33import org .jetbrains .annotations .Unmodifiable ;
44import org .jetbrains .annotations .UnmodifiableView ;
55import org .jspecify .annotations .Nullable ;
6- import xyz .xenondevs .invui .internal .util .ArrayUtils ;
76import xyz .xenondevs .invui .internal .util .CollectionUtils ;
87import xyz .xenondevs .invui .internal .util .FuncUtils ;
98import xyz .xenondevs .invui .internal .util .SlotUtils ;
1312import java .util .ArrayList ;
1413import java .util .Collections ;
1514import java .util .List ;
16- import java .util .SequencedSet ;
1715import java .util .function .BiConsumer ;
1816
1917non-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 );
0 commit comments