diff --git a/src/tel/eden/mod/gui/TerritoryLossBlacklistScreen.java b/src/tel/eden/mod/gui/TerritoryLossBlacklistScreen.java index 9714a90..ccc450c 100644 --- a/src/tel/eden/mod/gui/TerritoryLossBlacklistScreen.java +++ b/src/tel/eden/mod/gui/TerritoryLossBlacklistScreen.java @@ -1,7 +1,6 @@ package tel.eden.mod.gui; import java.util.ArrayList; -import java.util.List; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; @@ -45,7 +44,6 @@ public final class TerritoryLossBlacklistScreen extends EdenReferenceScreen { private final Screen parent; private final BridgeConfig config; - private final List rows = new ArrayList<>(); private EdenPanelLayout layout; private EditBox addBox; @@ -68,7 +66,6 @@ protected void init() { super.init(); updateReferenceSpace(); layout = EdenPanelLayout.centered(virtualWidth, virtualHeight, BASE_PANEL_WIDTH, BASE_PANEL_HEIGHT); - rows.clear(); addBox = new EditBox(this.font, layout.x(PANEL_PADDING), layout.y(INPUT_Y), layout.w(INPUT_WIDTH), layout.h(20), Component.literal("Territory name")); addBox.setMaxLength(100); @@ -85,21 +82,7 @@ protected void init() { config.territoryLossBlacklist = new ArrayList<>(BridgeConfig.DEFAULT_TERRITORY_LOSS_BLACKLIST); } - for (String territory : config.territoryLossBlacklist) { - if (territory == null || territory.isBlank()) { - continue; - } - rows.add(createRow(territory)); - } - scrollOffset = Math.max(0, Math.min(scrollOffset, maxScrollOffset())); - layoutRows(); - } - - private BlacklistRow createRow(String territory) { - Button removeButton = Button.builder(Component.literal("Remove"), button -> onDelete(territory)).bounds(0, 0, layout.w(REMOVE_WIDTH), layout.h(ROW_BUTTON_HEIGHT)).build(); - this.addWidget(removeButton); - return new BlacklistRow(territory, removeButton); } private void onAdd() { @@ -111,43 +94,34 @@ private void onAdd() { if (!exists) { config.territoryLossBlacklist.add(0, text); config.save(); + addBox.setValue(""); + scrollOffset = 0; } - this.minecraft.setScreen(new TerritoryLossBlacklistScreen(parent, config, 0)); } private void onDelete(String territory) { config.territoryLossBlacklist.remove(territory); config.save(); - this.minecraft.setScreen(new TerritoryLossBlacklistScreen(parent, config, scrollOffset)); + scrollOffset = Math.max(0, Math.min(scrollOffset, maxScrollOffset())); } private void onReset() { config.territoryLossBlacklist = new ArrayList<>(BridgeConfig.DEFAULT_TERRITORY_LOSS_BLACKLIST); config.save(); - this.minecraft.setScreen(new TerritoryLossBlacklistScreen(parent, config, 0)); + scrollOffset = 0; } private int maxScrollOffset() { - return Math.max(0, rows.size() - VISIBLE_ROWS); + return Math.max(0, config.territoryLossBlacklist.size() - VISIBLE_ROWS); } - private void layoutRows() { - for (int index = 0; index < rows.size(); index++) { - BlacklistRow row = rows.get(index); - int visibleIndex = index - scrollOffset; - boolean inView = visibleIndex >= 0 && visibleIndex < VISIBLE_ROWS; - row.removeButton.visible = inView; - row.removeButton.active = inView; - if (!inView) { - continue; - } - - int rowTop = layout.y(LIST_Y + 2 + visibleIndex * ROW_HEIGHT); - row.removeButton.setX(layout.x(REMOVE_X)); - row.removeButton.setY(rowTop + layout.h(ROW_BUTTON_TOP_OFFSET)); - row.removeButton.setWidth(layout.w(REMOVE_WIDTH)); - row.removeButton.setHeight(layout.h(ROW_BUTTON_HEIGHT)); - } + private void drawRemoveButton(GuiGraphics g, int x, int y, int width, int height, boolean hovered) { + int fill = hovered ? 0xFF777777 : 0xFF5A5A5A; + g.fill(x, y, x + width, y + height, fill); + g.fill(x, y, x + width, y + 1, 0xFFD8D8D8); + g.fill(x, y, x + 1, y + height, 0xFFD8D8D8); + g.fill(x + width - 1, y, x + width, y + height, 0xFF222222); + g.fill(x, y + height - 1, x + width, y + height, 0xFF222222); } @Override @@ -165,28 +139,32 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { int listHeight = layout.h(ROW_HEIGHT * VISIBLE_ROWS + 4); graphics.fill(listLeft, listTop, listLeft + listWidth, listTop + listHeight, 0x22000000); - layoutRows(); - graphics.enableScissor(listLeft, listTop, listLeft + listWidth, listTop + listHeight); for (int visible = 0; visible < VISIBLE_ROWS; visible++) { int index = scrollOffset + visible; - if (index >= rows.size()) { + if (index >= config.territoryLossBlacklist.size()) { break; } - BlacklistRow row = rows.get(index); + String territory = config.territoryLossBlacklist.get(index); int rowTop = layout.y(LIST_Y + 2 + visible * ROW_HEIGHT); graphics.fill(layout.x(ROW_X), rowTop, layout.x(ROW_X + ROW_WIDTH), rowTop + layout.h(ROW_INNER_HEIGHT), 0x44282828); - int textWidth = layout.x(REMOVE_X) - layout.x(NAME_X) - layout.w(8); - graphics.drawString(this.font, trimToWidth(row.name, textWidth), layout.x(NAME_X), rowTop + layout.h(7), 0xFFFFFFFF); - row.removeButton.render(graphics, scaledMouseX, scaledMouseY, delta); + int removeLeft = layout.x(REMOVE_X); + int removeTop = rowTop + layout.h(ROW_BUTTON_TOP_OFFSET); + int removeWidth = layout.w(REMOVE_WIDTH); + int removeHeight = layout.h(ROW_BUTTON_HEIGHT); + boolean hovered = isRemoveHovered(scaledMouseX, scaledMouseY, index); + drawRemoveButton(graphics, removeLeft, removeTop, removeWidth, removeHeight, hovered); + graphics.drawCenteredString(this.font, "Remove", removeLeft + (removeWidth / 2), removeTop + ((removeHeight - 9) / 2) + 1, 0xFFFFFFFF); + + int textWidth = removeLeft - layout.x(NAME_X) - layout.w(8); + graphics.drawString(this.font, trimToWidth(territory, textWidth), layout.x(NAME_X), rowTop + layout.h(7), 0xFFFFFFFF); } - graphics.disableScissor(); - layout.drawScrollbar(graphics, layout.x(SCROLLBAR_X), listTop, layout.w(8), listHeight, VISIBLE_ROWS, rows.size(), scrollOffset); + layout.drawScrollbar(graphics, layout.x(SCROLLBAR_X), listTop, layout.w(8), listHeight, VISIBLE_ROWS, config.territoryLossBlacklist.size(), scrollOffset); super.render(graphics, scaledMouseX, scaledMouseY, delta); graphics.drawCenteredString(this.font, this.title, layout.centerX(), layout.y(12), 0xFFFFFFFF); - if (rows.isEmpty()) { + if (config.territoryLossBlacklist.isEmpty()) { graphics.drawCenteredString(this.font, "Blacklist is empty (all territories will play sound)", layout.centerX(), layout.y(110), 0xFFAAAAAA); } popReferencePose(graphics); @@ -202,10 +180,18 @@ private String trimToWidth(String text, int width) { @Override public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) { MouseButtonEvent scaled = rescale(event); - if (scaled.button() == 0 && isOverScrollbar(scaled.x(), scaled.y())) { - draggingScrollbar = true; - updateScrollFromMouse(scaled.y()); - return true; + if (scaled.button() == 0) { + if (isOverScrollbar(scaled.x(), scaled.y())) { + draggingScrollbar = true; + updateScrollFromMouse(scaled.y()); + return true; + } + + int row = rowAt(scaled.x(), scaled.y()); + if (row >= 0 && isRemoveHovered(scaled.x(), scaled.y(), row)) { + onDelete(config.territoryLossBlacklist.get(row)); + return true; + } } if (scaled.button() == 0 && addBox != null) { if (addBox.isMouseOver(scaled.x(), scaled.y())) { @@ -218,6 +204,26 @@ public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) { return super.mouseClicked(scaled, doubleClick); } + private int rowAt(double mouseX, double mouseY) { + if (!isOverList(mouseX, mouseY)) { + return -1; + } + int row = ((int) mouseY - layout.y(LIST_Y)) / layout.h(ROW_HEIGHT); + int index = scrollOffset + row; + return index >= 0 && index < config.territoryLossBlacklist.size() ? index : -1; + } + + private boolean isRemoveHovered(double mouseX, double mouseY, int index) { + int visibleRow = index - scrollOffset; + if (visibleRow < 0 || visibleRow >= VISIBLE_ROWS) { + return false; + } + int rowTop = layout.y(LIST_Y + 2 + visibleRow * ROW_HEIGHT); + int removeLeft = layout.x(REMOVE_X); + int removeTop = rowTop + layout.h(ROW_BUTTON_TOP_OFFSET); + return mouseX >= removeLeft && mouseX <= removeLeft + layout.w(REMOVE_WIDTH) && mouseY >= removeTop && mouseY <= removeTop + layout.h(ROW_BUTTON_HEIGHT); + } + @Override public boolean keyPressed(KeyEvent event) { if (addBox != null && addBox.isFocused()) { @@ -278,32 +284,35 @@ public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, doubl return true; } scrollOffset = Math.max(0, Math.min(maxScrollOffset(), scrollOffset - (int) Math.signum(scrollY))); - layoutRows(); return true; } private boolean isOverList(double mouseX, double mouseY) { - return mouseX >= layout.x(LIST_X) && mouseX <= layout.x(LIST_X + LIST_WIDTH) && mouseY >= layout.y(LIST_Y) && mouseY <= layout.y(LIST_Y + ROW_HEIGHT * VISIBLE_ROWS + 4); + int left = layout.x(LIST_X); + int top = layout.y(LIST_Y); + return mouseX >= left && mouseX <= left + layout.w(LIST_WIDTH) && mouseY >= top && mouseY <= top + layout.h(ROW_HEIGHT * VISIBLE_ROWS + 4); } private boolean isOverScrollbar(double mouseX, double mouseY) { - return mouseX >= layout.x(SCROLLBAR_X) && mouseX <= layout.x(LIST_X + LIST_WIDTH) && mouseY >= layout.y(LIST_Y) && mouseY <= layout.y(LIST_Y + ROW_HEIGHT * VISIBLE_ROWS + 4); + int barX = layout.x(SCROLLBAR_X); + int top = layout.y(LIST_Y); + return mouseX >= barX && mouseX <= barX + layout.w(8) && mouseY >= top && mouseY <= top + layout.h(ROW_HEIGHT * VISIBLE_ROWS + 4); } private void updateScrollFromMouse(double mouseY) { - if (maxScrollOffset() == 0) { + int maxOffset = maxScrollOffset(); + if (maxOffset == 0) { scrollOffset = 0; return; } int trackTop = layout.y(LIST_Y); int trackHeight = layout.h(ROW_HEIGHT * VISIBLE_ROWS + 4); - int thumbHeight = Math.max(layout.h(18), Math.round(trackHeight * (VISIBLE_ROWS / (float) rows.size()))); + int thumbHeight = Math.max(layout.h(18), Math.round(trackHeight * (VISIBLE_ROWS / (float) config.territoryLossBlacklist.size()))); double relative = mouseY - trackTop - thumbHeight / 2.0; double range = Math.max(1, trackHeight - thumbHeight); double percent = Math.max(0.0, Math.min(1.0, relative / range)); - scrollOffset = (int) Math.round(percent * maxScrollOffset()); - layoutRows(); + scrollOffset = (int) Math.round(percent * maxOffset); } @Override @@ -311,14 +320,4 @@ public void onClose() { config.save(); this.minecraft.setScreen(parent); } - - private static final class BlacklistRow { - private final String name; - private final Button removeButton; - - private BlacklistRow(String name, Button removeButton) { - this.name = name; - this.removeButton = removeButton; - } - } }