Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify InsertHistory #1380

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 29 additions & 79 deletions src/main/java/de/neemann/digital/gui/InsertHistory.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<InsertAction> actionsLRU;
private final IdentityHashMap<InsertAction, JComponent> components;
private final ElementLibrary library;
private final ArrayList<WrapperAction> wrappers;
private int mainTime;
private InsertAction lastInsertAction;

/**
* Creates a new instance
Expand All @@ -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
Expand All @@ -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<WrapperAction> it = wrappers.iterator();
Iterator<InsertAction> 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));
}
}
}