1010import de .neemann .digital .draw .library .LibraryNode ;
1111
1212import javax .swing .*;
13- import java .awt .event .ActionEvent ;
1413import java .util .ArrayList ;
14+ import java .util .IdentityHashMap ;
1515import java .util .Iterator ;
1616
1717/**
1818 * The InsertHistory puts the most frequently used elements to the toolbar of the main window.
19- * So its easier to build circuits.
19+ * So it's easier to build circuits.
2020 */
2121public class InsertHistory implements LibraryListener {
2222 private static final int MAX_ICONS = 6 ;
2323 private final JToolBar bar ;
24+ private final ArrayList <InsertAction > actionsLRU ;
25+ private final IdentityHashMap <InsertAction , JComponent > components ;
2426 private final ElementLibrary library ;
25- private final ArrayList <WrapperAction > wrappers ;
26- private int mainTime ;
27- private InsertAction lastInsertAction ;
2827
2928 /**
3029 * Creates a new instance
@@ -35,63 +34,38 @@ public class InsertHistory implements LibraryListener {
3534 public InsertHistory (JToolBar bar , ElementLibrary library ) {
3635 this .bar = bar ;
3736 this .library = library ;
38- wrappers = new ArrayList <>();
37+ actionsLRU = new ArrayList <>();
38+ components = new IdentityHashMap <>();
3939 }
4040
4141 /**
4242 * Add an action to the toolbar.
43- * The given action is wrapped by an action which counts the usage .
44- * So its possible to remove the item which is not used the longest time when the toolbar becomes to large .
43+ * The history of actions is kept in the least-recently-used (LRU) order .
44+ * When the toolbar becomes too large, the oldest (LRU) action is removed .
4545 *
4646 * @param action the action
4747 */
4848 public void add (InsertAction action ) {
49- lastInsertAction = action ;
50- if (!contains (action )) {
51- WrapperAction wrapper = new WrapperAction (action , bar .getComponentCount ());
52- wrappers .add (wrapper );
53- bar .add (wrapper ).setToolTipText (action .getNode ().getToolTipText ());
54- if (wrappers .size () > MAX_ICONS ) {
55- int oldest = findOldestIndex ();
56- removeWrapperFromToolBar (wrappers .get (oldest ));
57- wrappers .remove (oldest );
49+ if (!actionsLRU .contains (action )) {
50+ if (actionsLRU .size () >= MAX_ICONS ) {
51+ InsertAction oldest = actionsLRU .get (0 );
52+ bar .remove (components .get (oldest ));
53+ components .remove (oldest );
54+ actionsLRU .remove (0 );
5855 }
56+ components .put (action , bar .add (action ));
57+ } else {
58+ actionsLRU .remove (action );
5959 }
60- }
61-
62- private void removeWrapperFromToolBar (WrapperAction wrapper ) {
63- final int position = wrapper .componentPosition ;
64- bar .remove (position );
65- for (WrapperAction w : wrappers )
66- if (w .componentPosition > position )
67- w .componentPosition --;
68- }
69-
70- private int findOldestIndex () {
71- int found = -1 ;
72- int oldestTime = mainTime ;
73- for (int i = 0 ; i < wrappers .size (); i ++) {
74- WrapperAction wrapper = wrappers .get (i );
75- if (wrapper .time < oldestTime ) {
76- found = i ;
77- oldestTime = wrapper .time ;
78- }
79- }
80- return found ;
81- }
82-
83- private boolean contains (InsertAction action ) {
84- for (WrapperAction wrapper : wrappers )
85- if (wrapper .action .getName ().equals (action .getName ()))
86- return true ;
87- return false ;
60+ actionsLRU .add (action );
8861 }
8962
9063 /**
9164 * @return the last insert action
9265 */
9366 public InsertAction getLastInsertAction () {
94- return lastInsertAction ;
67+ if (!actionsLRU .isEmpty ()) return actionsLRU .get (actionsLRU .size () - 1 );
68+ return null ;
9569 }
9670
9771 @ Override
@@ -104,42 +78,17 @@ public void libraryChanged(LibraryNode node) {
10478 * If the component no longer exists, it is deleted from the history toolbar.
10579 */
10680 private void updateCustomComponents () {
107- Iterator <WrapperAction > it = wrappers .iterator ();
81+ Iterator <InsertAction > it = actionsLRU .iterator ();
10882 while (it .hasNext ()) {
109- WrapperAction w = it .next ();
110- if (w .action .isCustom ()) {
111- LibraryNode n = library .getElementNodeOrNull (w .action .getName ());
112- if (n == null ) { // is'nt there, so delete
113- removeWrapperFromToolBar (w );
114- it .remove ();
115- } else
116- w .update (n );
83+ InsertAction a = it .next ();
84+ if (a .isCustom ()) {
85+ LibraryNode n = library .getElementNodeOrNull (a .getName ());
86+ if (n == null ) { // isn't there, so delete
87+ components .remove (a ); // removes from components
88+ it .remove (); // removes from actionsLRU
89+ } else a .update (n );
11790 }
11891 }
11992 bar .revalidate ();
12093 }
121-
122- private final class WrapperAction extends AbstractAction {
123- private final InsertAction action ;
124- private int componentPosition ;
125- private int time ;
126-
127- private WrapperAction (InsertAction action , int componentPosition ) {
128- super (action .getValue (Action .NAME ).toString (), (Icon ) action .getValue (Action .SMALL_ICON ));
129- this .action = action ;
130- this .componentPosition = componentPosition ;
131- time = mainTime ++;
132- }
133-
134- @ Override
135- public void actionPerformed (ActionEvent e ) {
136- action .actionPerformed (e );
137- time = mainTime ++;
138- }
139-
140- public void update (LibraryNode n ) {
141- action .update (n );
142- putValue (Action .SMALL_ICON , action .getValue (Action .SMALL_ICON ));
143- }
144- }
14594}
0 commit comments