All Downloads are FREE. Search and download functionalities are using the official Maven repository.

top.hendrixshen.magiclib.impl.malilib.config.gui.MagicConfigGui Maven / Gradle / Ivy

There is a newer version: 0.8.41
Show newest version
/*
 * This file is part of the TweakerMore project, licensed under the
 * GNU Lesser General Public License v3.0
 *
 * Copyright (C) 2023  Fallen_Breath and contributors
 *
 * TweakerMore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TweakerMore 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with TweakerMore.  If not, see .
 */

package top.hendrixshen.magiclib.impl.malilib.config.gui;

import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
import fi.dy.masa.malilib.config.IConfigResettable;
import fi.dy.masa.malilib.gui.GuiBase;
import fi.dy.masa.malilib.gui.GuiConfigsBase;
import fi.dy.masa.malilib.gui.GuiTextFieldGeneric;
import fi.dy.masa.malilib.gui.button.ButtonGeneric;
import fi.dy.masa.malilib.gui.widgets.WidgetBase;
import fi.dy.masa.malilib.gui.widgets.WidgetSearchBar;
import fi.dy.masa.malilib.interfaces.IStringValue;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.class_4587;
import org.jetbrains.annotations.NotNull;
import top.hendrixshen.magiclib.MagicLib;
import top.hendrixshen.magiclib.api.i18n.I18n;
import top.hendrixshen.magiclib.api.malilib.annotation.Config;
import top.hendrixshen.magiclib.api.malilib.config.MagicConfigManager;
import top.hendrixshen.magiclib.api.malilib.config.option.MagicIConfigBase;
import top.hendrixshen.magiclib.impl.malilib.config.ConfigContainer;
import top.hendrixshen.magiclib.mixin.malilib.accessor.WidgetSearchBarAccessor;
import top.hendrixshen.magiclib.util.minecraft.render.RenderUtil;
import top.hendrixshen.magiclib.util.serializable.JsonSaveAble;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * Reference to TweakerMore
 */
public class MagicConfigGui extends GuiConfigsBase {
    private final String identifier;
    private final MagicConfigManager configManager;
    private final Supplier titleProvider;
    private final List hoveringWidgets = Lists.newArrayList();
    @Setter
    private WidgetSearchBar searchBar = null;

    public MagicConfigGui(String identifier, MagicConfigManager configManager,
                          String title) {
        this(identifier, configManager, () -> title);
    }

    public MagicConfigGui(String identifier, MagicConfigManager configManager,
                          @NotNull Supplier titleProvider) {
        super(10, 50, identifier, null, titleProvider.get());
        this.identifier = identifier;
        this.configManager = configManager;
        this.titleProvider = titleProvider;
    }

    @Override
    public void initGui() {
        super.initGui();
        this.clearOptions();
        this.hoveringWidgets.clear();
        this.setTitle(this.titleProvider.get());
        int x = 10;
        int y = 26;

        for (String category : this.configManager.getCategories()) {
            if (this.configManager.getContainers(category).stream()
                    .filter(this::filterUnsatisfiedConfig)
                    .noneMatch(this::isValidConfig)) {
                continue;
            }

            x += this.createNavigationButton(x, y, category);
        }

        x = this.width - 11;
        x = this.initSortingStrategyDropDownList(x) - 5;

        if (this.searchBar != null) {
            GuiTextFieldGeneric searchBox = ((WidgetSearchBarAccessor) this.searchBar).magiclib$getSearchBox();
            int deltaWidth = Math.max(50, x - this.searchBar.getX()) - this.searchBar.getWidth();
            this.searchBar.setWidth(this.searchBar.getWidth() + deltaWidth);
            searchBox.setWidth(searchBox.getWidth() + deltaWidth);
        }

        this.initBottomLine();
    }

