/* * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod * Copyright (C) 2021 cyoung06 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package kr.syeyoung.dungeonsguide.config.guiconfig; import com.google.common.base.Function; import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; import kr.syeyoung.dungeonsguide.features.AbstractFeature; import kr.syeyoung.dungeonsguide.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.gui.MPanel; import kr.syeyoung.dungeonsguide.gui.elements.*; import kr.syeyoung.dungeonsguide.utils.RenderUtils; import lombok.Getter; import lombok.Setter; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import java.awt.*; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.*; public class RootConfigPanel extends MPanelScaledGUI { private MScrollablePanel navigationScroll; private MList navigation = new MList(); private MScrollablePanel contentScroll; private final Map pages = new HashMap(); @Getter @Setter private Function pageGenerator = ConfigPanelCreator.INSTANCE; @Getter private String currentPage = ""; private GuiConfigV2 gui; private long lastPageSet = System.currentTimeMillis(); private MTextField search; private MButton guiRelocate; private MButton github, discord; private final Stack history = new Stack(); public String getSearchWord() { return search.getText().trim().toLowerCase(); } public RootConfigPanel(GuiConfigV2 guiConfigV2) { this.gui = guiConfigV2; search = new MTextField() { @Override public void edit(String str) { setupNavigation(); setCurrentPageAndPushHistory(""); if (!categoryMap.containsKey(lastOpenCategory)) { for (Map.Entry nestedCategoryMPanelEntry : categoryMap.entrySet()) { if (nestedCategoryMPanelEntry.getValue() instanceof MCategoryElement) { setCurrentPageAndPushHistory(nestedCategoryMPanelEntry.getKey().categoryFull()); lastOpenCategory = nestedCategoryMPanelEntry.getKey(); break; } } } for (Map.Entry nestedCategoryMPanelEntry : categoryMap.entrySet()) { if (nestedCategoryMPanelEntry.getValue() instanceof MCollapsable) { ((MCollapsable) nestedCategoryMPanelEntry.getValue()).setCollapsed(false); } } rePlaceElements(); } }; search.setPlaceHolder("Search..."); add(search); guiRelocate = new MButton(); guiRelocate.setText("Edit Gui Locations"); guiRelocate.setOnActionPerformed(() -> { Minecraft.getMinecraft().displayGuiScreen(new GuiGuiLocationConfig(gui, null)); guiRelocate.setIsclicked(false); }); guiRelocate.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); add(guiRelocate); discord = new MButton(); github = new MButton(); discord.setText("Discord"); github.setText("Github"); discord.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); github.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); github.setOnActionPerformed(() -> { try { Desktop.getDesktop().browse(new URI("https://github.com/Dungeons-Guide/Skyblock-Dungeons-Guide/")); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }); discord.setOnActionPerformed(() -> { try { Desktop.getDesktop().browse(new URI("https://discord.gg/VuxayCWGE8")); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }); add(discord); add(github); navigationScroll = new MScrollablePanel(1); navigationScroll.setHideScrollBarWhenNotNecessary(false); add(navigationScroll); navigationScroll.add(navigation); contentScroll = new MScrollablePanel(3); contentScroll.setHideScrollBarWhenNotNecessary(true); add(contentScroll); setupNavigation(); navigation.setGap(0); navigation.setDrawLine(false); setCurrentPageAndPushHistory("ROOT"); rePlaceElements(); search.setFocused(true); } private Map categoryMap = new HashMap<>(); private NestedCategory lastOpenCategory; private void setupNavigation() { categoryMap.clear(); for (MPanel childComponent : navigation.getChildComponents()) { navigation.remove(childComponent); } NestedCategory root = new NestedCategory("ROOT"); Set categoryAllowed = new HashSet<>(); String search = this.search.getText().trim().toLowerCase(); for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { if (search.isEmpty()) { categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); } else if (abstractFeature.getName().toLowerCase().contains(search)) { categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); } else if (abstractFeature.getDescription().toLowerCase().contains(search)) { categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); } } for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { String category = abstractFeature.getCategory(); boolean test =false; for (String s : categoryAllowed) { if (s.startsWith("ROOT."+category+".")) { test = true; break; } } if (!test) continue; NestedCategory currentRoot = root; for (String s : category.split("\\.")) { NestedCategory finalCurrentRoot = currentRoot; if (currentRoot.children().containsKey(s)) currentRoot = currentRoot.children().get(s); else { currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull()+"."+s)); } } } for (NestedCategory value : root.children().values()) { setupNavigationRecursive(value, navigation, 0, 17); } ConfigPanelCreator.map.put("ROOT", () -> new MPanelCategory(root, this)); } private void setupNavigationRecursive(NestedCategory nestedCategory, MPanel parent, int depth, int offset) { ConfigPanelCreator.map.put(nestedCategory.categoryFull(), () -> new MPanelCategory(nestedCategory, this)); if (nestedCategory.children().size() == 0) { MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> { setCurrentPageAndPushHistory(nestedCategory.categoryFull()); lastOpenCategory = nestedCategory; }, 13 * depth + 17, offset, this); parent.add(current); categoryMap.put(nestedCategory, current); } else { MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> { setCurrentPageAndPushHistory(nestedCategory.categoryFull()); lastOpenCategory = nestedCategory; }, 3,offset, this); MCollapsable mCollapsable = new MCollapsable(current, this::rePlaceElements); mCollapsable.setLeftPad(offset-13); mCollapsable.getLowerElements().setDrawLine(false); mCollapsable.getLowerElements().setGap(0); mCollapsable.setLeftPadElements(0); parent.add(mCollapsable); categoryMap.put(nestedCategory, mCollapsable); for (NestedCategory value : nestedCategory.children().values()) { setupNavigationRecursive(value, mCollapsable, depth+1, offset+13); } } } public void setCurrentPageAndPushHistory(String currentPage) { if (!this.currentPage.equals(currentPage)) history.push(this.currentPage); lastOpenCategory = null; this.currentPage = currentPage; setupPage(); } public void goBack() { if (history.size() == 0) return; this.currentPage = history.pop(); setupPage(); } private void setupPage() { contentScroll.getContentArea().getChildComponents().forEach(contentScroll.getContentArea()::remove); if (!pages.containsKey(currentPage)) { MPanel page = pageGenerator.apply(currentPage); if (page == null) page = new MNotFound(); pages.put(currentPage, page); } contentScroll.getContentArea().add(pages.get(currentPage)); rePlaceElements(); } public void invalidatePage(String page) { pages.remove(page); if (page.equals(currentPage)) setupPage(); } @Override public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { Dimension effectiveDim = getEffectiveDimension(); Gui.drawRect(0,0, (int) (effectiveDim.width), (int) (effectiveDim.height), RenderUtils.blendAlpha(0x141414, 0.00f)); Gui.drawRect(0,0, (int) (effectiveDim.width), 25, RenderUtils.blendAlpha(0x0, 0.20f)); // Gui.drawRect(navigationScroll.getBounds().x + navigationScroll.getBounds().width - 10, 25, navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.04f)); Gui.drawRect(0, 25,navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.08f)); FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; fr.drawString("DungeonsGuide By syeyoung", (effectiveDim.width - fr.getStringWidth("DungeonsGuide By syeyoung"))/2, (25 - fr.FONT_HEIGHT)/2, 0xFF02EE67); } @Override public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) { super.render0(parentScale, parentPoint, parentClip, absMousex0, absMousey0, relMousex0, relMousey0, partialTicks); Dimension effectiveDim = getEffectiveDimension(); Gui.drawRect(0,24, (int) (Double.min(1, (System.currentTimeMillis() - lastPageSet)/1000.0) * effectiveDim.width), 25, 0xFF02EE67); } @Override public void setBounds(Rectangle bounds) { super.setBounds(bounds); rePlaceElements(); } @Override public void setScale(double scale) { super.setScale(scale); rePlaceElements(); } private void rePlaceElements() { Dimension effectiveDim = getEffectiveDimension(); navigation.setBounds(new Rectangle(new Point(0,1), new Dimension(Math.max(100, Math.max(navigation.getPreferredSize().width, navigationScroll.getBounds().width-10)), navigation.getPreferredSize().height))); navigation.realignChildren(); navigationScroll.evalulateContentArea(); Rectangle navBound; navigationScroll.setBounds(navBound = new Rectangle(0,50, navigation.getBounds().width+10, effectiveDim.height-50)); contentScroll.setBounds(new Rectangle(navBound.x + navBound.width, 25, effectiveDim.width - navBound.x - navBound.width, effectiveDim.height-25)); search.setBounds(new Rectangle(5,30,navBound.x + navBound.width - 10,15)); guiRelocate.setBounds(new Rectangle(5,5,100,15)); github.setBounds(new Rectangle(effectiveDim.width - 80,5,75,15)); discord.setBounds(new Rectangle(effectiveDim.width - 160,5,75,15)); } }