Skip to content

Commit 6c22ace

Browse files
Rework Paged-, Scroll-, TabGui
- PagedGui<Gui>, ScrollGui<Gui>, TabGui now keep the dimensions of the guis - ScrollGuis can now have lines of uneven length and interrupted lines. These spots will be treated as if they were overlayed over a ScrollGui with consecutive lines (i.e. content will be hidden "behind" them)
1 parent 6fdaf80 commit 6c22ace

29 files changed

+1442
-643
lines changed

invui-kotlin/src/test/kotlin/PropertyAccessorsPresenceTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class PropertyAccessorsPresenceTest {
4141
{
4242
// -- PagedGui --
4343
pagedGui.contentListSlots
44-
pagedGui.contentListSlots = emptySequencedSet()
44+
pagedGui.contentListSlots = emptyList()
4545

4646
pagedGui.content
4747
pagedGui.content = emptyList()
@@ -64,7 +64,7 @@ class PropertyAccessorsPresenceTest {
6464

6565
// -- TabGui --
6666
tabGui.contentListSlots
67-
tabGui.contentListSlots = emptySequencedSet()
67+
tabGui.contentListSlots = emptyList()
6868

6969
tabGui.tabs
7070
tabGui.tabs = emptyList()

invui/src/main/java/xyz/xenondevs/invui/gui/AbstractIngredientMapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ public S applyPreset(IngredientPreset preset) {
1919
@Override
2020
public S addIngredient(char key, SlotElementSupplier elementSupplier) {
2121
handleUpdate();
22-
ingredientMap.put(key, new Ingredient(elementSupplier));
22+
ingredientMap.put(key, new Ingredient.Element(elementSupplier));
2323
return (S) this;
2424
}
2525

2626
@Override
2727
public S addIngredient(char key, Marker marker) {
2828
handleUpdate();
29-
ingredientMap.put(key, new Ingredient(marker));
29+
ingredientMap.put(key, new Ingredient.Marker(marker));
3030
return (S) this;
3131
}
3232

invui/src/main/java/xyz/xenondevs/invui/gui/AbstractPagedGui.java

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,35 @@
55
import org.jspecify.annotations.Nullable;
66
import xyz.xenondevs.invui.internal.util.CollectionUtils;
77
import xyz.xenondevs.invui.internal.util.FuncUtils;
8-
import xyz.xenondevs.invui.internal.util.SlotUtils;
98
import xyz.xenondevs.invui.item.ItemProvider;
109
import xyz.xenondevs.invui.state.MutableProperty;
1110

12-
import java.util.ArrayList;
13-
import java.util.Collections;
14-
import java.util.List;
15-
import java.util.SequencedSet;
11+
import java.util.*;
1612
import java.util.function.BiConsumer;
1713

1814
non-sealed abstract class AbstractPagedGui<C> extends AbstractGui implements PagedGui<C> {
1915

2016
private static final int DEFAULT_PAGE = 0;
2117

22-
protected int[] contentListSlots;
18+
private List<Slot> contentListSlots = List.of();
2319

2420
private final MutableProperty<Integer> page;
2521
private final MutableProperty<List<? extends C>> content;
2622
private final List<BiConsumer<? super Integer, ? super Integer>> pageChangeHandlers = new ArrayList<>(0);
2723
private final List<BiConsumer<? super Integer, ? super Integer>> pageCountChangeHandlers = new ArrayList<>(0);
28-
private @Nullable List<? extends List<SlotElement>> pages;
2924
private int previousPage;
3025

3126
public AbstractPagedGui(
3227
int width, int height,
33-
SequencedSet<? extends Slot> contentListSlots,
28+
List<? extends Slot> contentListSlots,
3429
MutableProperty<List<? extends C>> content
3530
) {
3631
super(width, height);
3732
this.page = MutableProperty.of(DEFAULT_PAGE);
3833
page.observeWeak(this, AbstractPagedGui::handlePageChange);
3934
this.content = content;
4035
content.observeWeak(this, AbstractPagedGui::bake);
41-
this.contentListSlots = SlotUtils.toSlotIndices(contentListSlots, getWidth());
36+
this.contentListSlots = new ArrayList<>(contentListSlots);
4237
}
4338

4439
public AbstractPagedGui(
@@ -54,26 +49,32 @@ public AbstractPagedGui(
5449
page.observeWeak(this, AbstractPagedGui::handlePageChange);
5550
this.content = content;
5651
content.observeWeak(this, AbstractPagedGui::bake);
57-
this.contentListSlots = structure.getIngredientMatrix().findContentListSlots();
52+
this.contentListSlots = structure.getIngredientMatrix().getContentListSlots();
5853
super.applyStructure(structure); // super call to avoid bake() through applyStructure override
5954
}
6055

6156
@Override
6257
public void applyStructure(Structure structure) {
6358
super.applyStructure(structure);
64-
this.contentListSlots = structure.getIngredientMatrix().findContentListSlots();
59+
this.contentListSlots = structure.getIngredientMatrix().getContentListSlots();
6560
bake();
6661
}
6762

6863
@Override
69-
public void setContentListSlots(SequencedSet<Slot> slots) {
70-
this.contentListSlots = SlotUtils.toSlotIndices(slots, getWidth());
64+
public void setContentListSlots(List<? extends Slot> slots) {
65+
this.contentListSlots = new ArrayList<>(slots);
7166
bake();
7267
}
7368

7469
@Override
75-
public @Unmodifiable SequencedSet<Slot> getContentListSlots() {
76-
return Collections.unmodifiableSequencedSet(SlotUtils.toSlotSet(contentListSlots, getWidth()));
70+
public @Unmodifiable List<Slot> getContentListSlots() {
71+
return Collections.unmodifiableList(contentListSlots);
72+
}
73+
74+
@Override
75+
public final void bake() {
76+
// -- baking removed --
77+
setPage(getPage()); // corrects page and refreshes content
7778
}
7879

7980
private void handlePageChange() {
@@ -95,12 +96,7 @@ private void handlePageChange() {
9596
previousPage = targetPage;
9697
}
9798

98-
private void updateContent() {
99-
List<SlotElement> slotElements = (pages != null && !pages.isEmpty()) ? pages.get(getPage()) : List.of();
100-
for (int i = 0; i < contentListSlots.length; i++) {
101-
setSlotElement(contentListSlots[i], slotElements.size() > i ? slotElements.get(i) : null);
102-
}
103-
}
99+
protected abstract void updateContent();
104100

105101
private int correctPage(int page) {
106102
// 0 <= page < pageAmount
@@ -112,28 +108,11 @@ public void setContent(List<? extends C> content) {
112108
this.content.set(content);
113109
}
114110

115-
public void setBakedPages(@Nullable List<? extends List<SlotElement>> pages) {
116-
int prevPageCount = getPageCount();
117-
this.pages = pages;
118-
int newPageCount = getPageCount();
119-
120-
CollectionUtils.forEachCatching(
121-
pageCountChangeHandlers,
122-
handler -> handler.accept(prevPageCount, newPageCount),
123-
"Failed to handle page count change from " + prevPageCount + " to " + newPageCount
124-
);
125-
}
126-
127111
@Override
128112
public @UnmodifiableView List<C> getContent() {
129113
return Collections.unmodifiableList(FuncUtils.getSafely(content, List.of()));
130114
}
131115

132-
@Override
133-
public int getPageCount() {
134-
return pages != null ? pages.size() : 0;
135-
}
136-
137116
@Override
138117
public void setPage(int page) {
139118
this.page.set(page);

invui/src/main/java/xyz/xenondevs/invui/gui/AbstractScrollGui.java

Lines changed: 46 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import org.jetbrains.annotations.Unmodifiable;
44
import org.jetbrains.annotations.UnmodifiableView;
55
import org.jspecify.annotations.Nullable;
6-
import xyz.xenondevs.invui.internal.util.ArrayUtils;
76
import xyz.xenondevs.invui.internal.util.CollectionUtils;
87
import xyz.xenondevs.invui.internal.util.FuncUtils;
98
import xyz.xenondevs.invui.internal.util.SlotUtils;
@@ -13,35 +12,36 @@
1312
import java.util.ArrayList;
1413
import java.util.Collections;
1514
import java.util.List;
16-
import java.util.SequencedSet;
1715
import java.util.function.BiConsumer;
1816

1917
non-sealed abstract class AbstractScrollGui<C> extends AbstractGui implements ScrollGui<C> {
2018

2119
private static final int DEFAULT_LINE = 0;
2220

23-
private int lineLength;
24-
private int[] contentListSlots = new int[0];
21+
private List<Slot> contentListSlots = List.of();
22+
protected Slot min = new Slot(0, 0);
23+
protected Slot max = new Slot(0, 0);
24+
protected int lineLength = 0;
25+
private LineOrientation orientation = LineOrientation.HORIZONTAL;
2526

2627
private final MutableProperty<Integer> line;
2728
private final MutableProperty<List<? extends C>> content;
2829
private final List<BiConsumer<? super Integer, ? super Integer>> scrollHandlers = new ArrayList<>(0);
2930
private final List<BiConsumer<? super Integer, ? super Integer>> lineCountChangeHandlers = new ArrayList<>(0);
30-
private @Nullable List<SlotElement> elements;
3131
private int previousLine;
3232

3333
public AbstractScrollGui(
3434
int width, int height,
35-
SequencedSet<? extends Slot> contentListSlots,
36-
boolean horizontalLines,
35+
List<? extends Slot> contentListSlots,
36+
LineOrientation orientation,
3737
MutableProperty<List<? extends C>> content
3838
) {
3939
super(width, height);
4040
this.line = MutableProperty.of(DEFAULT_LINE);
4141
line.observeWeak(this, AbstractScrollGui::handleLineChange);
4242
this.content = content;
4343
content.observeWeak(this, AbstractScrollGui::bake);
44-
setContentListSlots(SlotUtils.toSlotIndicesSet(contentListSlots, getWidth()), horizontalLines);
44+
setContentListSlotsNoBake(contentListSlots, orientation);
4545
}
4646

4747
public AbstractScrollGui(
@@ -70,43 +70,40 @@ public void applyStructure(Structure structure) {
7070

7171
private void setContentListSlotsFromStructure(Structure structure) {
7272
IngredientMatrix matrix = structure.getIngredientMatrix();
73-
int[] horizontal = matrix.findIndices(Markers.CONTENT_LIST_SLOT_HORIZONTAL);
74-
int[] vertical = matrix.findIndices(Markers.CONTENT_LIST_SLOT_VERTICAL);
73+
List<Slot> horizontal = matrix.getSlots(Markers.CONTENT_LIST_SLOT_HORIZONTAL);
74+
List<Slot> vertical = matrix.getSlots(Markers.CONTENT_LIST_SLOT_VERTICAL);
7575

76-
if (horizontal.length > 0 && vertical.length > 0)
76+
if (!horizontal.isEmpty() && !vertical.isEmpty())
7777
throw new IllegalArgumentException("Cannot determine line orientation as structure contains both horizontal and vertical content list slots");
7878

79-
if (horizontal.length > 0) {
80-
setContentListSlots(ArrayUtils.toSequencedSet(horizontal), true);
81-
} else if (vertical.length > 0) {
82-
setContentListSlots(ArrayUtils.toSequencedSet(vertical), false);
79+
if (!horizontal.isEmpty()) {
80+
setContentListSlotsNoBake(horizontal, LineOrientation.HORIZONTAL);
81+
} else if (!vertical.isEmpty()) {
82+
setContentListSlotsNoBake(vertical, LineOrientation.VERTICAL);
8383
}
8484
}
8585

8686
@Override
87-
public void setContentListSlotsHorizontal(SequencedSet<? extends Slot> slots) {
88-
setContentListSlots(SlotUtils.toSlotIndicesSet(slots, getWidth()), true);
87+
public void setContentListSlots(List<? extends Slot> slots, LineOrientation orientation) {
88+
setContentListSlotsNoBake(slots, orientation);
8989
bake();
9090
}
9191

92-
@Override
93-
public void setContentListSlotsVertical(SequencedSet<? extends Slot> slots) {
94-
setContentListSlots(SlotUtils.toSlotIndicesSet(slots, getWidth()), false);
95-
bake();
92+
public void setContentListSlotsNoBake(List<? extends Slot> slots, LineOrientation orientation) {
93+
lineLength = switch (orientation) {
94+
case HORIZONTAL -> SlotUtils.determineLongestHorizontalLineLength(slots, getHeight());
95+
case VERTICAL -> SlotUtils.determineLongestVerticalLineLength(slots, getWidth());
96+
};
97+
this.min = SlotUtils.min(slots);
98+
this.max = SlotUtils.max(slots);
99+
this.contentListSlots = new ArrayList<>(slots);
100+
this.orientation = orientation;
96101
}
97102

98103
@Override
99-
public @Unmodifiable SequencedSet<Slot> getContentListSlots() {
100-
return Collections.unmodifiableSequencedSet(SlotUtils.toSlotSet(contentListSlots, getWidth()));
101-
}
102-
103-
private void setContentListSlots(SequencedSet<Integer> slots, boolean horizontal) {
104-
int lineLength = horizontal
105-
? SlotUtils.determineHorizontalLinesLength(slots, getWidth())
106-
: SlotUtils.determineVerticalLinesLength(slots, getWidth());
107-
108-
this.contentListSlots = ArrayUtils.toIntArray(slots);
109-
this.lineLength = lineLength;
104+
public final void bake() {
105+
// -- baking removed --
106+
setLine(getLine()); // corrects line and refreshes content
110107
}
111108

112109
private void handleLineChange() {
@@ -128,61 +125,45 @@ private void handleLineChange() {
128125
previousLine = targetLine;
129126
}
130127

131-
private void updateContent() {
132-
assert elements != null;
133-
int offset = getLine() * lineLength;
134-
List<SlotElement> slotElements = elements.subList(offset, Math.min(elements.size(), contentListSlots.length + offset));
135-
136-
for (int i = 0; i < contentListSlots.length; i++) {
137-
setSlotElement(contentListSlots[i], slotElements.size() > i ? slotElements.get(i) : null);
138-
}
139-
}
128+
protected abstract void updateContent();
140129

141130
private int correctLine(int line) {
142131
// 0 <= line <= maxLine
143132
return Math.max(0, Math.min(line, getMaxLine()));
144133
}
145134

146-
@Override
147-
public int getLineCount() {
148-
if (elements == null || lineLength == 0)
149-
return 0;
150-
151-
return (int) Math.ceil((double) elements.size() / (double) lineLength);
152-
}
153-
154135
@Override
155136
public int getMaxLine() {
156-
if (elements == null || lineLength == 0)
137+
if (lineLength == 0)
157138
return 0;
158139

159-
int visibleLines = contentListSlots.length / lineLength;
160-
int lineCount = getLineCount();
161-
return Math.max(0, lineCount - visibleLines);
140+
int lines = switch(orientation) {
141+
case HORIZONTAL -> max.y() - min.y();
142+
case VERTICAL -> max.x() - min.x();
143+
} + 1;
144+
return Math.max(0, getLineCount() - lines);
162145
}
163146

164147
@Override
165148
public void setContent(List<? extends C> content) {
166149
this.content.set(content);
167150
}
168151

169-
public void setElements(@Nullable List<SlotElement> elements) {
170-
int previousLineCount = getLineCount();
171-
this.elements = elements;
172-
int newLineCount = getLineCount();
173-
174-
CollectionUtils.forEachCatching(
175-
lineCountChangeHandlers,
176-
handler -> handler.accept(previousLineCount, newLineCount),
177-
"Failed to handle line count change from " + previousLineCount + " to " + newLineCount
178-
);
179-
}
180-
181152
@Override
182153
public @UnmodifiableView List<C> getContent() {
183154
return Collections.unmodifiableList(FuncUtils.getSafely(content, List.of()));
184155
}
185156

157+
@Override
158+
public @Unmodifiable List<Slot> getContentListSlots() {
159+
return Collections.unmodifiableList(contentListSlots);
160+
}
161+
162+
@Override
163+
public LineOrientation getLineOrientation() {
164+
return orientation;
165+
}
166+
186167
@Override
187168
public int getLine() {
188169
return FuncUtils.getSafely(line, DEFAULT_LINE);

invui/src/main/java/xyz/xenondevs/invui/gui/Gui.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ default void setGui(char key, Gui gui, int offsetX, int offsetY) {
575575
Collection<Player> getCurrentViewers();
576576

577577
/**
578-
* Closes the all open {@link Window Windows} that display this {@link Gui}.
578+
* Closes all open {@link Window Windows} that display this {@link Gui}.
579579
*/
580580
void closeForAllViewers();
581581

0 commit comments

Comments
 (0)