aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GuiTest/build.gradle8
-rw-r--r--GuiTest/settings.gradle3
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java38
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java26
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/ImplementedInventory.java213
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java25
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/TestContainer.java30
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java8
-rw-r--r--GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java19
-rw-r--r--build.gradle19
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java6
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java11
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java13
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java99
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java5
17 files changed, 486 insertions, 41 deletions
diff --git a/GuiTest/build.gradle b/GuiTest/build.gradle
index c45af5e..ddd6891 100644
--- a/GuiTest/build.gradle
+++ b/GuiTest/build.gradle
@@ -22,6 +22,10 @@ group = project.maven_group
minecraft {
}
+//configurations.modApi {
+// resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
+//}
+
repositories {
mavenLocal();
maven { url "http://server.bbkr.space:8081/artifactory/libs-release" }
@@ -39,7 +43,9 @@ dependencies {
modApi "io.github.prospector:modmenu:1.7.9+build.118"
- modApi "io.github.cottonmc:LibGui:1.3.1-SNAPSHOT"
+ //modApi ("io.github.cottonmc:LibGui:1.3.1-SNAPSHOT") { changing = true }
+ compile project(":LibGUI");
+ runtime project(":LibGUI");
}
processResources {
diff --git a/GuiTest/settings.gradle b/GuiTest/settings.gradle
index 5b60df3..55a4710 100644
--- a/GuiTest/settings.gradle
+++ b/GuiTest/settings.gradle
@@ -8,3 +8,6 @@ pluginManagement {
gradlePluginPortal()
}
}
+
+include ":LibGUI"
+project(":LibGUI").projectDir = file("../") \ No newline at end of file
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java
new file mode 100644
index 0000000..ec37c55
--- /dev/null
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlock.java
@@ -0,0 +1,38 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.fabric.api.block.FabricBlockSettings;
+import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockEntityProvider;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.Blocks;
+import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.Hand;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.hit.BlockHitResult;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.BlockView;
+import net.minecraft.world.World;
+
+public class GuiBlock extends Block implements BlockEntityProvider {
+
+ public GuiBlock() {
+ super(FabricBlockSettings.copy(Blocks.IRON_BLOCK).build());
+ }
+
+
+ @Override
+ public boolean activate(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hitResult) {
+ if (!world.isClient) {
+ ContainerProviderRegistry.INSTANCE.openContainer(new Identifier(LibGuiTest.MODID, "gui"), player, (buf)->buf.writeBlockPos(pos));
+ }
+ return true;
+ }
+
+
+ @Override
+ public BlockEntity createBlockEntity(BlockView var1) {
+ return new GuiBlockEntity();
+ }
+}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java
new file mode 100644
index 0000000..f07ccb7
--- /dev/null
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/GuiBlockEntity.java
@@ -0,0 +1,26 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.DefaultedList;
+
+public class GuiBlockEntity extends BlockEntity implements ImplementedInventory {
+
+ DefaultedList<ItemStack> items = DefaultedList.ofSize(8, ItemStack.EMPTY);
+
+ public GuiBlockEntity() {
+ super(LibGuiTest.GUI_BLOCKENTITY_TYPE);
+ }
+
+ @Override
+ public DefaultedList<ItemStack> getItems() {
+ return items;
+ }
+
+ @Override
+ public boolean canPlayerUseInv(PlayerEntity player) {
+ return pos.isWithinDistance(player.getBlockPos(), 4.5);
+ }
+
+}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/ImplementedInventory.java b/GuiTest/src/main/java/io/github/cottonmc/test/ImplementedInventory.java
new file mode 100644
index 0000000..177affd
--- /dev/null
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/ImplementedInventory.java
@@ -0,0 +1,213 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.inventory.Inventories;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.inventory.SidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.util.DefaultedList;
+import net.minecraft.util.math.Direction;
+
+import java.util.List;
+
+/**
+ * A simple {@code SidedInventory} implementation with only default methods + an item list getter.
+ *
+ * <h2>Reading and writing to tags</h2>
+ * Use {@link Inventories#fromTag(CompoundTag, DefaultedList)} and {@link Inventories#toTag(CompoundTag, DefaultedList)}
+ * on {@linkplain #getItems() the item list}.
+ *
+ * License: <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a>
+ * @author Juuz
+ */
+@FunctionalInterface
+public interface ImplementedInventory extends SidedInventory {
+ /**
+ * Gets the item list of this inventory.
+ * Must return the same instance every time it's called.
+ *
+ * @return the item list
+ */
+ DefaultedList<ItemStack> getItems();
+
+ // Creation
+
+ /**
+ * Creates an inventory from the item list.
+ *
+ * @param items the item list
+ * @return a new inventory
+ */
+ static ImplementedInventory of(DefaultedList<ItemStack> items) {
+ return () -> items;
+ }
+
+ /**
+ * Creates a new inventory with the size.
+ *
+ * @param size the inventory size
+ * @return a new inventory
+ */
+ static ImplementedInventory ofSize(int size) {
+ return of(DefaultedList.ofSize(size, ItemStack.EMPTY));
+ }
+
+ // SidedInventory
+
+ /**
+ * Gets the available slots to automation on the side.
+ *
+ * <p>The default implementation returns an array of all slots.
+ *
+ * @param side the side
+ * @return the available slots
+ */
+ @Override
+ default int[] getInvAvailableSlots(Direction side) {
+ int[] result = new int[getItems().size()];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = i;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns true if the stack can be inserted in the slot at the side.
+ *
+ * <p>The default implementation returns true.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ * @param side the side
+ * @return true if the stack can be inserted
+ */
+ @Override
+ default boolean canInsertInvStack(int slot, ItemStack stack, Direction side) {
+ return true;
+ }
+
+ /**
+ * Returns true if the stack can be extracted from the slot at the side.
+ *
+ * <p>The default implementation returns true.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ * @param side the side
+ * @return true if the stack can be extracted
+ */
+ @Override
+ default boolean canExtractInvStack(int slot, ItemStack stack, Direction side) {
+ return true;
+ }
+
+ // Inventory
+
+ /**
+ * Returns the inventory size.
+ *
+ * <p>The default implementation returns the size of {@link #getItems()}.
+ *
+ * @return the inventory size
+ */
+ @Override
+ default int getInvSize() {
+ return getItems().size();
+ }
+
+ /**
+ * @return true if this inventory has only empty stacks, false otherwise
+ */
+ @Override
+ default boolean isInvEmpty() {
+ for (int i = 0; i < getInvSize(); i++) {
+ ItemStack stack = getInvStack(i);
+ if (!stack.isEmpty()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets the item in the slot.
+ *
+ * @param slot the slot
+ * @return the item in the slot
+ */
+ @Override
+ default ItemStack getInvStack(int slot) {
+ return getItems().get(slot);
+ }
+
+ /**
+ * Takes a stack of the size from the slot.
+ *
+ * <p>(default implementation) If there are less items in the slot than what are requested,
+ * takes all items in that slot.
+ *
+ * @param slot the slot
+ * @param count the item count
+ * @return a stack
+ */
+ @Override
+ default ItemStack takeInvStack(int slot, int count) {
+ ItemStack result = Inventories.splitStack(getItems(), slot, count);
+ if (!result.isEmpty()) {
+ markDirty();
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes the current stack in the {@code slot} and returns it.
+ *
+ * <p>The default implementation uses {@link Inventories#removeStack(List, int)}
+ *
+ * @param slot the slot
+ * @return the removed stack
+ */
+ @Override
+ default ItemStack removeInvStack(int slot) {
+ return Inventories.removeStack(getItems(), slot);
+ }
+
+ /**
+ * Replaces the current stack in the {@code slot} with the provided stack.
+ *
+ * <p>If the stack is too big for this inventory ({@link Inventory#getInvMaxStackAmount()}),
+ * it gets resized to this inventory's maximum amount.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ */
+ @Override
+ default void setInvStack(int slot, ItemStack stack) {
+ getItems().set(slot, stack);
+ if (stack.getCount() > getInvMaxStackAmount()) {
+ stack.setCount(getInvMaxStackAmount());
+ }
+ }
+
+ /**
+ * Clears {@linkplain #getItems() the item list}}.
+ */
+ @Override
+ default void clear() {
+ getItems().clear();
+ }
+
+ @Override
+ default void markDirty() {
+ // Override if you want behavior.
+ }
+
+ @Override
+ default boolean canPlayerUseInv(PlayerEntity player) {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
index e2431c8..2e35a55 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/LibGuiTest.java
@@ -1,17 +1,38 @@
package io.github.cottonmc.test;
import net.fabricmc.api.ModInitializer;
+import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
+import net.minecraft.block.entity.BlockEntityType;
+import net.minecraft.container.BlockContext;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.BlockItem;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemGroup;
import net.minecraft.util.Identifier;
+import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.registry.Registry;
public class LibGuiTest implements ModInitializer {
public static final String MODID = "libgui-test";
+ public static GuiBlock GUI_BLOCK;
+ public static BlockItem GUI_BLOCK_ITEM;
+ public static BlockEntityType<GuiBlockEntity> GUI_BLOCKENTITY_TYPE;
@Override
public void onInitialize() {
- //TODO: Register an item that spawns a clientside gui, and a block that spawns a serverside one
-
Registry.register(Registry.ITEM, new Identifier(MODID, "client_gui"), new GuiItem());
+
+ GUI_BLOCK = new GuiBlock();
+ Registry.register(Registry.BLOCK, new Identifier(MODID, "gui"), GUI_BLOCK);
+ GUI_BLOCK_ITEM = new BlockItem(GUI_BLOCK, new Item.Settings().group(ItemGroup.MISC));
+ Registry.register(Registry.ITEM, new Identifier(MODID, "gui"), GUI_BLOCK_ITEM);
+ GUI_BLOCKENTITY_TYPE = BlockEntityType.Builder.create(GuiBlockEntity::new, GUI_BLOCK).build(null);
+ Registry.register(Registry.BLOCK_ENTITY, new Identifier(MODID, "gui"), GUI_BLOCKENTITY_TYPE);
+
+
+ ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(MODID, "gui"), (int syncId, Identifier identifier, PlayerEntity player, PacketByteBuf buf)->{
+ return new TestContainer(syncId, player.inventory, BlockContext.create(player.getEntityWorld(), buf.readBlockPos()));
+ });
}
}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/TestContainer.java b/GuiTest/src/main/java/io/github/cottonmc/test/TestContainer.java
new file mode 100644
index 0000000..975cd6f
--- /dev/null
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/TestContainer.java
@@ -0,0 +1,30 @@
+package io.github.cottonmc.test;
+
+import io.github.cottonmc.cotton.gui.CottonScreenController;
+import io.github.cottonmc.cotton.gui.widget.WButton;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WItemSlot;
+import io.github.cottonmc.cotton.gui.widget.WPlayerInvPanel;
+import net.minecraft.container.BlockContext;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.text.LiteralText;
+
+public class TestContainer extends CottonScreenController {
+
+ public TestContainer(int syncId, PlayerInventory playerInventory, BlockContext context) {
+ super(null, syncId, playerInventory, getBlockInventory(context), null);
+
+ WGridPanel root = (WGridPanel)this.getRootPanel();
+
+ root.add(WItemSlot.of(blockInventory, 0, 4, 1), 0, 1);
+
+ WButton button = new WButton(new LiteralText("Test Button"));
+ root.add(button, 0, 3, 5, 1);
+
+
+ root.add(new WPlayerInvPanel(playerInventory), 0, 5);
+
+
+ this.getRootPanel().validate(this);
+ }
+}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java b/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
index 42b4b42..360fd73 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/client/LibGuiTestClient.java
@@ -1,12 +1,18 @@
package io.github.cottonmc.test.client;
+import io.github.cottonmc.cotton.gui.client.CottonScreen;
+import io.github.cottonmc.test.LibGuiTest;
+import io.github.cottonmc.test.TestContainer;
import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
+import net.minecraft.container.BlockContext;
+import net.minecraft.util.Identifier;
public class LibGuiTestClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
-
+ ScreenProviderRegistry.INSTANCE.registerFactory(new Identifier(LibGuiTest.MODID, "gui"), (syncId, identifier, player, buf)->new CottonScreen<TestContainer>(new TestContainer(syncId, player.inventory, BlockContext.create(player.getEntityWorld(), buf.readBlockPos())), player));
}
}
diff --git a/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java b/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java
index 73f23b4..4b914f8 100644
--- a/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java
+++ b/GuiTest/src/main/java/io/github/cottonmc/test/client/TestClientGui.java
@@ -13,23 +13,22 @@ import net.minecraft.text.LiteralText;
public class TestClientGui extends LightweightGuiDescription {
public TestClientGui() {
- WGridPanel root = new WGridPanel();
+ WGridPanel root = new WGridPanel(24);
this.setRootPanel(root);
+ WLabel title = new WLabel(new LiteralText("Client Test Gui"), WLabel.DEFAULT_TEXT_COLOR);
+ root.add(title, 0, 0);
+
WTextField text = new WTextField();
text.setSuggestion("Test Suggestion");
root.add(text, 0, 1, 8, 1);
+ text.setSize(8*18, 20);
ArrayList<String> data = new ArrayList<>();
- data.add("This");
- data.add("is");
- data.add("a");
- data.add("test");
- data.add("of the");
- data.add("new");
- data.add("recycler-style");
- data.add("list");
- data.add("widget");
+ for(int i=0; i<100; i++) {
+ data.add(""+i);
+ }
+
BiConsumer<String, WLabel> configurator = (String s, WLabel label) -> {
label.setText(new LiteralText(s));
};
diff --git a/build.gradle b/build.gradle
index d321642..c453a51 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,18 +1,35 @@
buildscript {
repositories {
jcenter()
+ maven {
+ name = 'Fabric'
+ url = 'https://maven.fabricmc.net/'
+ }
+ }
+
+ dependencies {
+ System.out.println(rootProject.name);
+ if (rootProject.name=="LibGUI") {
+ System.out.println("Added libgui to classpath");
+ classpath 'fabric-loom:fabric-loom.gradle.plugin:0.2.4-SNAPSHOT'
+ }
}
}
plugins {
- id 'fabric-loom' version '0.2.4-SNAPSHOT'
+ //id 'fabric-loom' version '0.2.4-SNAPSHOT'
id 'maven-publish'
id "com.jfrog.artifactory" version "4.9.0"
}
+
+apply plugin: "fabric-loom";
+
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
+
+
if(rootProject.file('private.gradle').exists()) { //Publishing details
apply from: 'private.gradle'
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java
index 390b715..6935894 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java
@@ -190,7 +190,7 @@ public class CottonScreen<T extends CottonScreenController> extends AbstractCont
}
if (this.container.getRootPanel()!=null) {
- this.container.getRootPanel().paintForeground(0, 0, mouseX+left, mouseY+top);
+ this.container.getRootPanel().paintForeground(0, 0, mouseX-left, mouseY-top);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
index 3b6c299..0f5159c 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
@@ -31,6 +31,8 @@ public class WButton extends WWidget {
@Override
public void paintForeground(int x, int y, int mouseX, int mouseY) {
+ System.out.println("Mouse: { "+mouseX+", "+mouseY+" }");
+
boolean hovered = (mouseX>=x && mouseY>=y && mouseX<x+getWidth() && mouseY<y+getHeight());
int state = 1; //1=regular. 2=hovered. 0=disabled.
if (!enabled) state = 0;
@@ -64,6 +66,10 @@ public class WButton extends WWidget {
super.paintForeground(x, y, mouseX, mouseY);
}
+ @Override
+ public void setSize(int x, int y) {
+ super.setSize(x, 20);
+ }
@Override
public void onClick(int x, int y, int button) {
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
index 64d4171..f9918b0 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
@@ -93,7 +93,7 @@ public class WItemSlot extends WWidget {
for (int y = 0; y < slotsHigh; y++) {
for (int x = 0; x < slotsWide; x++) {
- ValidatedSlot slot = new ValidatedSlot(inventory, index, this.getAbsoluteX() + (x * 18) + 1, this.getAbsoluteY() + (y * 18) + 1);
+ ValidatedSlot slot = new ValidatedSlot(inventory, index, this.getAbsoluteX() + (x * 18), this.getAbsoluteY() + (y * 18));
peers.add(slot);
c.addSlotPeer(slot);
index++;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
index 6c6f82a..d17729f 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
@@ -34,17 +34,12 @@ public class WLabel extends WWidget {
@Override
public boolean canResize() {
- return false;
+ return true;
}
@Override
- public int getWidth() {
- return 8; //We don't actually clip to our boundaries so return a dummy value.
- }
-
- @Override
- public int getHeight() {
- return 8;
+ public void setSize(int x, int y) {
+ super.setSize(x, 20);
}
public WLabel setDarkmodeColor(int color) {
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
index a98857e..21bff58 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WListPanel.java
@@ -6,8 +6,6 @@ import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
-import io.github.cottonmc.cotton.gui.GuiDescription;
-import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
/**
@@ -30,13 +28,14 @@ public class WListPanel<D, W extends WWidget> extends WPanel {
protected int margin = 4;
- protected int scrollOffset;
+ protected WScrollBar scrollBar = new WScrollBar(Axis.VERTICAL);
public WListPanel(List<D> data, Class<W> listItemClass, Supplier<W> supplier, BiConsumer<D, W> configurator) {
this.data = data;
this.listItemClass = listItemClass;
this.supplier = supplier;
this.configurator = configurator;
+ scrollBar.setMaxValue(data.size());
}
@Override
@@ -56,6 +55,8 @@ public class WListPanel<D, W extends WWidget> extends WPanel {
public void layout() {
super.layout();
+ int scrollOffset = scrollBar.value;
+
System.out.println("Validating");
//Recompute cellHeight if needed
@@ -83,6 +84,12 @@ public class WListPanel<D, W extends WWidget> extends WPanel {
System.out.println("Adding children...");
this.children.clear();
+ this.children.add(scrollBar);
+ scrollBar.setLocation(this.width-4, 0);
+ scrollBar.setSize(4, this.height);
+ scrollBar.window = cellsHigh;
+ scrollBar.setMaxValue(data.size());
+
if (presentCells>0) {
for(int i=0; i<presentCells; i++) {
int index = i+scrollOffset;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
index 289a2cd..6eb6359 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
@@ -8,6 +8,8 @@ public class WScrollBar extends WWidget {
protected int maxValue = 100;
protected int window = 16;
+ protected int anchor = -1;
+
public WScrollBar() {
}
@@ -18,25 +20,96 @@ public class WScrollBar extends WWidget {
@Override
public void paintBackground(int x, int y) {
ScreenDrawing.drawBeveledPanel(x, y, width, height, 0xFFFFFFFF, 0xFF8b8b8b, 0xFF373737);
+ if (maxValue<=0) return;
- float barHeight = (window>maxValue) ? 1f : window / maxValue;
- int scrollDistance = maxValue - window;
+ int color = 0xFF_FFFFFF;
+ if (axis==Axis.HORIZONTAL) {
+ ScreenDrawing.rect(x+1+getHandlePosition(), y+1, getHandleSize(), height-2, color);
+ } else {
+ ScreenDrawing.rect(x+1, y+1+getHandlePosition(), width-2, getHandleSize(), color);
+ }
+ }
+
+ /**
+ * Gets the on-axis size of the scrollbar handle in gui pixels
+ */
+ public int getHandleSize() {
+ float percentage = (window>maxValue) ? 1f : window / (float)maxValue;
+ int bar = (axis==Axis.HORIZONTAL) ? width-2 : height-2;
+ return (int)(percentage*bar);
+ }
+
+ /**
+ * Gets the number of pixels the scrollbar handle is able to move along its track from one end to the other.
+ */
+ public int getMovableDistance() {
+ int logicalDistance = maxValue-window;
+ if (logicalDistance<0) logicalDistance = 0;
+ float percentage = logicalDistance / maxValue;
+ return (int) ( (axis==Axis.HORIZONTAL) ? (width-2)*percentage : (height-2)*percentage);
+ }
+
+ public int getHandlePosition() {
+ float percent = value / (float)Math.max(maxValue, 1);
+ return (int)(percent * getMovableDistance());
+ }
+
+ /**
+ * Gets the maximum scroll value achievable; this will typically be the maximum value minus the
+ * window size
+ */
+ public int getMaxScrollValue() {
+ return maxValue - window;
+ }
+
+ @Override
+ public WWidget onMouseDown(int x, int y, int button) {
+ //TODO: Clicking before or after the handle should jump instead of scrolling
- super.paintBackground(x, y);
+ if (axis==Axis.HORIZONTAL) {
+ anchor = x;
+ } else {
+ anchor = y;
+ }
+ System.out.println("Anchor set to "+anchor);
+ return this;
+ }
+
+ @Override
+ public void onMouseDrag(int x, int y, int button) {
+ int delta = 0;
+ if (axis==Axis.HORIZONTAL) {
+ delta = x-anchor;
+ } else {
+ delta = y-anchor;
+ }
+
+ float percentMoved = (delta / (float)getMovableDistance());
+ int valueDelta = (int)(percentMoved * maxValue);
+ //System.out.println("Anchor: "+anchor+", Delta: "+delta+", ValueDelta: "+valueDelta);
+
+ super.onMouseDrag(x, y, button);
}
@Override
- public void setSize(int x, int y) {
- switch(axis) {
- case HORIZONTAL:
- this.width = x;
- this.height = 8;
- break;
- case VERTICAL:
- this.width = 8;
- this.height = y;
- break;
+ public WWidget onMouseUp(int x, int y, int button) {
+ //TODO: Clicking before or after the handle should jump instead of scrolling
+ System.out.println("Anchor released.");
+ anchor = -1;
+
+ return this;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public WScrollBar setMaxValue(int max) {
+ this.maxValue = max;
+ if (this.value>maxValue-window) {
+ this.value = maxValue-window;
}
+ return this;
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
index 217e5d3..99ea221 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
@@ -81,6 +81,11 @@ public class WTextField extends WWidget {
return true;
}
+ @Override
+ public void setSize(int x, int y) {
+ super.setSize(x, 20);
+ }
+
/*
public String getSelectedText() {
int start = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin;