fixed some element library event handling issues

This commit is contained in:
hneemann 2017-03-27 09:05:24 +02:00
parent cb720e532d
commit 83a97053d4
9 changed files with 120 additions and 48 deletions

View File

@ -64,6 +64,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
*/ */
public ElementLibrary() { public ElementLibrary() {
root = new LibraryNode(Lang.get("menu_elements")); root = new LibraryNode(Lang.get("menu_elements"));
root.setLibrary(this);
LibraryNode node = new LibraryNode(Lang.get("lib_Logic")); LibraryNode node = new LibraryNode(Lang.get("lib_Logic"));
node.add(And.DESCRIPTION); node.add(And.DESCRIPTION);
@ -241,26 +242,38 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
private void rescanFolder() throws IOException { private void rescanFolder() throws IOException {
LOGGER.debug("rescan folder"); LOGGER.debug("rescan folder");
LibraryNode changedNode = null;
if (rootLibraryPath != null) { if (rootLibraryPath != null) {
if (customNode == null) { if (customNode == null) {
customNode = new LibraryNode(Lang.get("menu_custom")); customNode = new LibraryNode(Lang.get("menu_custom"));
root.add(customNode); root.add(customNode);
} else customNode.removeAll(); changedNode = root;
} else {
customNode.removeAll();
changedNode = customNode;
}
scanFolder(rootLibraryPath, customNode); scanFolder(rootLibraryPath, customNode);
} else if (customNode != null) { } else if (customNode != null) {
root.remove(customNode); root.remove(customNode);
customNode = null; customNode = null;
changedNode = root;
} }
populateNodeMap(); 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) for (LibraryListener l : listeners)
l.libraryChanged(); l.libraryChanged(node);
} }
private void scanFolder(File path, LibraryNode node) { private void scanFolder(File path, LibraryNode node) {

View File

@ -8,6 +8,8 @@ public interface LibraryListener {
/** /**
* called if library changes * called if library changes
*
* @param node the node that has changed. If null the tree structure has changed
*/ */
void libraryChanged(); void libraryChanged(LibraryNode node);
} }

View File

@ -21,6 +21,8 @@ public class LibraryNode implements Iterable<LibraryNode> {
private final DescriptionCreator creator; private final DescriptionCreator creator;
private ElementTypeDescription description; private ElementTypeDescription description;
private ImageIcon icon; private ImageIcon icon;
private ElementLibrary library;
private LibraryNode parent;
/** /**
* Creates a new node with the given name. * Creates a new node with the given name.
@ -70,6 +72,8 @@ public class LibraryNode implements Iterable<LibraryNode> {
*/ */
void add(LibraryNode node) { void add(LibraryNode node) {
children.add(node); children.add(node);
node.parent = this;
node.setLibrary(library);
} }
void add(ElementTypeDescription node) { void add(ElementTypeDescription node) {
@ -113,8 +117,10 @@ public class LibraryNode implements Iterable<LibraryNode> {
* @throws IOException IOException * @throws IOException IOException
*/ */
public ElementTypeDescription getDescription() throws IOException { public ElementTypeDescription getDescription() throws IOException {
if (description == null) if (description == null) {
description = creator.createDescription(); description = creator.createDescription();
library.fireLibraryChanged(this);
}
return description; return description;
} }
@ -227,4 +233,34 @@ public class LibraryNode implements Iterable<LibraryNode> {
public void remove(LibraryNode child) { public void remove(LibraryNode child) {
children.remove(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<Object> path = new ArrayList<>();
LibraryNode n = this;
while (n != null) {
path.add(0, n);
n = n.parent;
}
return path.toArray(new Object[path.size()]);
}
} }

View File

@ -1,5 +1,9 @@
package de.neemann.digital.gui; 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 javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.ArrayList; import java.util.ArrayList;
@ -11,7 +15,7 @@ import java.util.Iterator;
* *
* @author hneemann * @author hneemann
*/ */
public class InsertHistory { public class InsertHistory implements LibraryListener {
private static final int MAX_ICONS = 6; private static final int MAX_ICONS = 6;
private final JToolBar bar; private final JToolBar bar;
@ -21,11 +25,13 @@ public class InsertHistory {
/** /**
* Creates a new instance * Creates a new instance
* *
* @param library the library
* @param bar the toolbar to put the elements to * @param bar the toolbar to put the elements to
*/ */
public InsertHistory(JToolBar bar) { public InsertHistory(ElementLibrary library, JToolBar bar) {
this.bar = bar; this.bar = bar;
wrappers = new ArrayList<>(); wrappers = new ArrayList<>();
library.addListener(this);
} }
/** /**
@ -91,6 +97,11 @@ public class InsertHistory {
bar.revalidate(); bar.revalidate();
} }
@Override
public void libraryChanged(LibraryNode node) {
}
private final class WrapperAction extends AbstractAction { private final class WrapperAction extends AbstractAction {
private final InsertAction action; private final InsertAction action;
private int componentPosition; private int componentPosition;

View File

@ -52,20 +52,18 @@ public class LibrarySelector implements LibraryListener {
this.insertHistory = insertHistory; this.insertHistory = insertHistory;
this.circuitComponent = circuitComponent; this.circuitComponent = circuitComponent;
componentsMenu = new JMenu(Lang.get("menu_elements")); componentsMenu = new JMenu(Lang.get("menu_elements"));
libraryChanged(); libraryChanged(null);
return componentsMenu; return componentsMenu;
} }
@Override @Override
public void libraryChanged() { public void libraryChanged(LibraryNode node) {
componentsMenu.removeAll(); componentsMenu.removeAll();
for (LibraryNode n : library.getRoot()) for (LibraryNode n : library.getRoot())
addComponents(componentsMenu, n); addComponents(componentsMenu, n);
insertHistory.removeCustom();
if (library.getCustomNode() != null) { if (library.getCustomNode() != null) {
JMenuItem m = componentsMenu.getItem(componentsMenu.getItemCount() - 1); JMenuItem m = componentsMenu.getItem(componentsMenu.getItemCount() - 1);
if (m instanceof JMenu) { if (m instanceof JMenu) {

View File

@ -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.expression.ExpressionDialog;
import de.neemann.digital.gui.components.table.TableDialog; import de.neemann.digital.gui.components.table.TableDialog;
import de.neemann.digital.gui.components.testing.TestResultDialog; 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.components.tree.SelectTree;
import de.neemann.digital.gui.remote.DigitalHandler; import de.neemann.digital.gui.remote.DigitalHandler;
import de.neemann.digital.gui.remote.RemoteException; import de.neemann.digital.gui.remote.RemoteException;
@ -111,6 +112,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
private final ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1); private final ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1);
private final WindowPosManager windowPosManager = new WindowPosManager(); private final WindowPosManager windowPosManager = new WindowPosManager();
private final InsertHistory insertHistory; private final InsertHistory insertHistory;
private final boolean isParentsLibrary;
private File lastFilename; private File lastFilename;
private File filename; private File filename;
@ -126,6 +128,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
private RunModelState runModelState; private RunModelState runModelState;
private State runModelMicroState; private State runModelMicroState;
private JComponent componentOnPane; private JComponent componentOnPane;
private LibraryTreeModel treeModel;
private Main() { private Main() {
this(null, null, null, null); 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")); setIconImages(IconCreator.createImages("icon32.png", "icon64.png", "icon128.png"));
this.savedListener = savedListener; this.savedListener = savedListener;
if (parentsLibrary == null) library = new ElementLibrary(); isParentsLibrary = parentsLibrary != null;
else this.library = parentsLibrary; if (isParentsLibrary) this.library = parentsLibrary;
else library = new ElementLibrary();
shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES)); shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES));
fileHistory = new FileHistory(this); fileHistory = new FileHistory(this);
@ -195,15 +199,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
statusLabel = new JLabel(" "); statusLabel = new JLabel(" ");
getContentPane().add(statusLabel, BorderLayout.SOUTH); 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(); setupStates();
JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = new JMenuBar();
@ -227,8 +222,22 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
toolBar.addSeparator(); toolBar.addSeparator();
insertHistory = new InsertHistory(toolBar); insertHistory = new InsertHistory(library, toolBar);
menuBar.add(new LibrarySelector(library, shapeFactory).buildMenu(insertHistory, circuitComponent)); 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); getContentPane().add(toolBar, BorderLayout.NORTH);
@ -298,11 +307,16 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
getContentPane().remove(componentOnPane); getContentPane().remove(componentOnPane);
if (treeCheckBox.isSelected()) { if (treeCheckBox.isSelected()) {
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); 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); split.setRightComponent(circuitComponent);
getContentPane().add(split); getContentPane().add(split);
componentOnPane = split; componentOnPane = split;
} else { } else {
if (treeModel != null) {
library.removeListener(treeModel);
treeModel = null;
}
getContentPane().add(circuitComponent); getContentPane().add(circuitComponent);
componentOnPane = circuitComponent; componentOnPane = circuitComponent;
} }
@ -884,12 +898,11 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
private void loadFile(File filename, boolean toPrefs) { private void loadFile(File filename, boolean toPrefs) {
try { try {
library.setFilePath(filename.getParentFile()); setFilename(filename, toPrefs);
Circuit circ = Circuit.loadCircuit(filename, shapeFactory); Circuit circ = Circuit.loadCircuit(filename, shapeFactory);
circuitComponent.setCircuit(circ); circuitComponent.setCircuit(circ);
stoppedState.enter(); stoppedState.enter();
windowPosManager.closeAll(); windowPosManager.closeAll();
setFilename(filename, toPrefs);
statusLabel.setText(" "); statusLabel.setText(" ");
} catch (Exception e) { } catch (Exception e) {
circuitComponent.setCircuit(new Circuit()); circuitComponent.setCircuit(new Circuit());
@ -916,12 +929,12 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
this.filename = filename; this.filename = filename;
if (filename != null) { if (filename != null) {
this.lastFilename = filename; this.lastFilename = filename;
library.setFilePath(filename.getParentFile()); if (!isParentsLibrary) library.setFilePath(filename.getParentFile());
if (toPrefs) if (toPrefs)
fileHistory.add(filename); fileHistory.add(filename);
setTitle(filename + " - " + Lang.get("digital")); setTitle(filename + " - " + Lang.get("digital"));
} else { } else {
library.setFilePath(null); if (!isParentsLibrary) library.setFilePath(null);
setTitle(Lang.get("digital")); setTitle(Lang.get("digital"));
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -14,14 +14,17 @@ import java.util.ArrayList;
* TreeModel based on a {@link ElementLibrary} * TreeModel based on a {@link ElementLibrary}
* Created by hneemann on 25.03.17. * 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 LibraryNode root;
private final ElementLibrary library;
private final ArrayList<TreeModelListener> listeners = new ArrayList<>(); private final ArrayList<TreeModelListener> listeners = new ArrayList<>();
MyTreeModel(ElementLibrary library) { /**
* Creates a new library tree model
*
* @param library the library
*/
public LibraryTreeModel(ElementLibrary library) {
root = library.getRoot(); root = library.getRoot();
this.library = library;
library.addListener(this); library.addListener(this);
} }
@ -66,12 +69,9 @@ public class MyTreeModel implements TreeModel, LibraryListener {
} }
@Override @Override
public void libraryChanged() { public void libraryChanged(LibraryNode node) {
LibraryNode custom = library.getCustomNode(); final TreeModelEvent treeModelEvent = new TreeModelEvent(this, new TreePath(node.getPath()));
if (custom != null) { for (TreeModelListener l : listeners)
final TreeModelEvent treeModelEvent = new TreeModelEvent(this, new TreePath(new Object[]{root, custom})); l.treeStructureChanged(treeModelEvent);
for (TreeModelListener l : listeners)
l.treeStructureChanged(treeModelEvent);
}
} }
} }

View File

@ -2,7 +2,6 @@ package de.neemann.digital.gui.components.tree;
import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.draw.elements.VisualElement; 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.library.LibraryNode;
import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.InsertAction; import de.neemann.digital.gui.InsertAction;
@ -30,13 +29,13 @@ public class SelectTree extends JTree {
/** /**
* Create a new instance * 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 component the component to insert the components to
* @param shapeFactory the shape factory * @param shapeFactory the shape factory
* @param insertHistory the insert history * @param insertHistory the insert history
*/ */
public SelectTree(ElementLibrary library, CircuitComponent component, ShapeFactory shapeFactory, InsertHistory insertHistory) { public SelectTree(LibraryTreeModel model, CircuitComponent component, ShapeFactory shapeFactory, InsertHistory insertHistory) {
super(new MyTreeModel(library)); super(model);
this.shapeFactory = shapeFactory; this.shapeFactory = shapeFactory;
addMouseListener(new MouseAdapter() { addMouseListener(new MouseAdapter() {
@Override @Override

View File

@ -1,7 +1,6 @@
package de.neemann.digital.gui.components.tree; package de.neemann.digital.gui.components.tree;
import de.neemann.digital.draw.library.ElementLibrary; 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.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.InsertHistory; import de.neemann.digital.gui.InsertHistory;
import de.neemann.digital.gui.Main; import de.neemann.digital.gui.Main;
@ -31,13 +30,14 @@ public class SelectTreeDialog extends JDialog {
super(main, Lang.get("menu_elements"), false); super(main, Lang.get("menu_elements"), false);
setDefaultCloseOperation(DISPOSE_ON_CLOSE); 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)); getContentPane().add(new JScrollPane(tree));
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosed(WindowEvent windowEvent) { public void windowClosed(WindowEvent windowEvent) {
library.removeListener((LibraryListener) tree.getModel()); library.removeListener(model);
} }
}); });