    @Override
    public List getConfigs() {
        Comparator nameComparator = Comparator.comparing(c -> c.getConfig().getName(),
                String::compareToIgnoreCase);
        List configs = this.getCurrentContainers().stream()
                .filter(this::filterUnsatisfiedConfig)
                .filter(this::isValidConfig)
                .sorted(this.configManager.getGuiSetting().getSortingStrategy()
                        .getComparator().thenComparing(nameComparator))
                .map(ConfigContainer::getConfig)
                .collect(Collectors.toList());
        return ConfigOptionWrapper.createFor(configs);
    }

    public boolean hideUnAvailableConfigs() {
        return false;
    }

    public boolean isDebug() {
        return false;
    }

    public boolean isDevOnly() {
        return this.isDebug() && MagicLib.getInstance().getCurrentPlatform().isDevelopmentEnvironment();
    }

    // Dev & debug check.
    @SuppressWarnings("RedundantIfStatement")
    private boolean isValidConfig(@NotNull ConfigContainer configContainer) {
        // Hide debug configs unless debug mode on.
        if (configContainer.isDebugOnly() && !this.isDebug()) {
            return false;
        } else if (configContainer.isDevOnly() && !this.isDevOnly()) {
            // Hide dev only configs unless debug mode on and is dev env.
            return false;
        }

        return true;
    }

    private boolean filterUnsatisfiedConfig(ConfigContainer configContainer) {
        return !this.hideUnAvailableConfigs() || configContainer.isSatisfied();
    }

    private Collection getCurrentContainers() {
        return this.configManager.getContainers(this.configManager.getGuiSetting().category);
    }

    private  int initDropDownList(int x, @NotNull List entries, T defaultValue,
                                                          Supplier valueGetter, Consumer valueSetter,
                                                          String hoverTextKey,
                                                          @NotNull Consumer> postProcessor) {
        int y = this.getListY() + 3;
        int height = 16;
        int maxTextWidth = entries.stream().
                filter(Objects::nonNull).
                mapToInt(e -> this.getStringWidth(e.getStringValue())).
                max().orElse(-1);
        // constant 20 reference: fi.dy.masa.malilib.gui.widgets.WidgetDropDownList.getRequiredWidth
        int width = Math.max(maxTextWidth, 40) + 20;
        SelectorDropDownList dd = new SelectorDropDownList<>(x - width, y, width, height,
                200, entries.size(), entries);
        dd.setEntryChangeListener(entry -> this.setDisplayParameter(valueGetter.get(), entry,
                () -> valueSetter.accept(entry), true));
        dd.setSelectedEntry(defaultValue);
        dd.setHoverText(hoverTextKey);
        postProcessor.accept(dd);
        this.addWidget(dd);
        this.hoveringWidgets.add(dd);
        return dd.getX();
    }

    private int createNavigationButton(int x, int y, String category) {
        ButtonGeneric button = new ButtonGeneric(x, y, -1, 20,
                I18n.tr(String.format("%s.config.category.%s.name", this.identifier, category)));
        button.setEnabled(!this.configManager.getGuiSetting().category.equals(category));
        String translatedHoverText = I18n.translateOrFallback(String.format("%s.config.category.%s.desc",
                this.identifier, category), null);

        if (translatedHoverText != null) {
            button.setHoverStrings(translatedHoverText);
        }

        this.addButton(button, (b, mb) -> this.setDisplayParameter(this.configManager.getGuiSetting().category, category,
                () -> this.configManager.getGuiSetting().setCategory(category), false));
        return button.getWidth() + 2;
    }

    private  void setDisplayParameter(T currentValue, T newValue, Runnable valueSetter, boolean keepSearchBar) {
        if (newValue != currentValue) {
            valueSetter.run();
            this.reDraw(keepSearchBar);
        }
    }

