|
2 | 2 |
|
3 | 3 | import me.flame.menus.items.MenuItem;
|
4 | 4 | import me.flame.menus.menu.BaseMenu;
|
| 5 | +import me.flame.menus.menu.IterationDirection; |
5 | 6 | import me.flame.menus.menu.Slot;
|
| 7 | + |
6 | 8 | import org.jetbrains.annotations.NotNull;
|
7 | 9 | import org.jetbrains.annotations.Nullable;
|
8 | 10 |
|
|
19 | 21 | */
|
20 | 22 | @SuppressWarnings("unused")
|
21 | 23 | public final class MenuIterator implements Iterator<MenuItem> {
|
22 |
| - |
23 | 24 | @NotNull
|
24 |
| - private Slot currentPosition; |
| 25 | + private Slot position; |
25 | 26 |
|
26 | 27 | @NotNull
|
27 | 28 | private final IterationDirection direction;
|
28 | 29 |
|
| 30 | + |
29 | 31 | @NotNull
|
30 | 32 | private final BaseMenu<?> menu;
|
31 | 33 |
|
32 |
| - private final int menuRows; |
| 34 | + private Slot next; |
| 35 | + |
| 36 | + private boolean isFirst = true; |
| 37 | + |
| 38 | + private final int rows; |
| 39 | + |
| 40 | + private static final String NOTHING_MORE_NEXT = |
| 41 | + "Used PageIterator#next() but nothing more" + |
| 42 | + "\nFix: Use hasNext() beforehand to avoid this error."; |
| 43 | + |
| 44 | + private static final String NOTHING_MORE_NEXT_OPTIONAL = |
| 45 | + "Used PageIterator#nextOptional() but nothing more" + |
| 46 | + "\nFix: Use hasNext() beforehand to avoid this error."; |
| 47 | + |
| 48 | + private static final String NOTHING_MORE_NEXT_NOT_NULL = |
| 49 | + "Used PageIterator#nextNotNull() but nothing more"; |
| 50 | + |
| 51 | + private static final String GREATER_THAN_ONE_ONLY = |
| 52 | + "Starting row and column must be 1 or greater, col 9 and under or rows 6 and under only." + |
| 53 | + "\nFix: If you're using an algorithm for rows/cols, you might wanna check it"; |
33 | 54 |
|
34 | 55 | public MenuIterator(int startingRow, int startingCol,
|
35 | 56 | @NotNull IterationDirection direction,
|
36 | 57 | @NotNull BaseMenu<?> menu) {
|
37 |
| - if (startingRow < 1 || startingCol < 1) |
38 |
| - throw new IllegalArgumentException( |
39 |
| - "Starting row and column must be greater than 1 or equal. not under 0" + |
40 |
| - "\nFix: If you're using an algorithm for rows and/or cols, you might wanna check it." |
41 |
| - ); |
| 58 | + Slot prepos = new Slot(startingRow, startingCol); |
| 59 | + if (!prepos.isSlot()) throw new IllegalArgumentException(GREATER_THAN_ONE_ONLY); |
42 | 60 | this.menu = menu;
|
43 |
| - this.currentPosition = new Slot(startingRow, startingCol); |
| 61 | + this.position = prepos; |
44 | 62 | this.direction = direction;
|
45 |
| - this.menuRows = menu.getRows(); |
46 |
| - } |
47 | 63 |
|
48 |
| - public @Nullable Slot nextSlot(boolean emptyOnly) { |
49 |
| - if (!emptyOnly) { |
50 |
| - Slot newPos = direction.shift(currentPosition, this.menuRows); |
51 |
| - currentPosition = newPos; |
52 |
| - if (!currentPosition.isSlot()) { |
53 |
| - return null; |
54 |
| - } |
55 |
| - return newPos; |
56 |
| - } |
57 |
| - |
58 |
| - while (menu.hasItem(currentPosition)) { |
59 |
| - Slot shiftedPos = direction.shift(currentPosition, this.menuRows); |
| 64 | + this.rows = menu.getRows(); |
| 65 | + } |
| 66 | + public MenuIterator(@NotNull IterationDirection direction, |
| 67 | + @NotNull BaseMenu<?> menu) { |
| 68 | + this.menu = menu; |
| 69 | + this.position = Slot.FIRST.copy(); |
| 70 | + this.direction = direction; |
60 | 71 |
|
61 |
| - if (!shiftedPos.isSlot()) { |
62 |
| - return null; |
63 |
| - } |
| 72 | + this.rows = menu.getRows(); |
| 73 | + } |
64 | 74 |
|
65 |
| - currentPosition = shiftedPos; |
| 75 | + /** |
| 76 | + * Retrieves the next slot in the menu. |
| 77 | + * |
| 78 | + * @param emptyOnly a boolean indicating whether to retrieve only empty slots |
| 79 | + * @return the next empty slot in the menu, or null if no empty slot is found |
| 80 | + */ |
| 81 | + public Slot nextSlot(boolean emptyOnly) { |
| 82 | + if (!emptyOnly) return nextSlot(); |
| 83 | + |
| 84 | + while (true) { |
| 85 | + MenuItem item = menu.getItem(position); |
| 86 | + if (item == null) break; |
| 87 | + |
| 88 | + position = direction.shift(position, this.rows); |
| 89 | + if (!position.isSlot()) return null; |
66 | 90 | }
|
67 | 91 |
|
68 | 92 | // when it becomes empty
|
69 |
| - return currentPosition; |
| 93 | + return position; |
70 | 94 | }
|
71 | 95 |
|
| 96 | + /** |
| 97 | + * Retrieves the next slot in the menu. |
| 98 | + * @return the next empty slot in the menu, or null if no empty slot is found |
| 99 | + */ |
72 | 100 | public @Nullable Slot nextSlot() {
|
73 |
| - Slot newPos = direction.shift(currentPosition, this.menuRows); |
74 |
| - currentPosition = newPos; |
75 |
| - return !newPos.isSlot() ? null : newPos; |
| 101 | + if (!isFirst) { |
| 102 | + position = next; |
| 103 | + next = null; |
| 104 | + return position; |
| 105 | + } |
| 106 | + isFirst = false; |
| 107 | + return position; |
76 | 108 | }
|
77 | 109 |
|
78 | 110 | @Override
|
79 | 111 | public boolean hasNext() {
|
80 |
| - return currentPosition.isSlot(); |
| 112 | + if (next != null) return true; |
| 113 | + next = direction.shift(position, this.rows); |
| 114 | + return next.isSlot(); |
81 | 115 | }
|
82 | 116 |
|
83 | 117 | @Override
|
84 |
| - public @Nullable MenuItem next() { |
| 118 | + public MenuItem next() { |
85 | 119 | Slot slot = nextSlot();
|
86 |
| - if (slot == null) |
87 |
| - throw new NoSuchElementException("Used MenuIterator#next() but no more items to iterate over"); |
88 |
| - return menu.getItem(slot); |
| 120 | + if (slot != null) return menu.getItem(slot.getSlot()); |
| 121 | + throw new NoSuchElementException(NOTHING_MORE_NEXT); |
89 | 122 | }
|
90 | 123 |
|
91 |
| - public @NotNull MenuItem nextNotNull() { |
92 |
| - // don't be fooled, this is only 1 loop through the menu, not 1 AND recursion, only one happens. |
93 |
| - Slot slot = nextSlot(); |
94 |
| - if (slot == null) { |
95 |
| - while (hasNext()) { |
96 |
| - slot = nextSlot(); |
97 |
| - if (slot == null) continue; |
98 |
| - MenuItem item = menu.getItem(slot); |
99 |
| - if (item != null) { |
100 |
| - return item; |
101 |
| - } |
102 |
| - } |
103 |
| - |
104 |
| - throw new NoSuchElementException("Used MenuIterator#next() but no more items to iterate over"); |
| 124 | + /** |
| 125 | + * Retrieves the next non-null MenuItem in the menu. |
| 126 | + * |
| 127 | + * @return the next non-null MenuItem in the menu |
| 128 | + */ |
| 129 | + public MenuItem nextNotNull() { |
| 130 | + while (hasNext()) { |
| 131 | + Slot slot = nextSlot(); |
| 132 | + if (slot == null) |
| 133 | + throw new NoSuchElementException(NOTHING_MORE_NEXT_NOT_NULL + |
| 134 | + "\nFix: Everything after slot " + position.getSlot() + " is empty/null." |
| 135 | + ); |
| 136 | + |
| 137 | + MenuItem item = menu.getItem(slot.getSlot()); |
| 138 | + if (item != null) return item; |
105 | 139 | }
|
106 | 140 |
|
107 |
| - MenuItem item = menu.getItem(slot); |
108 |
| - if (item != null) { |
109 |
| - return item; |
110 |
| - } |
111 |
| - return nextNotNull(); |
| 141 | + throw new NoSuchElementException(NOTHING_MORE_NEXT_NOT_NULL + |
| 142 | + "\nFix: Everything after slot " + position.getSlot() + " is empty/null." |
| 143 | + ); |
112 | 144 | }
|
113 | 145 |
|
| 146 | + |
| 147 | + /** |
| 148 | + * Retrieves the next optional menu item. |
| 149 | + * |
| 150 | + * @return an Optional object containing the next MenuItem, if available. |
| 151 | + * Returns an empty Optional if the slot in the menu is empty. |
| 152 | + * Returns an empty Optional if there are no more items. |
| 153 | + * @throws NoSuchElementException if there are no more items in the menu. |
| 154 | + */ |
114 | 155 | public Optional<MenuItem> nextOptional() {
|
115 | 156 | Slot slot = nextSlot();
|
116 |
| - if (slot == null) |
117 |
| - throw new NoSuchElementException("Used MenuIterator#next() but no more items to iterate over"); |
118 |
| - return menu.get(slot); |
119 |
| - } |
120 |
| - |
121 |
| - public enum IterationDirection { |
122 |
| - HORIZONTAL() { |
123 |
| - @Override |
124 |
| - Slot shift(Slot oldPos, int maxRows) { |
125 |
| - |
126 |
| - int oldCol = oldPos.getColumn(); |
127 |
| - int oldRow = oldPos.getRow(); |
128 |
| - |
129 |
| - if (oldCol == 9 && oldRow < maxRows) { |
130 |
| - oldCol = 1; |
131 |
| - oldRow++; |
132 |
| - } else { |
133 |
| - oldCol++; |
134 |
| - } |
135 |
| - |
136 |
| - return new Slot(oldRow, oldCol); |
137 |
| - } |
138 |
| - }, |
139 |
| - |
140 |
| - VERTICAL() { |
141 |
| - @Override |
142 |
| - Slot shift(Slot oldPos, int maxRows) { |
143 |
| - int oldCol = oldPos.getColumn(); |
144 |
| - int oldRow = oldPos.getRow(); |
145 |
| - |
146 |
| - if (oldCol < 9 && oldRow == maxRows) { |
147 |
| - oldCol++; |
148 |
| - oldRow = 1; |
149 |
| - } else { |
150 |
| - oldRow++; |
151 |
| - } |
152 |
| - |
153 |
| - return new Slot(oldRow, oldCol); |
154 |
| - } |
155 |
| - }, |
156 |
| - |
157 |
| - UPWARDS_ONLY { |
158 |
| - |
159 |
| - @Override |
160 |
| - Slot shift(Slot oldPos, int maxRows) { |
161 |
| - int oldRow = oldPos.getRow(); |
162 |
| - int row = oldRow - 1; |
163 |
| - if (row < 1) { |
164 |
| - row = oldRow; |
165 |
| - } |
166 |
| - return new Slot(row, oldPos.getColumn()); |
167 |
| - } |
168 |
| - }, |
169 |
| - |
170 |
| - DOWNWARDS_ONLY { |
171 |
| - @Override |
172 |
| - Slot shift(Slot oldPos, int maxRows) { |
173 |
| - int oldRow = oldPos.getRow(); |
174 |
| - int row = oldRow + 1; |
175 |
| - if (row > maxRows) { |
176 |
| - row = oldRow; |
177 |
| - } |
178 |
| - return new Slot(row, oldPos.getColumn()); |
179 |
| - } |
180 |
| - }, |
181 |
| - |
182 |
| - RIGHT_ONLY { |
183 |
| - @Override |
184 |
| - Slot shift(Slot oldPos, int maxRows) { |
185 |
| - int oldCol = oldPos.getColumn() + 1; |
186 |
| - int col = oldCol > 9 ? oldCol - 1 : oldCol; |
187 |
| - return new Slot(oldPos.getRow(), col); |
188 |
| - } |
189 |
| - }, |
190 |
| - |
191 |
| - |
192 |
| - LEFT_ONLY { |
193 |
| - @Override |
194 |
| - Slot shift(Slot oldPos, int maxRows) { |
195 |
| - int oldCol = oldPos.getColumn() - 1; |
196 |
| - int col = oldCol < 1 ? oldCol + 1 : oldCol; |
197 |
| - return new Slot(oldPos.getRow(), col); |
198 |
| - } |
199 |
| - }, |
200 |
| - |
201 |
| - |
202 |
| - RIGHT_UPWARDS_ONLY { |
203 |
| - @Override |
204 |
| - Slot shift(Slot oldPos, int maxRows) { |
205 |
| - Slot upwardSlot = UPWARDS_ONLY.shift(oldPos, maxRows); |
206 |
| - int row = upwardSlot.getRow(); |
207 |
| - |
208 |
| - Slot rightSlot = RIGHT_ONLY.shift(oldPos, maxRows); |
209 |
| - int col = rightSlot.getColumn(); |
210 |
| - |
211 |
| - return new Slot(row, col); |
212 |
| - } |
213 |
| - }, |
214 |
| - |
215 |
| - |
216 |
| - RIGHT_DOWNWARDS_ONLY { |
217 |
| - @Override |
218 |
| - Slot shift(Slot oldPos, int maxRows) { |
219 |
| - Slot downwardSlot = DOWNWARDS_ONLY.shift(oldPos, maxRows); |
220 |
| - int row = downwardSlot.getRow(); |
221 |
| - |
222 |
| - Slot rightSlot = RIGHT_ONLY.shift(oldPos, maxRows); |
223 |
| - int col = rightSlot.getColumn(); |
224 |
| - |
225 |
| - return new Slot(row, col); |
226 |
| - } |
227 |
| - }, |
228 |
| - |
229 |
| - LEFT_UPWARDS { |
230 |
| - @Override |
231 |
| - Slot shift(Slot oldPos, int maxRows) { |
232 |
| - Slot upwardSlot = UPWARDS_ONLY.shift(oldPos, maxRows); |
233 |
| - int row = upwardSlot.getRow(); |
234 |
| - |
235 |
| - Slot leftSlot = LEFT_ONLY.shift(oldPos, maxRows); |
236 |
| - int col = leftSlot.getColumn(); |
237 |
| - |
238 |
| - return new Slot(row, col); |
239 |
| - } |
240 |
| - }, |
241 |
| - |
242 |
| - LEFT_DOWNWARDS { |
243 |
| - @Override |
244 |
| - Slot shift(Slot oldPos, int maxRows) { |
245 |
| - Slot downwardSlot = DOWNWARDS_ONLY.shift(oldPos, maxRows); |
246 |
| - int row = downwardSlot.getRow(); |
247 |
| - |
248 |
| - Slot leftSlot = LEFT_ONLY.shift(oldPos, maxRows); |
249 |
| - int col = leftSlot.getColumn(); |
250 |
| - |
251 |
| - return new Slot(row, col); |
252 |
| - } |
253 |
| - }; |
254 |
| - |
255 |
| - abstract Slot shift(Slot oldPos, int maxRows); |
| 157 | + if (slot != null) return menu.get(slot); |
| 158 | + throw new NoSuchElementException(NOTHING_MORE_NEXT_OPTIONAL); |
256 | 159 | }
|
257 | 160 | }
|
0 commit comments