From 3ff3945cbba758726b78410b51d6d8d1e8171a54 Mon Sep 17 00:00:00 2001 From: PotatoOfPotato <289999293+PotatoOfPotato@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:05:38 +0800 Subject: [PATCH 1/2] configlib : add color enum picker screen for 16-color selection Replace cyclic color switching with a grid picker screen. ColorEnumGuiButton now opens ColorEnumPickerScreen on click, showing all 16 chat colors in an 8x2 grid with blur background. Selecting a color updates the field without closing the screen; click Done or press ESC to close. --- .../configlib/lib/ConfigFieldContainer.java | 2 +- .../lib/gui/ColorEnumPickerScreen.java | 154 ++++++++++++++++++ .../lib/gui/elements/ColorEnumGuiButton.java | 60 ++++--- 3 files changed, 194 insertions(+), 22 deletions(-) create mode 100644 src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java diff --git a/src/configlib/java/fr/alexdoru/configlib/lib/ConfigFieldContainer.java b/src/configlib/java/fr/alexdoru/configlib/lib/ConfigFieldContainer.java index adc475f4..2ce2a246 100644 --- a/src/configlib/java/fr/alexdoru/configlib/lib/ConfigFieldContainer.java +++ b/src/configlib/java/fr/alexdoru/configlib/lib/ConfigFieldContainer.java @@ -280,7 +280,7 @@ public ConfigUIElement getConfigButton(ConfigGuiScreen configGuiScreen, Renderer } } case ENUM_COLOR: { - return new ColorEnumGuiButton(field, event, annotation); + return new ColorEnumGuiButton(configGuiScreen, field, event, annotation); } case ENUM: { return new EnumGuiButton(field, event, annotation); diff --git a/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java b/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java new file mode 100644 index 00000000..dc50bf31 --- /dev/null +++ b/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java @@ -0,0 +1,154 @@ +package fr.alexdoru.configlib.lib.gui; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; + +import java.awt.Color; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +public class ColorEnumPickerScreen extends GuiScreen { + + private static final ResourceLocation BLUR = new ResourceLocation("configlib", "blur.json"); + + private final GuiScreen parent; + private final Field field; + private final EnumChatFormatting[] colors; + private EnumChatFormatting current; + private final Runnable onPick; + + private int gridStartY; + + public ColorEnumPickerScreen(ConfigGuiScreen parent, Field field, EnumChatFormatting current, Runnable onPick) { + this.parent = parent; + this.field = field; + this.current = current; + this.onPick = onPick; + + final List list = new ArrayList<>(); + for (final EnumChatFormatting c : EnumChatFormatting.values()) { + if (c.isColor()) list.add(c); + } + this.colors = list.toArray(new EnumChatFormatting[0]); + } + + @Override + public void initGui() { + final int square = 18; + final int gap = 4; + final int totalW = 8 * square + 7 * gap; + final int startX = (this.width - totalW) / 2; + this.gridStartY = this.height / 2 - (square + gap / 2); + + int id = 1000; + for (int i = 0; i < colors.length; i++) { + final int row = i / 8; + final int col = i % 8; + this.buttonList.add(new ColorSquareButton(id++, + startX + col * (square + gap), this.gridStartY + row * (square + gap), + square, square, colors[i])); + } + + this.buttonList.add(new GuiButton(2000, this.width / 2 - 50, + this.gridStartY + 2 * (square + gap) + 10, 100, 20, "Done")); + + this.mc.entityRenderer.loadShader(BLUR); + super.initGui(); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + + EnumChatFormatting hovered = null; + + for (final GuiButton button : this.buttonList) { + if (button instanceof ColorSquareButton) { + final ColorSquareButton b = (ColorSquareButton) button; + if (b.color == this.current) { + GuiUtil.drawBoxWithOutline( + b.xPosition - 2, b.yPosition - 2, + b.xPosition + b.width + 2, b.yPosition + b.height + 2, + 0x00000000, Color.WHITE.getRGB()); + } + if (mouseX >= b.xPosition && mouseY >= b.yPosition + && mouseX < b.xPosition + b.width && mouseY < b.yPosition + b.height) { + hovered = b.color; + } + } + } + + if (hovered != null) { + final String name = hovered + hovered.name(); + final int textX = (this.width - this.fontRendererObj.getStringWidth(name)) / 2; + final int textY = this.gridStartY - 12 - this.fontRendererObj.FONT_HEIGHT; + this.fontRendererObj.drawStringWithShadow(name, textX, textY, 0xFFFFFF); + } + } + + @Override + protected void actionPerformed(GuiButton button) { + if (button.id == 2000) { + mc.displayGuiScreen(parent); + return; + } + if (button instanceof ColorSquareButton) { + this.current = ((ColorSquareButton) button).color; + try { + field.set(null, this.current); + } catch (IllegalAccessException ignored) {} + if (onPick != null) onPick.run(); + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + if (keyCode == 1) { + mc.displayGuiScreen(parent); + return; + } + super.keyTyped(typedChar, keyCode); + } + + @Override + public void onGuiClosed() { + this.mc.entityRenderer.stopUseShader(); + super.onGuiClosed(); + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } + + private static class ColorSquareButton extends GuiButton { + + private final EnumChatFormatting color; + + ColorSquareButton(int buttonId, int x, int y, int w, int h, EnumChatFormatting color) { + super(buttonId, x, y, w, h, ""); + this.color = color; + } + + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY) { + if (!this.visible) return; + + final int rgb = 255 << 24 | mc.fontRendererObj.getColorCode(color.toString().charAt(1)); + final boolean hover = mouseX >= xPosition && mouseY >= yPosition + && mouseX < xPosition + width && mouseY < yPosition + height; + + GuiUtil.drawBoxWithOutline( + xPosition, yPosition, + xPosition + width, yPosition + height, + rgb, + hover ? Color.WHITE.getRGB() : Color.BLACK.getRGB()); + } + } + +} diff --git a/src/configlib/java/fr/alexdoru/configlib/lib/gui/elements/ColorEnumGuiButton.java b/src/configlib/java/fr/alexdoru/configlib/lib/gui/elements/ColorEnumGuiButton.java index dc341a0a..2244b9b5 100644 --- a/src/configlib/java/fr/alexdoru/configlib/lib/gui/elements/ColorEnumGuiButton.java +++ b/src/configlib/java/fr/alexdoru/configlib/lib/gui/elements/ColorEnumGuiButton.java @@ -2,6 +2,8 @@ import fr.alexdoru.configlib.api.ColorPalette; import fr.alexdoru.configlib.api.ConfigProperty; +import fr.alexdoru.configlib.lib.gui.ColorEnumPickerScreen; +import fr.alexdoru.configlib.lib.gui.ConfigGuiScreen; import fr.alexdoru.configlib.lib.gui.GuiUtil; import net.minecraft.client.Minecraft; import net.minecraft.util.EnumChatFormatting; @@ -9,40 +11,56 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -public class ColorEnumGuiButton extends EnumGuiButton { +public class ColorEnumGuiButton extends ConfigGuiButton { + private final ConfigGuiScreen parentScreen; + private final ClickGuiButton button; private int color; + private EnumChatFormatting value; - public ColorEnumGuiButton(Field field, Method event, ConfigProperty annotation) throws IllegalAccessException { + public ColorEnumGuiButton(ConfigGuiScreen parentScreen, Field field, Method event, ConfigProperty annotation) throws IllegalAccessException { super(field, event, annotation); + this.parentScreen = parentScreen; + this.value = (EnumChatFormatting) this.field.get(null); + this.color = mc.fontRendererObj.getColorCode(this.value.toString().charAt(1)); + + int width = 0; + for (final EnumChatFormatting c : EnumChatFormatting.values()) { + if (c.isColor()) { + width = Math.max(width, mc.fontRendererObj.getStringWidth(" " + c.name())); + } + } + this.button = new ClickGuiButton(0, 0, 0, width, 20, ""); + this.button.displayString = this.value + this.value.name(); } @Override public void draw(ColorPalette colorPalette, int drawX, int drawY, int mouseX, int mouseY) { super.draw(colorPalette, drawX, drawY, mouseX, mouseY); - final int left = this.button.xPosition - 20 - 1; - final int top = this.button.yPosition; + button.xPosition = drawX + boxWidth - button.width - 20; + button.yPosition = drawY + (hasComment ? 8 + mc.fontRendererObj.FONT_HEIGHT / 2 : (getHeight() - button.height) / 2); + button.drawButton(colorPalette, mc, mouseX, mouseY); + final int left = button.xPosition - 20 - 1; + final int top = button.yPosition; GuiUtil.drawBoxWithOutline(left, top, left + 20, top + 20, 255 << 24 | color, colorPalette.COLOR_BUTTON_INDICATOR_BORDER); } @Override - protected void setValue(Enum v) { - this.value = v; - this.color = Minecraft.getMinecraft().fontRendererObj.getColorCode(v.toString().charAt(1)); - this.button.displayString = v + v.name(); - } - - @Override - protected void cycleEnum(int direction) throws IllegalAccessException { - EnumChatFormatting nextColor = (EnumChatFormatting) this.value; - do { - int nextOrdinal = (nextColor.ordinal() + direction) % values.length; - if (nextOrdinal < 0) nextOrdinal += values.length; - nextColor = (EnumChatFormatting) values[nextOrdinal]; - } while (!nextColor.isColor()); - this.setValue(nextColor); - this.field.set(null, nextColor); - this.invokeConfigEvent(); + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IllegalAccessException { + if (mouseButton == 0 && button.mousePressed(mc, mouseX, mouseY)) { + button.playPressSound(mc.getSoundHandler()); + mc.displayGuiScreen(new ColorEnumPickerScreen(parentScreen, field, this.value, + () -> { + try { + this.value = (EnumChatFormatting) this.field.get(null); + this.color = mc.fontRendererObj.getColorCode(this.value.toString().charAt(1)); + this.button.displayString = this.value + this.value.name(); + } catch (IllegalAccessException ignored) {} + invokeConfigEvent(); + })); + return true; + } + return false; } } From 03d77144bbcbd1c239280ec48dd2ec092cedc09d Mon Sep 17 00:00:00 2001 From: PotatoOfPotato <289999293+PotatoOfPotato@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:23:01 +0800 Subject: [PATCH 2/2] details --- .../alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java b/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java index dc50bf31..c9ba0451 100644 --- a/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java +++ b/src/configlib/java/fr/alexdoru/configlib/lib/gui/ColorEnumPickerScreen.java @@ -94,22 +94,22 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { @Override protected void actionPerformed(GuiButton button) { if (button.id == 2000) { - mc.displayGuiScreen(parent); + this.mc.displayGuiScreen(this.parent); return; } if (button instanceof ColorSquareButton) { this.current = ((ColorSquareButton) button).color; try { - field.set(null, this.current); + this.field.set(null, this.current); } catch (IllegalAccessException ignored) {} - if (onPick != null) onPick.run(); + if (this.onPick != null) this.onPick.run(); } } @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { if (keyCode == 1) { - mc.displayGuiScreen(parent); + this.mc.displayGuiScreen(this.parent); return; } super.keyTyped(typedChar, keyCode);