From 83a97053d4cfad035c67c362cda801329bcc2b0a Mon Sep 17 00:00:00 2001 From: hneemann Date: Mon, 27 Mar 2017 09:05:24 +0200 Subject: [PATCH] fixed some element library event handling issues --- .../digital/draw/library/ElementLibrary.java | 21 ++++++-- .../digital/draw/library/LibraryListener.java | 4 +- .../digital/draw/library/LibraryNode.java | 38 +++++++++++++- .../de/neemann/digital/gui/InsertHistory.java | 15 +++++- .../neemann/digital/gui/LibrarySelector.java | 6 +-- .../java/de/neemann/digital/gui/Main.java | 49 ++++++++++++------- ...MyTreeModel.java => LibraryTreeModel.java} | 22 ++++----- .../gui/components/tree/SelectTree.java | 7 ++- .../gui/components/tree/SelectTreeDialog.java | 6 +-- 9 files changed, 120 insertions(+), 48 deletions(-) rename src/main/java/de/neemann/digital/gui/components/tree/{MyTreeModel.java => LibraryTreeModel.java} (74%) 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 0fbb5dcbc..9af377031 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -64,6 +64,7 @@ public class ElementLibrary implements Iterable */ public ElementLibrary() { root = new LibraryNode(Lang.get("menu_elements")); + root.setLibrary(this); LibraryNode node = new LibraryNode(Lang.get("lib_Logic")); node.add(And.DESCRIPTION); @@ -241,26 +242,38 @@ public class ElementLibrary implements Iterable private void rescanFolder() throws IOException { LOGGER.debug("rescan folder"); + LibraryNode changedNode = null; if (rootLibraryPath != null) { if (customNode == null) { customNode = new LibraryNode(Lang.get("menu_custom")); root.add(customNode); - } else customNode.removeAll(); + changedNode = root; + } else { + customNode.removeAll(); + changedNode = customNode; + } scanFolder(rootLibraryPath, customNode); } else if (customNode != null) { root.remove(customNode); customNode = null; + changedNode = root; } populateNodeMap(); - fireLibraryChanged(); + if (changedNode != null) + fireLibraryChanged(changedNode); } - private void fireLibraryChanged() { + /** + * Fires a library event + * + * @param node the node changed + */ + public void fireLibraryChanged(LibraryNode node) { for (LibraryListener l : listeners) - l.libraryChanged(); + l.libraryChanged(node); } private void scanFolder(File path, LibraryNode node) { diff --git a/src/main/java/de/neemann/digital/draw/library/LibraryListener.java b/src/main/java/de/neemann/digital/draw/library/LibraryListener.java index 8ad5e2aad..047e39b6e 100644 --- a/src/main/java/de/neemann/digital/draw/library/LibraryListener.java +++ b/src/main/java/de/neemann/digital/draw/library/LibraryListener.java @@ -8,6 +8,8 @@ public interface LibraryListener { /** * called if library changes + * + * @param node the node that has changed. If null the tree structure has changed */ - void libraryChanged(); + void libraryChanged(LibraryNode node); } 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 bb4aca1db..2f8a658d1 100644 --- a/src/main/java/de/neemann/digital/draw/library/LibraryNode.java +++ b/src/main/java/de/neemann/digital/draw/library/LibraryNode.java @@ -21,6 +21,8 @@ public class LibraryNode implements Iterable { private final DescriptionCreator creator; private ElementTypeDescription description; private ImageIcon icon; + private ElementLibrary library; + private LibraryNode parent; /** * Creates a new node with the given name. @@ -70,6 +72,8 @@ public class LibraryNode implements Iterable { */ void add(LibraryNode node) { children.add(node); + node.parent = this; + node.setLibrary(library); } void add(ElementTypeDescription node) { @@ -113,8 +117,10 @@ public class LibraryNode implements Iterable { * @throws IOException IOException */ public ElementTypeDescription getDescription() throws IOException { - if (description == null) + if (description == null) { description = creator.createDescription(); + library.fireLibraryChanged(this); + } return description; } @@ -227,4 +233,34 @@ public class LibraryNode implements Iterable { public void remove(LibraryNode child) { children.remove(child); } + + /** + * Sets the library this node belongs to + * + * @param library the library + */ + public void setLibrary(ElementLibrary library) { + if (this.library != library) { + this.library = library; + if (children != null) + for (LibraryNode c : children) + c.setLibrary(library); + } + } + + /** + * returns the tree path + * + * @return the path + */ + public Object[] getPath() { + ArrayList path = new ArrayList<>(); + LibraryNode n = this; + while (n != null) { + path.add(0, n); + n = n.parent; + } + return path.toArray(new Object[path.size()]); + } + } diff --git a/src/main/java/de/neemann/digital/gui/InsertHistory.java b/src/main/java/de/neemann/digital/gui/InsertHistory.java index e49374874..fe8bc8073 100644 --- a/src/main/java/de/neemann/digital/gui/InsertHistory.java +++ b/src/main/java/de/neemann/digital/gui/InsertHistory.java @@ -1,5 +1,9 @@ package de.neemann.digital.gui; +import de.neemann.digital.draw.library.ElementLibrary; +import de.neemann.digital.draw.library.LibraryListener; +import de.neemann.digital.draw.library.LibraryNode; + import javax.swing.*; import java.awt.event.ActionEvent; import java.util.ArrayList; @@ -11,7 +15,7 @@ import java.util.Iterator; * * @author hneemann */ -public class InsertHistory { +public class InsertHistory implements LibraryListener { private static final int MAX_ICONS = 6; private final JToolBar bar; @@ -21,11 +25,13 @@ public class InsertHistory { /** * Creates a new instance * + * @param library the library * @param bar the toolbar to put the elements to */ - public InsertHistory(JToolBar bar) { + public InsertHistory(ElementLibrary library, JToolBar bar) { this.bar = bar; wrappers = new ArrayList<>(); + library.addListener(this); } /** @@ -91,6 +97,11 @@ public class InsertHistory { bar.revalidate(); } + @Override + public void libraryChanged(LibraryNode node) { + + } + private final class WrapperAction extends AbstractAction { private final InsertAction action; private int componentPosition; diff --git a/src/main/java/de/neemann/digital/gui/LibrarySelector.java b/src/main/java/de/neemann/digital/gui/LibrarySelector.java index 7fb0c0cdf..29e8179a1 100644 --- a/src/main/java/de/neemann/digital/gui/LibrarySelector.java +++ b/src/main/java/de/neemann/digital/gui/LibrarySelector.java @@ -52,20 +52,18 @@ public class LibrarySelector implements LibraryListener { this.insertHistory = insertHistory; this.circuitComponent = circuitComponent; componentsMenu = new JMenu(Lang.get("menu_elements")); - libraryChanged(); + libraryChanged(null); return componentsMenu; } @Override - public void libraryChanged() { + public void libraryChanged(LibraryNode node) { componentsMenu.removeAll(); for (LibraryNode n : library.getRoot()) addComponents(componentsMenu, n); - insertHistory.removeCustom(); - if (library.getCustomNode() != null) { JMenuItem m = componentsMenu.getItem(componentsMenu.getItemCount() - 1); if (m instanceof JMenu) { diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index ab083a81f..42ac42715 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -25,6 +25,7 @@ import de.neemann.digital.gui.components.data.DataSetDialog; import de.neemann.digital.gui.components.expression.ExpressionDialog; import de.neemann.digital.gui.components.table.TableDialog; import de.neemann.digital.gui.components.testing.TestResultDialog; +import de.neemann.digital.gui.components.tree.LibraryTreeModel; import de.neemann.digital.gui.components.tree.SelectTree; import de.neemann.digital.gui.remote.DigitalHandler; import de.neemann.digital.gui.remote.RemoteException; @@ -111,6 +112,7 @@ 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 isParentsLibrary; private File lastFilename; private File filename; @@ -126,6 +128,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E private RunModelState runModelState; private State runModelMicroState; private JComponent componentOnPane; + private LibraryTreeModel treeModel; private Main() { this(null, null, null, null); @@ -166,8 +169,9 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E setIconImages(IconCreator.createImages("icon32.png", "icon64.png", "icon128.png")); this.savedListener = savedListener; - if (parentsLibrary == null) library = new ElementLibrary(); - else this.library = parentsLibrary; + isParentsLibrary = parentsLibrary != null; + if (isParentsLibrary) this.library = parentsLibrary; + else library = new ElementLibrary(); shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES)); fileHistory = new FileHistory(this); @@ -195,15 +199,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E statusLabel = new JLabel(" "); getContentPane().add(statusLabel, BorderLayout.SOUTH); - addWindowListener(new ClosingWindowListener(this, this)); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - clearModelDescription(); // stop model timer if running - timerExecuter.shutdown(); - } - }); - setupStates(); JMenuBar menuBar = new JMenuBar(); @@ -227,8 +222,22 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E toolBar.addSeparator(); - insertHistory = new InsertHistory(toolBar); - menuBar.add(new LibrarySelector(library, shapeFactory).buildMenu(insertHistory, circuitComponent)); + insertHistory = new InsertHistory(library, toolBar); + final LibrarySelector librarySelector = new LibrarySelector(library, shapeFactory); + menuBar.add(librarySelector.buildMenu(insertHistory, circuitComponent)); + + addWindowListener(new ClosingWindowListener(this, this)); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + clearModelDescription(); // stop model timer if running + timerExecuter.shutdown(); + library.removeListener(librarySelector); + library.removeListener(insertHistory); + if (treeModel != null) + library.removeListener(treeModel); + } + }); getContentPane().add(toolBar, BorderLayout.NORTH); @@ -298,11 +307,16 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E getContentPane().remove(componentOnPane); if (treeCheckBox.isSelected()) { JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - split.setLeftComponent(new JScrollPane(new SelectTree(library, circuitComponent, shapeFactory, insertHistory))); + treeModel = new LibraryTreeModel(library); + split.setLeftComponent(new JScrollPane(new SelectTree(treeModel, circuitComponent, shapeFactory, insertHistory))); split.setRightComponent(circuitComponent); getContentPane().add(split); componentOnPane = split; } else { + if (treeModel != null) { + library.removeListener(treeModel); + treeModel = null; + } getContentPane().add(circuitComponent); componentOnPane = circuitComponent; } @@ -884,12 +898,11 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E private void loadFile(File filename, boolean toPrefs) { try { - library.setFilePath(filename.getParentFile()); + setFilename(filename, toPrefs); Circuit circ = Circuit.loadCircuit(filename, shapeFactory); circuitComponent.setCircuit(circ); stoppedState.enter(); windowPosManager.closeAll(); - setFilename(filename, toPrefs); statusLabel.setText(" "); } catch (Exception e) { circuitComponent.setCircuit(new Circuit()); @@ -916,12 +929,12 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E this.filename = filename; if (filename != null) { this.lastFilename = filename; - library.setFilePath(filename.getParentFile()); + if (!isParentsLibrary) library.setFilePath(filename.getParentFile()); if (toPrefs) fileHistory.add(filename); setTitle(filename + " - " + Lang.get("digital")); } else { - library.setFilePath(null); + if (!isParentsLibrary) library.setFilePath(null); setTitle(Lang.get("digital")); } } catch (IOException e) { diff --git a/src/main/java/de/neemann/digital/gui/components/tree/MyTreeModel.java b/src/main/java/de/neemann/digital/gui/components/tree/LibraryTreeModel.java similarity index 74% rename from src/main/java/de/neemann/digital/gui/components/tree/MyTreeModel.java rename to src/main/java/de/neemann/digital/gui/components/tree/LibraryTreeModel.java index b9919bb96..69e807540 100644 --- a/src/main/java/de/neemann/digital/gui/components/tree/MyTreeModel.java +++ b/src/main/java/de/neemann/digital/gui/components/tree/LibraryTreeModel.java @@ -14,14 +14,17 @@ import java.util.ArrayList; * TreeModel based on a {@link ElementLibrary} * Created by hneemann on 25.03.17. */ -public class MyTreeModel implements TreeModel, LibraryListener { +public class LibraryTreeModel implements TreeModel, LibraryListener { private final LibraryNode root; - private final ElementLibrary library; private final ArrayList listeners = new ArrayList<>(); - MyTreeModel(ElementLibrary library) { + /** + * Creates a new library tree model + * + * @param library the library + */ + public LibraryTreeModel(ElementLibrary library) { root = library.getRoot(); - this.library = library; library.addListener(this); } @@ -66,12 +69,9 @@ public class MyTreeModel implements TreeModel, LibraryListener { } @Override - public void libraryChanged() { - LibraryNode custom = library.getCustomNode(); - if (custom != null) { - final TreeModelEvent treeModelEvent = new TreeModelEvent(this, new TreePath(new Object[]{root, custom})); - for (TreeModelListener l : listeners) - l.treeStructureChanged(treeModelEvent); - } + public void libraryChanged(LibraryNode node) { + final TreeModelEvent treeModelEvent = new TreeModelEvent(this, new TreePath(node.getPath())); + for (TreeModelListener l : listeners) + l.treeStructureChanged(treeModelEvent); } } 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 d35469ad7..8239e20af 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 @@ -2,7 +2,6 @@ package de.neemann.digital.gui.components.tree; import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.draw.elements.VisualElement; -import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.LibraryNode; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.InsertAction; @@ -30,13 +29,13 @@ public class SelectTree extends JTree { /** * Create a new instance * - * @param library the library to use + * @param model the model to use * @param component the component to insert the components to * @param shapeFactory the shape factory * @param insertHistory the insert history */ - public SelectTree(ElementLibrary library, CircuitComponent component, ShapeFactory shapeFactory, InsertHistory insertHistory) { - super(new MyTreeModel(library)); + public SelectTree(LibraryTreeModel model, CircuitComponent component, ShapeFactory shapeFactory, InsertHistory insertHistory) { + super(model); this.shapeFactory = shapeFactory; addMouseListener(new MouseAdapter() { @Override diff --git a/src/main/java/de/neemann/digital/gui/components/tree/SelectTreeDialog.java b/src/main/java/de/neemann/digital/gui/components/tree/SelectTreeDialog.java index af13db482..63259e8bd 100644 --- a/src/main/java/de/neemann/digital/gui/components/tree/SelectTreeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/tree/SelectTreeDialog.java @@ -1,7 +1,6 @@ package de.neemann.digital.gui.components.tree; import de.neemann.digital.draw.library.ElementLibrary; -import de.neemann.digital.draw.library.LibraryListener; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.InsertHistory; import de.neemann.digital.gui.Main; @@ -31,13 +30,14 @@ public class SelectTreeDialog extends JDialog { super(main, Lang.get("menu_elements"), false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); - JTree tree = new SelectTree(library, component, shapeFactory, insertHistory); + LibraryTreeModel model = new LibraryTreeModel(library); + JTree tree = new SelectTree(model, component, shapeFactory, insertHistory); getContentPane().add(new JScrollPane(tree)); addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent windowEvent) { - library.removeListener((LibraryListener) tree.getModel()); + library.removeListener(model); } });