diff --git a/src/main/java/kamkeel/npcs/client/gui/components/ScrollPanel.java b/src/main/java/kamkeel/npcs/client/gui/components/ScrollPanel.java index bf20c4640..26909322a 100644 --- a/src/main/java/kamkeel/npcs/client/gui/components/ScrollPanel.java +++ b/src/main/java/kamkeel/npcs/client/gui/components/ScrollPanel.java @@ -70,6 +70,15 @@ public class ScrollPanel extends Gui { } } + public void setBackgroundColor(int color) { + this.backgroundColor = color; + } + + public void resetScroll() { + this.scrollY = 0; + this.targetScrollY = 0; + } + public int getContentHeight() { return contentHeight; } diff --git a/src/main/java/kamkeel/npcs/client/gui/modern/DialogEditorPanel.java b/src/main/java/kamkeel/npcs/client/gui/modern/DialogEditorPanel.java index 35d1010fe..c5cad2b12 100644 --- a/src/main/java/kamkeel/npcs/client/gui/modern/DialogEditorPanel.java +++ b/src/main/java/kamkeel/npcs/client/gui/modern/DialogEditorPanel.java @@ -7,9 +7,7 @@ import noppes.npcs.client.gui.util.IDialogEditorListener; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.ScaledResolution; import noppes.npcs.controllers.data.Dialog; -import org.lwjgl.opengl.GL11; import java.util.ArrayList; import java.util.List; @@ -38,9 +36,9 @@ public class DialogEditorPanel extends Gui { protected Dialog dialog; protected boolean dirty = false; protected int currentTab = 0; - protected float scrollY = 0; - protected float targetScrollY = 0; - protected int contentHeight = 0; + + // === Scroll Panel (replaces manual scroll logic) === + protected ScrollPanel scrollPanel; // === Tab Names === protected static final String[] TAB_NAMES = {"Text", "Options", "Feedback", "Settings", "Availability"}; @@ -59,12 +57,6 @@ public class DialogEditorPanel extends Gui { // === Listener === protected IDialogEditorListener listener; - // === Scrollbar === - protected int scrollbarWidth = 6; - protected boolean isDraggingScrollbar = false; - protected int dragStartY; - protected float dragStartScroll; - // === Footer === protected boolean hoverTestBtn = false; protected boolean hoverSaveBtn = false; @@ -76,6 +68,18 @@ public class DialogEditorPanel extends Gui { this.width = width; this.height = height; initTabs(); + initScrollPanel(); + } + + protected void initScrollPanel() { + int contentY = y + headerHeight + tabBarHeight; + int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; + scrollPanel = new ScrollPanel(x, contentY, width, contentAreaH); + scrollPanel.setBackgroundColor(0); // Transparent - we draw our own background + } + + protected int getScrollbarWidth() { + return scrollPanel != null ? 6 : 0; } // === Tab Initialization === @@ -97,8 +101,7 @@ public class DialogEditorPanel extends Gui { public void setDialog(Dialog dialog) { this.dialog = dialog; this.dirty = false; - this.scrollY = 0; - this.targetScrollY = 0; + scrollPanel.resetScroll(); for (DialogEditorTab tab : tabs) { tab.setDialog(dialog); @@ -128,13 +131,6 @@ public class DialogEditorPanel extends Gui { FontRenderer fr = Minecraft.getMinecraft().fontRenderer; - // Update scroll animation - if (Math.abs(scrollY - targetScrollY) > 0.5f) { - scrollY += (targetScrollY - scrollY) * 0.3f; - } else { - scrollY = targetScrollY; - } - // Background drawRect(x, y, x + width, y + height, ModernColors.PANEL_BG_SOLID); @@ -144,44 +140,24 @@ public class DialogEditorPanel extends Gui { // Tab bar drawTabBar(mouseX, mouseY, fr); - // Content area with scissor - int contentY = y + headerHeight + tabBarHeight; - int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; - - Minecraft mc = Minecraft.getMinecraft(); - ScaledResolution sr = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); - int scale = sr.getScaleFactor(); - // Update screen positions for all dropdowns BEFORE scroll translation updateDropdownScreenPositions(); - GL11.glEnable(GL11.GL_SCISSOR_TEST); - GL11.glScissor(x * scale, mc.displayHeight - (contentY + contentAreaH) * scale, - (width - scrollbarWidth) * scale, contentAreaH * scale); + // Draw scrollable content using ScrollPanel + int contentX = x + padding; + int contentW = width - padding * 2 - getScrollbarWidth(); + int startY = y + headerHeight + tabBarHeight + padding; - GL11.glPushMatrix(); - GL11.glTranslatef(0, -scrollY, 0); + scrollPanel.beginDraw(); // Draw current tab content - int contentX = x + padding; - int contentW = width - padding * 2 - scrollbarWidth; - int startY = y + headerHeight + tabBarHeight + padding; - contentHeight = tabs[currentTab].draw(contentX, contentW, startY, mouseX, (int)(mouseY + scrollY), fr); + int contentHeight = tabs[currentTab].draw(contentX, contentW, startY, + mouseX, scrollPanel.toContentY(mouseY), fr); - GL11.glPopMatrix(); - GL11.glDisable(GL11.GL_SCISSOR_TEST); + // Update scroll panel's content height + scrollPanel.setContentHeight(contentHeight); - // Clamp scroll position when content height changes - int maxScroll = Math.max(0, contentHeight - contentAreaH); - if (scrollY > maxScroll) { - scrollY = maxScroll; - targetScrollY = maxScroll; - } - - // Draw scrollbar - if (contentHeight > contentAreaH) { - drawScrollbar(mouseX, mouseY, contentY, contentAreaH); - } + scrollPanel.endDraw(mouseX, mouseY); // Draw expanded dropdowns in SCREEN SPACE (no translation!) drawExpandedDropdownsScreenSpace(mouseX, mouseY); @@ -242,21 +218,6 @@ public class DialogEditorPanel extends Gui { } } - protected void drawScrollbar(int mouseX, int mouseY, int contentY, int contentAreaH) { - int sbX = x + width - scrollbarWidth; - drawRect(sbX, contentY, sbX + scrollbarWidth, contentY + contentAreaH, ModernColors.SCROLLBAR_BG); - - float viewRatio = (float) contentAreaH / contentHeight; - int thumbH = Math.max(20, (int)(contentAreaH * viewRatio)); - int maxScroll = contentHeight - contentAreaH; - int thumbY = maxScroll > 0 ? (int)((contentAreaH - thumbH) * (scrollY / maxScroll)) : 0; - - boolean hoverThumb = mouseX >= sbX && mouseX < sbX + scrollbarWidth && - mouseY >= contentY + thumbY && mouseY < contentY + thumbY + thumbH; - int thumbColor = (hoverThumb || isDraggingScrollbar) ? ModernColors.SCROLLBAR_THUMB_HOVER : ModernColors.SCROLLBAR_THUMB; - drawRect(sbX + 1, contentY + thumbY, sbX + scrollbarWidth - 1, contentY + thumbY + thumbH, thumbColor); - } - protected void drawFooter(int mouseX, int mouseY, FontRenderer fr) { int footerY = y + height - footerHeight; drawRect(x, footerY, x + width, y + height, ModernColors.SECTION_HEADER_BG); @@ -301,7 +262,7 @@ public class DialogEditorPanel extends Gui { protected void updateDropdownScreenPositions() { for (ModernDropdown dropdown : getAllDropdowns()) { - int screenDropdownY = dropdown.getY() - (int)scrollY; + int screenDropdownY = scrollPanel.toScreenY(dropdown.getY()); dropdown.setScreenPosition(dropdown.getX(), screenDropdownY); } } @@ -336,8 +297,7 @@ public class DialogEditorPanel extends Gui { // Tab clicks if (hoveredTab >= 0 && mouseY >= y + headerHeight && mouseY < y + headerHeight + tabBarHeight) { currentTab = hoveredTab; - scrollY = 0; - targetScrollY = 0; + scrollPanel.resetScroll(); closeAllDropdowns(); return true; } @@ -356,14 +316,8 @@ public class DialogEditorPanel extends Gui { return true; } - // Scrollbar - int contentY = y + headerHeight + tabBarHeight; - int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; - int sbX = x + width - scrollbarWidth; - if (contentHeight > contentAreaH && mouseX >= sbX && mouseX < sbX + scrollbarWidth) { - isDraggingScrollbar = true; - dragStartY = mouseY; - dragStartScroll = scrollY; + // Scrollbar - delegate to ScrollPanel + if (scrollPanel.mouseClicked(mouseX, mouseY, button)) { return true; } @@ -381,7 +335,7 @@ public class DialogEditorPanel extends Gui { } // Adjust mouseY for scroll (for components inside scrollable content) - int adjMouseY = (int)(mouseY + scrollY); + int adjMouseY = scrollPanel.toContentY(mouseY); // Delegate to current tab return tabs[currentTab].mouseClicked(mouseX, adjMouseY, button); @@ -393,37 +347,18 @@ public class DialogEditorPanel extends Gui { } public void mouseScrolled(int delta) { - int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; - if (contentHeight <= contentAreaH) return; - - int maxScroll = contentHeight - contentAreaH; - targetScrollY = Math.max(0, Math.min(targetScrollY - delta * 20, maxScroll)); + scrollPanel.mouseScrolled(delta); } public void mouseReleased(int mouseX, int mouseY) { - isDraggingScrollbar = false; + scrollPanel.mouseReleased(mouseX, mouseY); // Let text areas handle mouse release textTab.getTextArea().mouseReleased(mouseX, mouseY); settingsTab.getCommandArea().mouseReleased(mouseX, mouseY); } public void mouseDragged(int mouseX, int mouseY) { - if (isDraggingScrollbar) { - int contentY = y + headerHeight + tabBarHeight; - int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; - int maxScroll = contentHeight - contentAreaH; - - float viewRatio = (float) contentAreaH / contentHeight; - int thumbH = Math.max(20, (int)(contentAreaH * viewRatio)); - int trackH = contentAreaH - thumbH; - - if (trackH > 0) { - int deltaY = mouseY - dragStartY; - float scrollDelta = (deltaY / (float)trackH) * maxScroll; - scrollY = Math.max(0, Math.min(dragStartScroll + scrollDelta, maxScroll)); - targetScrollY = scrollY; - } - } + scrollPanel.mouseDragged(mouseX, mouseY); textTab.getTextArea().mouseDragged(mouseX, mouseY); settingsTab.getCommandArea().mouseDragged(mouseX, mouseY); } @@ -457,6 +392,10 @@ public class DialogEditorPanel extends Gui { this.y = y; this.width = width; this.height = height; + // Update scroll panel bounds + int contentY = y + headerHeight + tabBarHeight; + int contentAreaH = height - headerHeight - tabBarHeight - footerHeight; + scrollPanel.setBounds(x, contentY, width, contentAreaH); } public void setListener(IDialogEditorListener listener) { diff --git a/src/main/java/kamkeel/npcs/client/gui/modern/ModernColorPicker.java b/src/main/java/kamkeel/npcs/client/gui/modern/ModernColorPicker.java index 1d047c26e..cd91c9f6a 100644 --- a/src/main/java/kamkeel/npcs/client/gui/modern/ModernColorPicker.java +++ b/src/main/java/kamkeel/npcs/client/gui/modern/ModernColorPicker.java @@ -195,14 +195,27 @@ public class ModernColorPicker extends ModernSubGuiInterface { /** * Check if mouse is inside the color wheel area. + * Uses circular bounds for accurate detection. */ private boolean isInsideWheel(int mouseX, int mouseY) { - return mouseX >= wheelX && mouseX < wheelX + wheelSize && - mouseY >= wheelY && mouseY < wheelY + wheelSize; + // First check rectangle bounds + if (mouseX < wheelX || mouseX >= wheelX + wheelSize || + mouseY < wheelY || mouseY >= wheelY + wheelSize) { + return false; + } + // Then check circular bounds (wheel is circular) + int centerX = wheelX + wheelSize / 2; + int centerY = wheelY + wheelSize / 2; + int radius = wheelSize / 2; + int dx = mouseX - centerX; + int dy = mouseY - centerY; + return (dx * dx + dy * dy) <= (radius * radius); } /** * Pick color from the wheel texture at clicked position. + * Uses the same 4x multiplier as the original SubGuiColorSelector + * since the texture is 480x480 and we display at variable size. */ private void pickColorFromWheel(int mouseX, int mouseY) { InputStream stream = null; @@ -210,8 +223,9 @@ public class ModernColorPicker extends ModernSubGuiInterface { IResource resource = mc.getResourceManager().getResource(COLOR_WHEEL); BufferedImage image = ImageIO.read(stream = resource.getInputStream()); - // Scale mouse position to texture coordinates - // The texture is assumed to be a certain size, compute ratio + // Calculate texture coordinates using the same ratio as original + // Original: draws 120x120, texture is 480x480, uses *4 multiplier + // We draw wheelSize x wheelSize, so scale proportionally int texX = (mouseX - wheelX) * image.getWidth() / wheelSize; int texY = (mouseY - wheelY) * image.getHeight() / wheelSize; @@ -219,8 +233,13 @@ public class ModernColorPicker extends ModernSubGuiInterface { texX = Math.max(0, Math.min(texX, image.getWidth() - 1)); texY = Math.max(0, Math.min(texY, image.getHeight() - 1)); - color = image.getRGB(texX, texY) & 0xFFFFFF; - hexField.setText(getHexString()); + // Get pixel color, ignoring alpha and transparent pixels + int pixel = image.getRGB(texX, texY); + int alpha = (pixel >> 24) & 0xFF; + if (alpha > 0) { + color = pixel & 0xFFFFFF; + hexField.setText(getHexString()); + } } catch (IOException e) { // Ignore errors diff --git a/src/main/java/kamkeel/npcs/client/gui/modern/ModernSoundSelector.java b/src/main/java/kamkeel/npcs/client/gui/modern/ModernSoundSelector.java index 78c5ac74e..999e04926 100644 --- a/src/main/java/kamkeel/npcs/client/gui/modern/ModernSoundSelector.java +++ b/src/main/java/kamkeel/npcs/client/gui/modern/ModernSoundSelector.java @@ -21,7 +21,7 @@ import java.util.*; * Features two-column layout (domains | sounds), search fields, and preview button. */ public class ModernSoundSelector extends ModernSubGuiInterface { - +` // Selected values private String selectedDomain; public ResourceLocation selectedResource; diff --git a/src/main/java/kamkeel/npcs/client/gui/modern/ModernSubGuiInterface.java b/src/main/java/kamkeel/npcs/client/gui/modern/ModernSubGuiInterface.java index 349b05c5a..200ed1eff 100644 --- a/src/main/java/kamkeel/npcs/client/gui/modern/ModernSubGuiInterface.java +++ b/src/main/java/kamkeel/npcs/client/gui/modern/ModernSubGuiInterface.java @@ -17,6 +17,8 @@ public class ModernSubGuiInterface extends SubGuiInterface { // Overlay color (semi-transparent black) protected int overlayColor = 0x80000000; + // Whether to draw overlay over entire screen (true) or just around panel (false) + protected boolean fullScreenOverlay = false; // Panel colors protected int panelBg = ModernColors.PANEL_BG_SOLID; @@ -36,8 +38,20 @@ public class ModernSubGuiInterface extends SubGuiInterface { @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { - // Draw semi-transparent overlay over entire screen - Gui.drawRect(0, 0, width, height, overlayColor); + // Draw semi-transparent overlay + // Only darken a region around the panel, not the entire screen + // This allows the diagram/tree view to remain visible + if (fullScreenOverlay) { + Gui.drawRect(0, 0, width, height, overlayColor); + } else { + // Draw overlay only behind and slightly around the panel + int margin = 20; + int overlayLeft = Math.max(0, guiLeft - margin); + int overlayTop = Math.max(0, guiTop - margin); + int overlayRight = Math.min(width, guiLeft + xSize + margin); + int overlayBottom = Math.min(height, guiTop + ySize + margin); + Gui.drawRect(overlayLeft, overlayTop, overlayRight, overlayBottom, overlayColor); + } // Draw modern panel background drawModernPanel(); @@ -144,6 +158,14 @@ public class ModernSubGuiInterface extends SubGuiInterface { this.overlayColor = color; } + /** + * Set whether to draw overlay over entire screen or just around panel. + * Default is false (localized overlay to preserve visibility of parent content). + */ + public void setFullScreenOverlay(boolean fullScreen) { + this.fullScreenOverlay = fullScreen; + } + /** * Get content area Y start (after header if present). */ diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiAdvancedDiagram.java b/src/main/java/noppes/npcs/client/gui/util/GuiAdvancedDiagram.java index 3496c88e6..d851f711c 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiAdvancedDiagram.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiAdvancedDiagram.java @@ -399,7 +399,9 @@ public abstract class GuiAdvancedDiagram extends Gui { // ===== Drawing ===== public void drawDiagram(int mouseX, int mouseY) { - if (parent != null && parent.hasSubGui()) return; + // Note: We removed the hasSubGui() check here. The diagram should continue + // drawing even when a SubGui is open - the SubGui renders on top via z-order. + // Previously this caused the entire diagram to disappear when opening dialogs. if (isWithin(mouseX, mouseY)) { handleMouseScroll(Mouse.getDWheel()); diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiNpcTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiNpcTextArea.java index 144948172..f131544ac 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiNpcTextArea.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiNpcTextArea.java @@ -94,6 +94,74 @@ public class GuiNpcTextArea extends GuiNpcTextField { public boolean textboxKeyTyped(char c, int i) { if (isFocused() && canEdit) { String originalText = getText(); + + // Handle Ctrl+A (Select All) - char code 1 + if (GuiScreen.isCtrlKeyDown() && (i == Keyboard.KEY_A || c == 1)) { + cursorPosition = originalText.length(); + setSelectionPos(0); + return true; + } + + // Handle Ctrl+C (Copy) - char code 3 + if (GuiScreen.isCtrlKeyDown() && (i == Keyboard.KEY_C || c == 3)) { + String selected = getSelectedText(); + if (selected != null && !selected.isEmpty()) { + GuiScreen.setClipboardString(selected); + } + return true; + } + + // Handle Ctrl+V (Paste) - char code 22 + if (GuiScreen.isCtrlKeyDown() && (i == Keyboard.KEY_V || c == 22)) { + String clipboard = GuiScreen.getClipboardString(); + if (clipboard != null && !clipboard.isEmpty()) { + // Delete selected text first if any + String selected = getSelectedText(); + int selStart = getSelectionEnd(); + int selEnd = cursorPosition; + if (selStart > selEnd) { + int tmp = selStart; + selStart = selEnd; + selEnd = tmp; + } + if (selected != null && !selected.isEmpty()) { + String before = originalText.substring(0, selStart); + String after = originalText.substring(selEnd); + this.setText(before + clipboard + after); + cursorPosition = selStart + clipboard.length(); + } else { + String before = originalText.substring(0, cursorPosition); + String after = originalText.substring(cursorPosition); + this.setText(before + clipboard + after); + cursorPosition += clipboard.length(); + } + updateLineList(); + } + return true; + } + + // Handle Ctrl+X (Cut) - char code 24 + if (GuiScreen.isCtrlKeyDown() && (i == Keyboard.KEY_X || c == 24)) { + String selected = getSelectedText(); + if (selected != null && !selected.isEmpty()) { + GuiScreen.setClipboardString(selected); + // Delete selected text + int selStart = getSelectionEnd(); + int selEnd = cursorPosition; + if (selStart > selEnd) { + int tmp = selStart; + selStart = selEnd; + selEnd = tmp; + } + String before = originalText.substring(0, selStart); + String after = originalText.substring(selEnd); + this.setText(before + after); + cursorPosition = selStart; + updateLineList(); + } + return true; + } + // Handle newline specially - insert and return immediately if (c == '\r' || c == '\n') { this.setText(originalText.substring(0, cursorPosition) + c + originalText.substring(cursorPosition)); diff --git a/src/main/java/noppes/npcs/client/gui/util/SubGuiInterface.java b/src/main/java/noppes/npcs/client/gui/util/SubGuiInterface.java index b10ba84bd..e3335ee68 100644 --- a/src/main/java/noppes/npcs/client/gui/util/SubGuiInterface.java +++ b/src/main/java/noppes/npcs/client/gui/util/SubGuiInterface.java @@ -1,10 +1,21 @@ package noppes.npcs.client.gui.util; +import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiScreen; public class SubGuiInterface extends GuiNPCInterface { public GuiScreen parent; + // === Modern Style Option === + protected boolean useModernStyle = false; + protected int modernOverlayColor = 0x80000000; + protected int modernPanelBg = 0xFF1E1E2E; + protected int modernPanelBorder = 0xFF4488CC; + protected int modernHeaderBg = 0xFF2A2A3A; + protected int modernHeaderText = 0xFFFFFF; + protected String modernHeaderTitle = null; + protected int modernHeaderHeight = 20; + @Override public void save() { @@ -34,6 +45,105 @@ public class SubGuiInterface extends GuiNPCInterface { @Override public void drawScreen(int i, int j, float f) { - super.drawScreen(i, j, f); + if (useModernStyle) { + drawModernStyle(i, j, f); + } else { + super.drawScreen(i, j, f); + } + } + + /** + * Draw with modern styling - dark overlay, modern panel, accent border. + */ + protected void drawModernStyle(int mouseX, int mouseY, float partialTicks) { + // Draw semi-transparent overlay behind panel + int margin = 20; + int overlayLeft = Math.max(0, guiLeft - margin); + int overlayTop = Math.max(0, guiTop - margin); + int overlayRight = Math.min(width, guiLeft + xSize + margin); + int overlayBottom = Math.min(height, guiTop + ySize + margin); + Gui.drawRect(overlayLeft, overlayTop, overlayRight, overlayBottom, modernOverlayColor); + + // Draw panel border + Gui.drawRect(guiLeft - 1, guiTop - 1, guiLeft + xSize + 1, guiTop + ySize + 1, modernPanelBorder); + + // Draw panel background + Gui.drawRect(guiLeft, guiTop, guiLeft + xSize, guiTop + ySize, modernPanelBg); + + // Draw header if set + if (modernHeaderTitle != null) { + Gui.drawRect(guiLeft, guiTop, guiLeft + xSize, guiTop + modernHeaderHeight, modernHeaderBg); + int textW = fontRendererObj.getStringWidth(modernHeaderTitle); + int textX = guiLeft + (xSize - textW) / 2; + int textY = guiTop + (modernHeaderHeight - fontRendererObj.FONT_HEIGHT) / 2; + fontRendererObj.drawString(modernHeaderTitle, textX, textY, modernHeaderText); + } + + // Draw buttons, labels, textfields, scrolls from parent + for (Object obj : buttonList) { + if (obj instanceof net.minecraft.client.gui.GuiButton) { + ((net.minecraft.client.gui.GuiButton) obj).drawButton(mc, mouseX, mouseY); + } + } + for (GuiNpcLabel label : labels.values()) { + label.drawLabel(this, fontRendererObj); + } + for (GuiNpcTextField tf : textfields.values()) { + tf.drawTextBox(mouseX, mouseY); + } + for (GuiCustomScroll scroll : scrolls.values()) { + scroll.drawScreen(mouseX, mouseY, 0, scroll.isMouseOver(mouseX, mouseY) ? org.lwjgl.input.Mouse.getDWheel() : 0); + } + + // Allow subclasses to draw custom content + drawModernContent(mouseX, mouseY, partialTicks); + } + + /** + * Override to draw custom content in modern style. + */ + protected void drawModernContent(int mouseX, int mouseY, float partialTicks) { + // Override in subclasses + } + + // === Modern Style Configuration === + + /** + * Enable modern styling for this SubGui. + */ + public void setUseModernStyle(boolean modern) { + this.useModernStyle = modern; + if (modern) { + drawDefaultBackground = false; + } + } + + /** + * Set the header title for modern style. Pass null to disable header. + */ + public void setModernHeaderTitle(String title) { + this.modernHeaderTitle = title; + } + + /** + * Set panel colors for modern style. + */ + public void setModernPanelColors(int background, int border) { + this.modernPanelBg = background; + this.modernPanelBorder = border; + } + + /** + * Get content area Y start (after header if present). + */ + protected int getModernContentY() { + return guiTop + (modernHeaderTitle != null ? modernHeaderHeight : 0); + } + + /** + * Get content area height (excluding header if present). + */ + protected int getModernContentHeight() { + return ySize - (modernHeaderTitle != null ? modernHeaderHeight : 0); } }