From 289c63a99f0dc4018c71f7cbf93fad48bb6fff1d Mon Sep 17 00:00:00 2001 From: "natan.nascimento" Date: Sun, 10 Dec 2023 18:56:13 -0300 Subject: [PATCH] Simplify pipelining --- .../component/ComponentHandle.java | 36 +------------ .../context/IFComponentClearContext.java | 14 +++++ .../inventoryframework/state/State.java | 5 +- .../component/AbstractComponent.java | 35 +++++++++---- .../component/PaginationImpl.java | 38 +++----------- .../state/DefaultStateValueHost.java | 3 +- .../state/StateRegistry.java | 9 ++++ .../component/BukkitComponentHandle.java | 40 ++++++++++++--- .../component/BukkitItemComponentImpl.java | 1 - .../BukkitItemComponentImplHandle.java | 15 +++--- .../context/ComponentClearContext.java | 51 +++++++++++++++++++ .../context/RenderContext.java | 5 ++ .../pipeline/ItemClickInterceptor.java | 3 -- .../component/PaginationBuilder.java | 20 +++++--- .../component/PlatformComponent.java | 12 +++++ ...ndle.java => PlatformComponentHandle.java} | 4 +- .../context/PlatformContext.java | 5 +- .../context/PlatformRenderContext.java | 18 +++++-- .../state/StateAccessImpl.java | 3 +- 19 files changed, 205 insertions(+), 112 deletions(-) create mode 100644 inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFComponentClearContext.java create mode 100644 inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/ComponentClearContext.java rename inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/{AbstractComponentHandle.java => PlatformComponentHandle.java} (98%) diff --git a/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ComponentHandle.java b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ComponentHandle.java index 240537367..58d87d195 100644 --- a/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ComponentHandle.java +++ b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ComponentHandle.java @@ -1,40 +1,6 @@ package me.devnatan.inventoryframework.component; import me.devnatan.inventoryframework.VirtualView; -import me.devnatan.inventoryframework.context.IFComponentContext; -import me.devnatan.inventoryframework.context.IFComponentRenderContext; -import me.devnatan.inventoryframework.context.IFComponentUpdateContext; -import me.devnatan.inventoryframework.context.IFSlotClickContext; import me.devnatan.inventoryframework.pipeline.PipelineInterceptor; -import org.jetbrains.annotations.NotNull; -public abstract class ComponentHandle implements PipelineInterceptor { - - /** - * Renders this component to the given context. - * - * @param context The context that this component will be rendered on. - */ - void rendered(@NotNull IFComponentRenderContext context) {} - - /** - * Called when this component is updated in the given context. - * - * @param context The update context. - */ - void updated(@NotNull IFComponentUpdateContext context) {} - - /** - * Clears this component from the given context. - * - * @param context The context that this component will be cleared from. - */ - public void cleared(@NotNull IFComponentContext context) {} - - /** - * Called when a viewer clicks in that component. - * - * @param context The click context. - */ - void clicked(@NotNull IFSlotClickContext context) {} -} +public abstract class ComponentHandle implements PipelineInterceptor {} diff --git a/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFComponentClearContext.java b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFComponentClearContext.java new file mode 100644 index 000000000..76b775023 --- /dev/null +++ b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFComponentClearContext.java @@ -0,0 +1,14 @@ +package me.devnatan.inventoryframework.context; + +import me.devnatan.inventoryframework.ViewContainer; + +public interface IFComponentClearContext extends IFComponentContext, IFConfinedContext { + + IFRenderContext getParent(); + + ViewContainer getContainer(); + + boolean isCancelled(); + + void setCancelled(boolean cancelled); +} diff --git a/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/state/State.java b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/state/State.java index e210e955e..55c5596eb 100644 --- a/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/state/State.java +++ b/inventory-framework-api/src/main/java/me/devnatan/inventoryframework/state/State.java @@ -1,6 +1,7 @@ package me.devnatan.inventoryframework.state; import java.util.concurrent.atomic.AtomicLong; +import me.devnatan.inventoryframework.IFDebug; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -54,6 +55,8 @@ public interface State { * @return A new unique state id. */ static long next() { - return ids.getAndIncrement(); + final long id = ids.getAndIncrement(); + IFDebug.debug("New state id generated: %d", id); + return id; } } diff --git a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/AbstractComponent.java b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/AbstractComponent.java index 08294e1b3..7b93ea122 100644 --- a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/AbstractComponent.java +++ b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/AbstractComponent.java @@ -18,8 +18,6 @@ public abstract class AbstractComponent implements Component { - private static final ComponentHandle NOOP_HANDLE = new NoopComponentHandle(); - private final String key; private final VirtualView root; private final Ref reference; @@ -43,6 +41,7 @@ protected AbstractComponent( this.reference = reference; this.watchingStates = watchingStates; this.displayCondition = displayCondition; + setHandle(NoopComponentHandle.INSTANCE); } @Override @@ -124,20 +123,20 @@ public final void hide() { @Override public final @NotNull ComponentHandle getHandle() { - return handle == null ? NOOP_HANDLE : handle; + return handle; } @Override public final void setHandle(ComponentHandle handle) { if (this.handle != null) getPipeline().removeInterceptor(this.handle); - if (handle != null) { - for (final PipelinePhase phase : - new PipelinePhase[] {Component.RENDER, Component.UPDATE, Component.CLEAR, Component.CLICK}) { + if (handle == null) + throw new IllegalArgumentException("Component handle argument in #setHandle cannot be null"); - getPipeline().intercept(phase, handle); - } - } + for (final PipelinePhase phase : + new PipelinePhase[] {Component.RENDER, Component.UPDATE, Component.CLEAR, Component.CLICK}) { + getPipeline().intercept(phase, handle); + } this.handle = handle; } @@ -162,9 +161,25 @@ protected final boolean wasForceUpdated() { return wasForceUpdated; } // endregion + + @Override + public String toString() { + return "AbstractComponent{" + "key='" + + key + '\'' + ", root=" + + root + ", reference=" + + reference + ", watchingStates=" + + watchingStates + ", displayCondition=" + + displayCondition + ", pipeline=" + + pipeline + ", handle=" + + handle + ", isVisible=" + + isVisible + ", wasForceUpdated=" + + wasForceUpdated + '}'; + } } -final class NoopComponentHandle extends ComponentHandle { +class NoopComponentHandle extends ComponentHandle { + + static final ComponentHandle INSTANCE = new NoopComponentHandle(); @Override public void intercept(PipelineContext pipeline, VirtualView subject) {} diff --git a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/PaginationImpl.java b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/PaginationImpl.java index 0030beffe..44d0d6cb5 100644 --- a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/PaginationImpl.java +++ b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/PaginationImpl.java @@ -12,7 +12,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -21,8 +20,6 @@ import me.devnatan.inventoryframework.VirtualView; import me.devnatan.inventoryframework.context.*; import me.devnatan.inventoryframework.internal.LayoutSlot; -import me.devnatan.inventoryframework.pipeline.PipelineContext; -import me.devnatan.inventoryframework.pipeline.PipelinePhase; import me.devnatan.inventoryframework.state.State; import me.devnatan.inventoryframework.state.StateValue; import me.devnatan.inventoryframework.state.StateValueHost; @@ -82,7 +79,6 @@ public PaginationImpl( boolean isAsync, boolean isComputed) { super(key, root, reference, watchingStates, displayCondition); - setHandle(new Handle(this)); this.internalStateId = internalStateId; this.layoutTarget = layoutTarget; this.sourceProvider = sourceProvider; @@ -148,7 +144,7 @@ private CompletableFuture> loadSourceForTheCurrentPage() { simulateStateUpdate(); // TODO Do some error treatment here, even if we expect to the user to handle it - return createProvidedNewSource().handle((result, exception) -> { + return createNewProvidedSource().handle((result, exception) -> { if (exception != null) { debug("[Pagination] An error occurred on data source computation: %s", exception.getMessage()); exception.printStackTrace(); @@ -166,9 +162,11 @@ private CompletableFuture> loadSourceForTheCurrentPage() { } @SuppressWarnings("unchecked") - private CompletableFuture> createProvidedNewSource() { + private CompletableFuture> createNewProvidedSource() { CompletableFuture> job = new CompletableFuture<>(); + System.out.println("getRoot() = " + getRoot()); + final Object source = _srcFactory.apply(getRoot()); if (isAsync()) job = (CompletableFuture>) source; else if (isComputed() || isLazy()) job.complete((List) source); @@ -383,11 +381,6 @@ public void set(Object value) { // do nothing since Pagination is not immutable but unmodifiable directly } - private void accessStateHost(Consumer consumer) { - if (!(getRoot() instanceof StateValueHost)) return; - consumer.accept((StateValueHost) getRoot()); - } - /** * Simulate state update to call listeners thus calling watches in parent components. *

@@ -395,8 +388,8 @@ private void accessStateHost(Consumer consumer) { * for changes in {@link #isLoading()} and current page states. */ private void simulateStateUpdate() { - debug("[Pagination] State update simulation triggered on %d", internalStateId); - accessStateHost(host -> host.updateState(internalStateId, this)); + debug("[Pagination] State update simulation triggered on %d", internalId()); + ((StateValueHost) getRoot()).updateState(internalId(), this); } // endregion @@ -682,22 +675,3 @@ public String toString() { + super.toString(); } } - -class Handle extends ComponentHandle { - - private final PaginationImpl pagination; - - public Handle(PaginationImpl pagination) { - this.pagination = pagination; - } - - @Override - public void intercept(PipelineContext pipeline, VirtualView subject) { - final PipelinePhase phase = Objects.requireNonNull( - pipeline.getPhase(), "Pipeline phase cannot be null in ComponentHandle interceptor"); - if (phase == Component.RENDER) pagination.render((IFComponentRenderContext) subject); - else if (phase == Component.UPDATE) pagination.updated((IFComponentUpdateContext) subject); - else if (phase == Component.CLEAR) pagination.cleared((IFRenderContext) subject); - else if (phase == Component.CLICK) pagination.clicked((IFSlotClickContext) subject); - } -} diff --git a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/DefaultStateValueHost.java b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/DefaultStateValueHost.java index b7316cbec..4e4a9c831 100644 --- a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/DefaultStateValueHost.java +++ b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/DefaultStateValueHost.java @@ -48,7 +48,6 @@ public StateValue getInternalStateValue(State state) { if (value == null) { value = state.factory().create(this, state); initializeState(id, value); - IFDebug.debug("State %s initialized (initialValue = %s)", id, value.toString()); } return value; @@ -57,6 +56,8 @@ public StateValue getInternalStateValue(State state) { @Override public void initializeState(long id, @NotNull StateValue value) { valuesMap.put(id, value); + IFDebug.debug( + "State %s initialized in %s (initialValue = %s)", id, getClass().getName(), value.toString()); } @Override diff --git a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/StateRegistry.java b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/StateRegistry.java index 87d1ba4b6..a085715cb 100644 --- a/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/StateRegistry.java +++ b/inventory-framework-core/src/main/java/me/devnatan/inventoryframework/state/StateRegistry.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import me.devnatan.inventoryframework.IFDebug; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -26,6 +27,11 @@ public final class StateRegistry implements Iterable> { public void registerState(@NotNull State state, Object caller) { synchronized (stateMap) { stateMap.put(state.internalId(), state); + IFDebug.debug( + "State %s (id: %d) registered in %s", + state.getClass().getName(), + state.internalId(), + caller.getClass().getName()); if (state instanceof StateWatcher) ((StateWatcher) state).stateRegistered(state, caller); } } @@ -38,6 +44,9 @@ public void registerState(@NotNull State state, Object caller) { public void unregisterState(long stateId, Object caller) { synchronized (stateMap) { final State state = stateMap.remove(stateId); + IFDebug.debug( + "State %s unregistered from %s", + state.internalId(), caller.getClass().getName()); if (state instanceof StateWatcher) ((StateWatcher) state).stateUnregistered(state, caller); } } diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitComponentHandle.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitComponentHandle.java index 5eef5c49a..0d3e23ccb 100644 --- a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitComponentHandle.java +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitComponentHandle.java @@ -1,29 +1,53 @@ package me.devnatan.inventoryframework.component; +import java.util.Objects; import me.devnatan.inventoryframework.VirtualView; +import me.devnatan.inventoryframework.context.ComponentClearContext; import me.devnatan.inventoryframework.context.ComponentRenderContext; import me.devnatan.inventoryframework.context.ComponentUpdateContext; import me.devnatan.inventoryframework.context.Context; -import me.devnatan.inventoryframework.context.RenderContext; import me.devnatan.inventoryframework.context.SlotClickContext; import me.devnatan.inventoryframework.pipeline.PipelineContext; +import me.devnatan.inventoryframework.pipeline.PipelinePhase; -public abstract class BukkitComponentHandle extends AbstractComponentHandle { +public abstract class BukkitComponentHandle extends PlatformComponentHandle { + /** + * Renders the component in the given context. + * + * @param context The context that this component will be rendered on. + */ protected abstract void rendered(ComponentRenderContext context); + /** + * Called when the component is updated in the given context. + * + * @param context The update context. + */ protected void updated(ComponentUpdateContext context) {} - // TODO Create ComponentClearContext - protected void cleared(RenderContext context) {} + /** + * Called when the component is cleared from the given context. + * + * @param context The context that this component will be cleared from. + */ + protected void cleared(ComponentClearContext context) {} + /** + * Called when a viewer clicks in the component. + * + * @param context The click context. + */ protected void clicked(SlotClickContext context) {} @Override public final void intercept(PipelineContext pipeline, VirtualView subject) { - if (pipeline.getPhase() == Component.RENDER) rendered((ComponentRenderContext) subject); - if (pipeline.getPhase() == Component.UPDATE) updated((ComponentUpdateContext) subject); - if (pipeline.getPhase() == Component.CLICK) clicked((SlotClickContext) subject); - if (pipeline.getPhase() == Component.CLEAR) cleared((RenderContext) subject); + final PipelinePhase phase = Objects.requireNonNull( + pipeline.getPhase(), "Pipeline phase cannot be null in ComponentHandle interceptor"); + + if (phase == Component.RENDER) rendered((ComponentRenderContext) subject); + if (phase == Component.UPDATE) updated((ComponentUpdateContext) subject); + if (phase == Component.CLEAR) cleared((ComponentClearContext) subject); + if (phase == Component.CLICK) clicked((SlotClickContext) subject); } } diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImpl.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImpl.java index c60e3119e..2805dedcd 100644 --- a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImpl.java +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImpl.java @@ -50,7 +50,6 @@ public final class BukkitItemComponentImpl extends PlatformComponent implements updateOnClick); this.position = position; this.stack = itemStack; - setHandle(new BukkitItemComponentImplHandle()); } @Override diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImplHandle.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImplHandle.java index ee15d7706..d5618eb51 100644 --- a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImplHandle.java +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentImplHandle.java @@ -1,11 +1,11 @@ package me.devnatan.inventoryframework.component; import me.devnatan.inventoryframework.InventoryFrameworkException; +import me.devnatan.inventoryframework.context.ComponentClearContext; import me.devnatan.inventoryframework.context.ComponentRenderContext; -import me.devnatan.inventoryframework.context.IFComponentContext; -import me.devnatan.inventoryframework.context.IFComponentUpdateContext; +import me.devnatan.inventoryframework.context.ComponentUpdateContext; import me.devnatan.inventoryframework.context.IFRenderContext; -import me.devnatan.inventoryframework.context.IFSlotClickContext; +import me.devnatan.inventoryframework.context.SlotClickContext; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -57,7 +57,7 @@ public void rendered(@NotNull ComponentRenderContext context) { } @Override - public void updated(@NotNull IFComponentUpdateContext context) { + protected void updated(ComponentUpdateContext context) { if (context.isCancelled()) return; final PlatformComponent component = (PlatformComponent) context.getComponent(); @@ -75,14 +75,17 @@ public void updated(@NotNull IFComponentUpdateContext context) { } @Override - public void cleared(@NotNull IFComponentContext context) { + protected void cleared(ComponentClearContext context) { final Component component = context.getComponent(); component.getContainer().removeItem(((ItemComponent) component).getPosition()); } @Override - public void clicked(@NotNull IFSlotClickContext context) { + protected void clicked(SlotClickContext context) { final PlatformComponent component = (PlatformComponent) context.getComponent(); + if (component.getClickHandler() != null) { + component.getClickHandler().accept(context); + } if (component.isUpdateOnClick()) context.update(); } diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/ComponentClearContext.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/ComponentClearContext.java new file mode 100644 index 000000000..008b20c8e --- /dev/null +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/ComponentClearContext.java @@ -0,0 +1,51 @@ +package me.devnatan.inventoryframework.context; + +import me.devnatan.inventoryframework.BukkitViewer; +import me.devnatan.inventoryframework.ViewContainer; +import me.devnatan.inventoryframework.Viewer; +import me.devnatan.inventoryframework.component.Component; +import org.bukkit.entity.Player; + +public final class ComponentClearContext extends ComponentContext implements IFComponentClearContext { + + private final Viewer viewer; + private final Player player; + private boolean cancelled; + + public ComponentClearContext(RenderContext parent, Component component, Viewer viewer) { + super(parent, component); + this.viewer = viewer; + this.player = viewer == null ? null : ((BukkitViewer) viewer).getPlayer(); + } + + @Override + public Viewer getViewer() { + return viewer; + } + + @Override + public Player getPlayer() { + return player; + } + + @Override + public ViewContainer getContainer() { + return getComponent().getContainer(); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public String toString() { + return "ComponentClearContext{" + "viewer=" + viewer + ", player=" + player + ", cancelled=" + cancelled + "} " + + super.toString(); + } +} diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/RenderContext.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/RenderContext.java index 030fea79c..7bc0da4cd 100644 --- a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/RenderContext.java +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/RenderContext.java @@ -158,6 +158,11 @@ IFComponentRenderContext createComponentRenderContext(Component component, boole IFComponentUpdateContext createComponentUpdateContext(Component component, boolean force, UpdateReason reason) { return new ComponentUpdateContext(this, component, getViewer()); } + + @Override + IFComponentClearContext createComponentClearContext(Component component) { + return new ComponentClearContext(this, component, getViewer()); + } // endregion @Override diff --git a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/pipeline/ItemClickInterceptor.java b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/pipeline/ItemClickInterceptor.java index ff2a4429e..123916ebe 100644 --- a/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/pipeline/ItemClickInterceptor.java +++ b/inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/pipeline/ItemClickInterceptor.java @@ -1,7 +1,6 @@ package me.devnatan.inventoryframework.pipeline; import me.devnatan.inventoryframework.VirtualView; -import me.devnatan.inventoryframework.component.Component; import me.devnatan.inventoryframework.component.PlatformComponent; import me.devnatan.inventoryframework.context.SlotClickContext; import org.bukkit.event.inventory.InventoryClickEvent; @@ -21,12 +20,10 @@ public void intercept(@NotNull PipelineContext pipeline, @NotNull V final InventoryClickEvent event = context.getClickOrigin(); if (event.getSlotType() == InventoryType.SlotType.OUTSIDE) return; - @SuppressWarnings("rawtypes") final PlatformComponent component = (PlatformComponent) context.getComponent(); if (component == null) return; // inherit cancellation so we can un-cancel it context.setCancelled(component.isCancelOnClick()); - component.getPipeline().execute(Component.CLICK, context); } } diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PaginationBuilder.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PaginationBuilder.java index 7cd2b1df3..bdcf38b60 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PaginationBuilder.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PaginationBuilder.java @@ -68,12 +68,12 @@ public PaginationBuilder elementFactory( @NotNull PaginationValueConsumer elementConsumer) { this.paginationElementFactory = (pagination, index, slot, value) -> { CONTEXT context = (CONTEXT) pagination.getRoot(); - BUILDER builder = (BUILDER) PlatformUtils.getFactory().createItemComponentBuilder(pagination); - if (builder instanceof ItemComponentBuilder) ((ItemComponentBuilder) builder).setPosition(slot); + ItemComponentBuilder builder = PlatformUtils.getFactory().createItemComponentBuilder(pagination); + builder.setPosition(slot); - elementConsumer.accept(context, builder, index, value); + elementConsumer.accept(context, (BUILDER) builder, index, value); - return ((ComponentBuilder) builder).buildComponent(pagination); + return builder.buildComponent(pagination); }; return this; } @@ -119,10 +119,18 @@ public State build() { return stateFactory.apply(this); } - @SuppressWarnings({"unchecked", "rawtypes"}) @Override public Component buildComponent(VirtualView root) { - long stateId = State.next(); + throw new UnsupportedOperationException("PaginationBuilder component cannot be built"); + } + + /** + * This is an internal inventory-framework API that should not be used from outside of + * this library. No compatibility guarantees are provided. + */ + @ApiStatus.Internal + @SuppressWarnings({"unchecked", "rawtypes"}) + public Pagination buildComponent0(long stateId, VirtualView root) { return new PaginationImpl( Long.toString(stateId), root, diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponent.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponent.java index f189af39d..1ec366811 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponent.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponent.java @@ -68,4 +68,16 @@ public final Consumer getClickHandler() { return clickHandler; } // endregion + + @Override + public String toString() { + return "PlatformComponent{" + "cancelOnClick=" + + cancelOnClick + ", closeOnClick=" + + closeOnClick + ", updateOnClick=" + + updateOnClick + ", renderHandler=" + + renderHandler + ", updateHandler=" + + updateHandler + ", clickHandler=" + + clickHandler + "} " + + super.toString(); + } } diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/AbstractComponentHandle.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponentHandle.java similarity index 98% rename from inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/AbstractComponentHandle.java rename to inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponentHandle.java index d271f8643..c56369e44 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/AbstractComponentHandle.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/component/PlatformComponentHandle.java @@ -13,13 +13,13 @@ import me.devnatan.inventoryframework.state.StateRegistry; import org.jetbrains.annotations.NotNull; -public abstract class AbstractComponentHandle extends ComponentHandle +public abstract class PlatformComponentHandle extends ComponentHandle implements StateAccess, VirtualView { private final StateRegistry stateRegistry = new StateRegistry(); private final StateAccess stateAccess = new StateAccessImpl<>(this, stateRegistry); - protected AbstractComponentHandle() {} + protected PlatformComponentHandle() {} public abstract COMPONENT_BUILDER builder(); diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformContext.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformContext.java index 040ef274c..e67e20b6d 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformContext.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformContext.java @@ -1,5 +1,6 @@ package me.devnatan.inventoryframework.context; +import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import me.devnatan.inventoryframework.*; @@ -131,13 +132,13 @@ final Optional getOverlappingComponentToRender(ComponentContainer con // TODO Support recursive overlapping (more than two components overlapping each other) for (final Component child : container.getInternalComponents()) { if (!child.isVisible()) continue; - if (child.getKey().equals(subject.getKey())) continue; + if (Objects.equals(child.getKey(), subject.getKey())) continue; if (child instanceof ComponentComposition) { // This prevents from child being compared with its own root that would cause an // infinite rendering loop causing the root being re-rendered entirely, thus the // child, because child always intersects with its root since it is inside it if (subject.getRoot() instanceof Component - && child.getKey().equals(((Component) subject.getRoot()).getKey())) { + && Objects.equals(child.getKey(), ((Component) subject.getRoot()).getKey())) { continue; } diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformRenderContext.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformRenderContext.java index 6ded2b1e7..e2b6e31d4 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformRenderContext.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/context/PlatformRenderContext.java @@ -18,11 +18,11 @@ import me.devnatan.inventoryframework.ViewContainer; import me.devnatan.inventoryframework.ViewType; import me.devnatan.inventoryframework.Viewer; -import me.devnatan.inventoryframework.component.AbstractComponentHandle; import me.devnatan.inventoryframework.component.Component; import me.devnatan.inventoryframework.component.ComponentBuilder; import me.devnatan.inventoryframework.component.ItemComponentBuilder; import me.devnatan.inventoryframework.component.PlatformComponentBuilder; +import me.devnatan.inventoryframework.component.PlatformComponentHandle; import me.devnatan.inventoryframework.internal.LayoutSlot; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -130,7 +130,7 @@ public final ITEM_BUILDER slot(int row, int column) { */ @ApiStatus.Experimental public final @NotNull < - T extends AbstractComponentHandle, B extends PlatformComponentBuilder> + T extends PlatformComponentHandle, B extends PlatformComponentBuilder> B firstSlot(@NotNull T componentHandle) { final B builder = componentHandle.builder(); final Component component = builder.buildComponent(this); @@ -363,8 +363,9 @@ public final void renderComponent(@NotNull Component component) { if (overlap.isVisible()) return; } - component.getPipeline().execute(Component.CLEAR, this); - clearComponent(component); + final IFComponentClearContext clearContext = createComponentClearContext(component); + component.getPipeline().execute(Component.CLEAR, clearContext); + if (!clearContext.isCancelled()) clearComponent(component); return; } @@ -401,6 +402,15 @@ public final void clearComponent(@NotNull Component component) {} abstract IFComponentUpdateContext createComponentUpdateContext( Component component, boolean force, UpdateReason reason); + /** + * Creates a IFComponentClearContext for the current platform. + * + * @param component The component. + * @return A new IFComponentClearContext instance. + */ + @ApiStatus.Internal + abstract IFComponentClearContext createComponentClearContext(Component component); + /** * Creates a new platform builder instance. * diff --git a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/state/StateAccessImpl.java b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/state/StateAccessImpl.java index 511de6214..9c2117d3f 100644 --- a/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/state/StateAccessImpl.java +++ b/inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/state/StateAccessImpl.java @@ -201,7 +201,8 @@ public PaginationBuilder buildLazyAsyncPaginationS State createPaginationState(@NotNull PaginationBuilder builder) { final long id = State.next(); - final StateValueFactory factory = (host, state) -> (PaginationImpl) builder.buildComponent((VirtualView) host); + final StateValueFactory factory = + (host, state) -> (PaginationImpl) builder.buildComponent0(id, (VirtualView) host); final State state = new PaginationState(id, factory); this.stateRegistry.registerState(state, caller);