1010import org .quiltmc .enigma .api .source .TokenType ;
1111import org .quiltmc .enigma .api .translation .representation .entry .Entry ;
1212
13- import javax .annotation .Nullable ;
1413import javax .swing .JButton ;
1514import javax .swing .JComboBox ;
1615import javax .swing .JLabel ;
1716import javax .swing .JPanel ;
1817import java .awt .Color ;
1918import java .awt .event .ItemEvent ;
2019import java .util .ArrayList ;
20+ import java .util .Collection ;
2121import java .util .Collections ;
2222import java .util .HashMap ;
23+ import java .util .LinkedHashMap ;
24+ import java .util .LinkedHashSet ;
2325import java .util .List ;
2426import java .util .Map ;
27+ import java .util .Set ;
2528
2629/**
2730 * A panel with buttons to navigate to the next and previous items in its entry collection.
@@ -31,7 +34,8 @@ public class NavigatorPanel extends JPanel {
3134
3235 private final Gui gui ;
3336 private final JLabel statsLabel ;
34- private final Map <TokenType , List <Entry <?>>> entries = new HashMap <>();
37+ private final Set <Entry <?>> allEntries = new LinkedHashSet <>();
38+ private final Map <TokenType , Map <Entry <?>, Integer >> entryIndexesByType = new HashMap <>();
3539
3640 private int currentIndex = 0 ;
3741 private TokenType selectedType ;
@@ -54,9 +58,7 @@ public NavigatorPanel(Gui gui) {
5458 });
5559 this .selectedType = TokenType .OBFUSCATED ;
5660
57- for (TokenType type : SUPPORTED_TOKEN_TYPES ) {
58- this .entries .put (type , new ArrayList <>());
59- }
61+ this .initEntryIndexesByType ();
6062
6163 JButton up = new JButton (GuiUtil .getUpChevron ());
6264 up .addActionListener (event -> this .navigateUp ());
@@ -72,6 +74,12 @@ public NavigatorPanel(Gui gui) {
7274 this .setBackground (new Color (0 , 0 , 0 , 0 ));
7375 }
7476
77+ private void initEntryIndexesByType () {
78+ for (TokenType type : SUPPORTED_TOKEN_TYPES ) {
79+ this .entryIndexesByType .put (type , new LinkedHashMap <>());
80+ }
81+ }
82+
7583 /**
7684 * Navigates to the next entry matching the current filter.
7785 */
@@ -92,10 +100,10 @@ private void onTypeChange() {
92100 }
93101
94102 private void wrapIndex () {
95- List < Entry <?>> currentEntrySet = this .entries .get (this .selectedType );
103+ final int selectedEntryTypeCount = this .entryIndexesByType .get (this .selectedType ). size ( );
96104 if (this .currentIndex < 0 ) {
97- this .currentIndex = currentEntrySet . size () - 1 ;
98- } else if (this .currentIndex >= currentEntrySet . size () ) {
105+ this .currentIndex = selectedEntryTypeCount - 1 ;
106+ } else if (this .currentIndex >= selectedEntryTypeCount ) {
99107 this .currentIndex = 0 ;
100108 }
101109 }
@@ -105,16 +113,16 @@ public void decrementIndex() {
105113 }
106114
107115 private void tryNavigate (boolean reverse ) {
108- List <Entry <?>> currentEntrySet = this .entries .get (this .selectedType );
109- if (!currentEntrySet .isEmpty ()) {
110- Entry <?> entry = this .getClosestEntryToCursor (currentEntrySet , reverse );
116+ Map <Entry <?>, Integer > selectedEntryIndexes = this .entryIndexesByType .get (this .selectedType );
117+ if (!selectedEntryIndexes .isEmpty ()) {
118+ Entry <?> entry = this .getClosestEntryToCursor (selectedEntryIndexes . keySet () , reverse );
111119 this .gui .getController ().navigateTo (entry );
112- this .currentIndex = currentEntrySet . indexOf (entry );
120+ this .currentIndex = selectedEntryIndexes . get (entry );
113121 this .updateStatsLabel ();
114122 }
115123 }
116124
117- public Entry <?> getClosestEntryToCursor (List <Entry <?>> currentEntrySet , boolean reverse ) {
125+ public Entry <?> getClosestEntryToCursor (Collection <Entry <?>> currentEntrySet , boolean reverse ) {
118126 List <Entry <?>> possibleEntriesCopy = new ArrayList <>(currentEntrySet );
119127 if (reverse ) {
120128 Collections .reverse (possibleEntriesCopy );
@@ -134,54 +142,40 @@ public Entry<?> getClosestEntryToCursor(List<Entry<?>> currentEntrySet, boolean
134142 return possibleEntriesCopy .get (0 );
135143 }
136144
137- /**
138- * Adds the provided entry to this navigator's pool and sorts it.
139- * @param entry the entry to add
140- */
141- public void addEntry (@ Nullable Entry <?> entry ) {
142- EnigmaProject project = this .gui .getController ().getProject ();
143- if (entry != null && this .gui .isEditable (EditableType .fromEntry (entry )) && project .isRenamable (entry ) && project .isNavigable (entry )) {
144- TokenType tokenType = this .getTokenType (entry );
145- List <Entry <?>> entries = this .entries .get (tokenType );
145+ public void resetEntries (Iterable <Entry <?>> newEntries ) {
146+ this .allEntries .clear ();
147+ this .initEntryIndexesByType ();
146148
147- if (!entries .contains (entry )) {
148- entries .add (entry );
149- this .updateStatsLabel ();
149+ EnigmaProject project = this .gui .getController ().getProject ();
150+ for (Entry <?> entry : newEntries ) {
151+ if (entry != null && this .gui .isEditable (EditableType .fromEntry (entry )) && project .isRenamable (entry ) && project .isNavigable (entry )) {
152+ if (!this .allEntries .contains (entry )) {
153+ Map <Entry <?>, Integer > entryIndexesOfType = this .entryIndexesByType .get (this .getTokenType (entry ));
154+ if (entryIndexesOfType != null ) {
155+ this .allEntries .add (entry );
156+ entryIndexesOfType .put (entry , entryIndexesOfType .size ());
157+ }
158+ }
150159 }
151160 }
161+
162+ this .updateStatsLabel ();
152163 }
153164
154165 /**
155166 * Rechecks and updates all token types.
156- * @see #updateTokenType(Entry)
157167 */
158168 public void updateAllTokenTypes () {
159- for (var list : this .entries .values ()) {
160- var copy = new ArrayList <>(list );
169+ this .initEntryIndexesByType ();
161170
162- for (var target : copy ) {
163- this .updateTokenType (target );
171+ for (Entry <?> entry : this .allEntries ) {
172+ Map <Entry <?>, Integer > entryIndexesOfType = this .entryIndexesByType .get (this .getTokenType (entry ));
173+ if (entryIndexesOfType != null ) {
174+ entryIndexesOfType .put (entry , entryIndexesOfType .size ());
164175 }
165176 }
166177 }
167178
168- /**
169- * Checks if the entry should be moved to a different token type, and updates it if so.
170- * Assumes that the entry's old token type matches the currently selected token type.
171- * @param target the entry to check
172- */
173- public void updateTokenType (Entry <?> target ) {
174- TokenType tokenType = this .getTokenType (target );
175- for (var entry : this .entries .entrySet ()) {
176- if (entry .getValue () != null && entry .getValue ().remove (target )) {
177- break ;
178- }
179- }
180-
181- this .entries .get (tokenType ).add (target );
182- this .updateStatsLabel ();
183- }
184-
185179 private TokenType getTokenType (Entry <?> target ) {
186180 // make sure we're checking from the root of the inheritance tree
187181 EnigmaProject project = this .gui .getController ().getProject ();
@@ -191,8 +185,13 @@ private TokenType getTokenType(Entry<?> target) {
191185 }
192186
193187 private void updateStatsLabel () {
194- int index = this .entries .get (this .selectedType ).isEmpty () ? 0 : this .currentIndex + 1 ;
195- String indexString = String .valueOf (index ).length () == 1 ? "0" + index : String .valueOf (index );
196- this .statsLabel .setText (indexString + "/" + this .entries .get (this .selectedType ).size ());
188+ final Map <Entry <?>, Integer > entryIndexesOfType = this .entryIndexesByType .get (this .selectedType );
189+ final String index = String .valueOf (entryIndexesOfType .isEmpty () ? 0 : this .currentIndex + 1 );
190+ final String total = String .valueOf (entryIndexesOfType .size ());
191+
192+ final int lengthDiff = total .length () - index .length ();
193+ final String paddedIndex = lengthDiff == 0 ? index : "0" .repeat (lengthDiff ) + index ;
194+
195+ this .statsLabel .setText (paddedIndex + "/" + total );
197196 }
198197}
0 commit comments