    private void initBottomLine() {
        int available = 0;
        int unavailable = 0;
        int modified = 0;

        for (ConfigContainer config : this.getCurrentContainers()) {
            if (this.isValidConfig(config) && config.isSatisfied()) {
                if (config.getConfig() instanceof IConfigResettable &&
                        ((IConfigResettable) config.getConfig()).isModified()) {
                    modified++;
                }

                available++;
            } else {
                unavailable++;
            }
        }

        int total = available + unavailable;
        String stats = I18n.tr("magiclib.config.gui.bottom_line.stat", total, available, unavailable, modified);
        int width = RenderUtil.getRenderWidth(stats);
        int height = RenderUtil.TEXT_HEIGHT;
        int x = 10;
        int y = this.height - height - GuiBase.TOP;
        this.addLabel(x, y, width, height, 0xFFAAAAAA, stats);
    }

    private int initSortingStrategyDropDownList(int x) {
        List items = Arrays.asList(SortingStrategy.values());
        return this.initDropDownList(
                x, items, this.configManager.getGuiSetting().getSortingStrategy(),
                () -> this.configManager.getGuiSetting().getSortingStrategy(),
                strategy -> this.configManager.getGuiSetting().setSortingStrategy(strategy),
                "magiclib.config.gui.sorting_strategy.label_text",
                dd -> {
                }
        );
    }

    public void reDraw() {
        this.reDraw(true);
    }

    public void reDraw(boolean keepSearchBar) {
        // Storing search bar data.
        String previousSearchBarText = null;
        boolean previousSearchBoxFocus = false;

        if (keepSearchBar && this.searchBar != null && this.searchBar.isSearchOpen()) {
            previousSearchBarText = this.searchBar.getFilter();
            previousSearchBoxFocus = ((WidgetSearchBarAccessor) this.searchBar).magiclib$getSearchBox().isFocused();
        }

        super.removed();
        this.reCreateListWidget();

        // Restoring search bar data.
        if (this.searchBar != null && previousSearchBarText != null) {
            this.searchBar.setSearchOpen(true);
            ((WidgetSearchBarAccessor) this.searchBar).magiclib$getSearchBox().setValue(previousSearchBarText);
            ((WidgetSearchBarAccessor) this.searchBar).magiclib$getSearchBox().setFocused(previousSearchBoxFocus);
        }

        Objects.requireNonNull(this.getListWidget()).resetScrollbarPosition();
        this.initGui();
    }

    public void renderDropDownList(
            //#if MC > 11904
            //$$ GuiGraphics poseStackOrGuiGraphics,
            //#elseif MC > 11502
            class_4587 poseStackOrGuiGraphics,
            //#endif
            int mouseX, int mouseY
    ) {
        this.hoveringWidgets.forEach(widget -> widget.render(
                mouseX, mouseY, widget.isMouseOver(mouseX, mouseY)
                //#if MC > 11502
                , poseStackOrGuiGraphics
                //#endif
        ));
    }

    @Getter
    @Setter
    public static class GuiSetting implements JsonSaveAble {
        private String category = Config.defaultCategory;
        private SortingStrategy sortingStrategy = SortingStrategy.ALPHABET;

        @Override
        public void dumpToJson(@NotNull JsonObject jsonObject) {
            jsonObject.addProperty("category", this.category);
            jsonObject.addProperty("sortingStrategy", this.sortingStrategy.name());
        }

        @Override
        public void loadFromJson(@NotNull JsonObject jsonObject) {
            this.category = jsonObject.get("category").getAsString();
            this.sortingStrategy = this.getEnumSafe(jsonObject, "sortingStrategy", this.sortingStrategy);
        }
    }

    @Getter
    public enum SortingStrategy implements IStringValue {
        ALPHABET((a, b) -> 0),
        MOST_RECENTLY_USED(Collections.reverseOrder(Comparator.comparingLong(c -> c.getStatistic().lastUsedTime))),
        MOST_COMMONLY_USED(Collections.reverseOrder(Comparator.comparingLong(c -> c.getStatistic().useAmount)));

        private final Comparator comparator;

        SortingStrategy(Comparator comparator) {
            this.comparator = comparator;
        }

        @Override
        public String getStringValue() {
            return I18n.tr("magiclib.config.gui.sorting_strategy." + this.name().toLowerCase());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy