Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ public static List<ItemStack> getRandomItems(int amount) {
}

public static ItemStack displayItem(Material material, String displayName) {
ItemStack item = new ItemStack(material);
return displayItem(material, displayName, 1);
}

public static ItemStack displayItem(Material material, String displayName, int amount) {
ItemStack item = new ItemStack(material, amount);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(displayName);
item.setItemMeta(itemMeta);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public class SamplePlugin extends JavaPlugin {
public void onEnable() {
ViewFrame viewFrame = ViewFrame.create(this)
.install(AnvilInputFeature.AnvilInput)
.with(new AnvilInputSample(), new Failing(), new SimplePagination(), new AutoUpdate())
.with(
new AnvilInputSample(),
new Failing(),
new SimplePagination(),
new AutoUpdate(),
new PaginationOrientation())
.register();

IFExampleCommandExecutor command = new IFExampleCommandExecutor(viewFrame);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package me.devnatan.inventoryframework.runtime.commands;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.devnatan.inventoryframework.View;
import me.devnatan.inventoryframework.ViewFrame;
import me.devnatan.inventoryframework.runtime.view.AnvilInputSample;
import me.devnatan.inventoryframework.runtime.view.AutoUpdate;
import me.devnatan.inventoryframework.runtime.view.Failing;
import me.devnatan.inventoryframework.runtime.view.PaginationOrientation;
import me.devnatan.inventoryframework.runtime.view.SimplePagination;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
Expand All @@ -19,11 +21,16 @@

public class IFExampleCommandExecutor implements CommandExecutor, TabCompleter {

private static final Map<String, Class<? extends View>> views = Map.of(
"anvil", AnvilInputSample.class,
"failing", Failing.class,
"simple-pagination", SimplePagination.class,
"auto-update", AutoUpdate.class);
private static final Map<String, Class<? extends View>> views;

static {
views = new HashMap<>();
views.put("anvil", AnvilInputSample.class);
views.put("failing", Failing.class);
views.put("simple-pagination", SimplePagination.class);
views.put("auto-update", AutoUpdate.class);
views.put("pagination", PaginationOrientation.class);
}

private final ViewFrame viewFrame;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package me.devnatan.inventoryframework.runtime.view;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import me.devnatan.inventoryframework.View;
import me.devnatan.inventoryframework.ViewConfigBuilder;
import me.devnatan.inventoryframework.component.Pagination;
import me.devnatan.inventoryframework.context.RenderContext;
import me.devnatan.inventoryframework.runtime.ExampleUtil;
import me.devnatan.inventoryframework.state.State;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;

public class PaginationOrientation extends View {

private final State<Pagination> paginationState = lazyPaginationState(
() -> IntStream.range(0, 50).boxed().collect(Collectors.toList()), (context, builder, index, value) -> {
builder.withItem(ExampleUtil.displayItem(Material.ARROW, "Item " + value, value + 1));
builder.onClick((ctx) -> {
ctx.getPlayer().sendMessage("You clicked on item " + index);
});
});

@Override
public void onInit(@NotNull ViewConfigBuilder config) {
config.cancelOnClick();
config.size(6);
config.title("Pagination (HORIZONTAL)");
config.layout(" ", " ", "OOOOOOOOO", "OOOOOOOOO", "OOOOOOOOO", "OOOOOOOOO");
}

@Override
public void onFirstRender(@NotNull RenderContext render) {
render.firstSlot(ExampleUtil.displayItem(Material.DIAMOND, "Change orientation"))
.onClick(click -> {
final Pagination pagination = paginationState.get(click);
pagination.setOrientation(pagination.getOrientation());

switch (pagination.getOrientation()) {
case VERTICAL:
pagination.setOrientation(Pagination.Orientation.HORIZONTAL);
break;
case HORIZONTAL:
pagination.setOrientation(Pagination.Orientation.ALTERNATING_COLUMNS);
break;
case ALTERNATING_COLUMNS:
pagination.setOrientation(Pagination.Orientation.ALTERNATING_ROWS);
break;
case ALTERNATING_ROWS:
pagination.setOrientation(Pagination.Orientation.TOP_BOTTOM_LEFT_RIGHT);
break;
case TOP_BOTTOM_LEFT_RIGHT:
pagination.setOrientation(Pagination.Orientation.VERTICAL);
break;
}

pagination.forceUpdate();
click.updateTitleForPlayer(
"Pagination (" + pagination.getOrientation().name() + ")");
click.getPlayer().sendMessage("Pagination orientation set to " + pagination.getOrientation());
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,48 +165,48 @@ public interface ComponentBuilder<S extends ComponentBuilder<S, C>, C extends IF
*/
S hideIf(Predicate<C> condition);

/**
* Identifies this component with a constant key.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param key The constant key to identify this component
* @return This component builder
*/
/**
* Identifies this component with a constant key.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param key The constant key to identify this component
* @return This component builder
*/
@ApiStatus.Experimental
S identifiedBy(String key);

/**
* Identifies this component with a key provided by a {@link Supplier}.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during scheduled updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param keyProvider A supplier that provides the key to identify this component.
* @return This component builder.
*/
/**
* Identifies this component with a key provided by a {@link Supplier}.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during scheduled updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param keyProvider A supplier that provides the key to identify this component.
* @return This component builder.
*/
@ApiStatus.Experimental
S identifiedBy(Supplier<String> keyProvider);

/**
* Identifies this component with a key provided by a {@link Function} based on the context.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during scheduled updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param keyProvider A function that provides the key to identify this component based on the context.
* @return This component builder.
*/
/**
* Identifies this component with a key provided by a {@link Function} based on the context.
* <p>
* Components with explicit keys are only re-rendered when their key changes.
* This can be used to prevent unnecessary re-renders during scheduled updates.
*
* <p><b><i>This API is experimental and is not subject to the general compatibility guarantees.
* It may be changed or removed completely in any further release.</i></b>
*
* @param keyProvider A function that provides the key to identify this component based on the context.
* @return This component builder.
*/
@ApiStatus.Experimental
S identifiedBy(Function<C, String> keyProvider);
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,7 @@ public void render(@NotNull IFSlotRenderContext context) {
public void updated(@NotNull IFSlotRenderContext context) {
if (context.isCancelled()) return;
// Key-based skip optimization should always take precedence
if (keyFactory != null
&& lastKey != null) {
if (keyFactory != null && lastKey != null) {
String currentKey = keyFactory.apply(context);
if (Objects.equals(lastKey, currentKey)) return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,106 @@ static List<?> splitSourceForPage(int index, int pageSize, int pagesCount, List<
int toIndex = Math.min(fromIndex + pageSize, src.size());
return src.subList(fromIndex, toIndex);
}

/**
* Returns the orientation used to determine how pagination slot positions
* are traversed when generating paginated components.
*
* <p>The orientation affects only the ordering of slot positions,
* not the page size. It controls whether items fill the pagination
* horizontally, vertically, or in one of the mixed cluster-based modes.</p>
*
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
* such API may be changed or may be removed completely in any further release. </i></b>
*
* @return the currently configured {@link Orientation}
*/
@ApiStatus.Experimental
Orientation getOrientation();

/**
* Sets the orientation that defines how layout slots will be traversed
* when producing paginated components.
*
* <p>This setting does not affect the page size — only the ordering of
* component placement inside the layout.</p>
*
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
* such API may be changed or may be removed completely in any further release. </i></b>
*
* @param orientation the {@link Orientation} value to use
*/
@ApiStatus.Experimental
void setOrientation(Orientation orientation);

enum Orientation {

/**
* Column-major ordering.
*
* <p>Slots are traversed from top to bottom within each column,
* and columns are processed from left to right.</p>
*
* <p>This is used for vertical progression:
* <pre>
* (r0,c0), (r1,c0), (r2,c0), ...
* (r0,c1), (r1,c1), (r2,c1), ...
* </pre>
* </p>
*/
VERTICAL,

/**
* Row-major ordering.
*
* <p>Slots are traversed from left to right within each row,
* and rows are processed from top to bottom.</p>
*
* <p>This is the traditional horizontal progression:
* <pre>
* (r0,c0), (r0,c1), (r0,c2), ...
* (r1,c0), (r1,c1), (r1,c2), ...
* </pre>
* </p>
*/
HORIZONTAL,

/**
* Iterates slot positions using an alternating row-major traversal.
* Elements are interleaved from both ends of the row-major ordered list:
* <pre>
* first, last, second, penultimate, ...
* </pre>
*
* <p>Example for a 3×3 grid (row-major base order: 1–9):
* <pre>
* order = 1, 9, 2, 8, 3, 7, 4, 6, 5
* </pre>
*/
ALTERNATING_ROWS,

/**
* Iterates slot positions using an alternating column-major traversal.
* This variant applies the same interleaving strategy as {@link #ALTERNATING_ROWS}
* but operates on the column-major base order.
*
* <p>Example for a 3×3 grid (column-major base order: 1–6):
* <pre>
* order = 1, 9, 4, 6, 7, 3, 2, 8, 5
* </pre>
*/
ALTERNATING_COLUMNS,

/**
* Mixed column-major ordering.
*
* <p>Slots are traversed vertically (top to bottom, left to right),
* but processed sequence-by-sequence. A "sequence" is a contiguous group
* of valid slots in the layout.</p>
*
* <p>This mode preserves logical grouping while following a
* vertical reading direction.</p>
*/
TOP_BOTTOM_LEFT_RIGHT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import me.devnatan.inventoryframework.internal.ElementFactory;
import me.devnatan.inventoryframework.internal.LayoutSlot;
import me.devnatan.inventoryframework.state.State;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

public final class PaginationStateBuilder<
Expand All @@ -19,6 +20,7 @@ public final class PaginationStateBuilder<
private PaginationElementFactory<V> paginationElementFactory;
private BiConsumer<Context, Pagination> pageSwitchHandler;
private final boolean async, computed;
private Pagination.Orientation orientation;

public PaginationStateBuilder(
Supplier<ElementFactory> internalElementFactoryProvider,
Expand All @@ -31,6 +33,7 @@ public PaginationStateBuilder(
this.sourceProvider = sourceProvider;
this.async = async;
this.computed = computed;
this.orientation = Pagination.Orientation.HORIZONTAL;
}

/**
Expand Down Expand Up @@ -106,6 +109,32 @@ public PaginationStateBuilder<Context, Builder, V> onPageSwitch(
return this;
}

/**
* Defines the iteration order used by pagination.
* The default value is {@link Pagination.Orientation#HORIZONTAL}.
*
* <p>This controls how layout slot positions are traversed when generating
* paginated components. The orientation affects only the ordering of the
* slot iteration.</p>
*
* <p><b><i>This API is experimental and is not subject to the general
* compatibility guarantees. It may be changed or removed entirely
* in a future release.</i></b></p>
*
* @param orientation the pagination orientation to apply.
* @return this pagination builder.
*
* @see Pagination.Orientation
* @see <a href="https://github.com/DevNatan/inventory-framework/wiki/Pagination#pagination-orientation">
* Pagination Orientation on Wiki
* </a>
*/
@ApiStatus.Experimental
public PaginationStateBuilder<Context, Builder, V> orientation(Pagination.Orientation orientation) {
this.orientation = orientation;
return this;
}

/**
* Builds a pagination state based on this builder values.
*
Expand Down Expand Up @@ -144,4 +173,8 @@ public BiConsumer<Context, Pagination> getPageSwitchHandler() {
public PaginationElementFactory<V> getPaginationElementFactory() {
return paginationElementFactory;
}

public Pagination.Orientation getOrientation() {
return orientation;
}
}
Loading
Loading