diff --git a/src/main/java/de/neemann/digital/gui/InsertHistory.java b/src/main/java/de/neemann/digital/gui/InsertHistory.java index d507ee4fd..54d5aa535 100644 --- a/src/main/java/de/neemann/digital/gui/InsertHistory.java +++ b/src/main/java/de/neemann/digital/gui/InsertHistory.java @@ -10,21 +10,20 @@ import de.neemann.digital.draw.library.LibraryNode; import javax.swing.*; -import java.awt.event.ActionEvent; import java.util.ArrayList; +import java.util.IdentityHashMap; import java.util.Iterator; /** * The InsertHistory puts the most frequently used elements to the toolbar of the main window. - * So its easier to build circuits. + * So it's easier to build circuits. */ public class InsertHistory implements LibraryListener { private static final int MAX_ICONS = 6; private final JToolBar bar; + private final ArrayList actionsLRU; + private final IdentityHashMap components; private final ElementLibrary library; - private final ArrayList wrappers; - private int mainTime; - private InsertAction lastInsertAction; /** * Creates a new instance @@ -35,63 +34,38 @@ public class InsertHistory implements LibraryListener { public InsertHistory(JToolBar bar, ElementLibrary library) { this.bar = bar; this.library = library; - wrappers = new ArrayList<>(); + actionsLRU = new ArrayList<>(); + components = new IdentityHashMap<>(); } /** * Add an action to the toolbar. - * The given action is wrapped by an action which counts the usage. - * So its possible to remove the item which is not used the longest time when the toolbar becomes to large. + * The history of actions is kept in the least-recently-used (LRU) order. + * When the toolbar becomes too large, the oldest (LRU) action is removed. * * @param action the action */ public void add(InsertAction action) { - lastInsertAction = action; - if (!contains(action)) { - WrapperAction wrapper = new WrapperAction(action, bar.getComponentCount()); - wrappers.add(wrapper); - bar.add(wrapper).setToolTipText(action.getNode().getToolTipText()); - if (wrappers.size() > MAX_ICONS) { - int oldest = findOldestIndex(); - removeWrapperFromToolBar(wrappers.get(oldest)); - wrappers.remove(oldest); + if (!actionsLRU.contains(action)) { + if (actionsLRU.size() >= MAX_ICONS) { + InsertAction oldest = actionsLRU.get(0); + bar.remove(components.get(oldest)); + components.remove(oldest); + actionsLRU.remove(0); } + components.put(action, bar.add(action)); + } else { + actionsLRU.remove(action); } - } - - private void removeWrapperFromToolBar(WrapperAction wrapper) { - final int position = wrapper.componentPosition; - bar.remove(position); - for (WrapperAction w : wrappers) - if (w.componentPosition > position) - w.componentPosition--; - } - - private int findOldestIndex() { - int found = -1; - int oldestTime = mainTime; - for (int i = 0; i < wrappers.size(); i++) { - WrapperAction wrapper = wrappers.get(i); - if (wrapper.time < oldestTime) { - found = i; - oldestTime = wrapper.time; - } - } - return found; - } - - private boolean contains(InsertAction action) { - for (WrapperAction wrapper : wrappers) - if (wrapper.action.getName().equals(action.getName())) - return true; - return false; + actionsLRU.add(action); } /** * @return the last insert action */ public InsertAction getLastInsertAction() { - return lastInsertAction; + if (!actionsLRU.isEmpty()) return actionsLRU.get(actionsLRU.size() - 1); + return null; } @Override @@ -104,42 +78,18 @@ public void libraryChanged(LibraryNode node) { * If the component no longer exists, it is deleted from the history toolbar. */ private void updateCustomComponents() { - Iterator it = wrappers.iterator(); + Iterator it = actionsLRU.iterator(); while (it.hasNext()) { - WrapperAction w = it.next(); - if (w.action.isCustom()) { - LibraryNode n = library.getElementNodeOrNull(w.action.getName()); - if (n == null) { // is'nt there, so delete - removeWrapperFromToolBar(w); - it.remove(); - } else - w.update(n); + InsertAction a = it.next(); + if (a.isCustom()) { + LibraryNode n = library.getElementNodeOrNull(a.getName()); + if (n == null) { // isn't there, so delete + bar.remove(components.get(a)); // removes from the toolbar + components.remove(a); // removes from components + it.remove(); // removes from actionsLRU + } else a.update(n); } } bar.revalidate(); } - - private final class WrapperAction extends AbstractAction { - private final InsertAction action; - private int componentPosition; - private int time; - - private WrapperAction(InsertAction action, int componentPosition) { - super(action.getValue(Action.NAME).toString(), (Icon) action.getValue(Action.SMALL_ICON)); - this.action = action; - this.componentPosition = componentPosition; - time = mainTime++; - } - - @Override - public void actionPerformed(ActionEvent e) { - action.actionPerformed(e); - time = mainTime++; - } - - public void update(LibraryNode n) { - action.update(n); - putValue(Action.SMALL_ICON, action.getValue(Action.SMALL_ICON)); - } - } }