<commit_before>package mezz.jei.gui;

import com.google.common.collect.ImmutableList;
import mezz.jei.Internal;
import mezz.jei.ItemFilter;
import mezz.jei.JustEnoughItems;
import mezz.jei.api.IItemListOverlay;
import mezz.jei.api.gui.IAdvancedGuiHandler;
import mezz.jei.api.gui.IDrawable;
import mezz.jei.config.Config;
import mezz.jei.config.Constants;
import mezz.jei.config.JEIModConfigGui;
import mezz.jei.gui.ingredients.GuiItemStackFast;
import mezz.jei.gui.ingredients.GuiItemStackFastList;
import mezz.jei.gui.ingredients.GuiItemStackGroup;
import mezz.jei.input.GuiTextFieldFilter;
import mezz.jei.input.ICloseable;
import mezz.jei.input.IKeyable;
import mezz.jei.input.IMouseHandler;
import mezz.jei.input.IShowsRecipeFocuses;
import mezz.jei.network.packets.PacketDeletePlayerItem;
import mezz.jei.network.packets.PacketJEI;
import mezz.jei.util.ItemStackElement;
import mezz.jei.util.Log;
import mezz.jei.util.MathUtil;
import mezz.jei.util.Translator;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatAllowedCharacters;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.client.config.GuiButtonExt;
import net.minecraftforge.fml.client.config.HoverChecker;
import org.lwjgl.input.Keyboard;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.*;
import java.util.List;
import java.util.Objects;

public class ItemListOverlay implements IItemListOverlay, IShowsRecipeFocuses, IMouseHandler, IKeyable, ICloseable {

	private static final int borderPadding = 2;
	private static final int searchHeight = 16;
	private static final int buttonSize = 20;
	private static final String nextLabel = ">";
	private static final String backLabel = "<";

	private static final int itemStackPadding = 1;
	private static final int itemStackWidth = GuiItemStackGroup.getWidth(itemStackPadding);
	private static final int itemStackHeight = GuiItemStackGroup.getHeight(itemStackPadding);
	private static int firstItemIndex = 0;

	@Nonnull
	private final ItemFilter itemFilter;
	@Nonnull
	private final List<IAdvancedGuiHandler<?>> advancedGuiHandlers;

	private final GuiItemStackFastList guiItemStacks = new GuiItemStackFastList();
	private GuiButton nextButton;
	private GuiButton backButton;
	private GuiButton configButton;
	private IDrawable configButtonIcon;
	private IDrawable configButtonCheatIcon;
	private HoverChecker configButtonHoverChecker;
	private GuiTextFieldFilter searchField;

	private String pageNumDisplayString;
	private int pageNumDisplayX;
	private int pageNumDisplayY;

	private GuiItemStackFast hovered = null;

	// properties of the gui we're beside
	@Nullable
	private GuiProperties guiProperties;
	@Nullable
	private List<Rectangle> guiAreas;
	@Nullable
	IAdvancedGuiHandler advancedGuiHandler;

	private boolean open = false;

	public ItemListOverlay(@Nonnull ItemFilter itemFilter, @Nonnull List<IAdvancedGuiHandler<?>> advancedGuiHandlers) {
		this.itemFilter = itemFilter;
		this.advancedGuiHandlers = advancedGuiHandlers;
	}

	public void initGui(@Nonnull GuiScreen guiScreen) {
		GuiProperties guiProperties = GuiProperties.create(guiScreen);
		if (guiProperties == null) {
			return;
		}

		this.guiProperties = guiProperties;
		this.advancedGuiHandler = getAdvancedGuiHandler(guiScreen);
		if (advancedGuiHandler != null && guiScreen instanceof GuiContainer) {
			GuiContainer guiContainer = (GuiContainer) guiScreen;
			//noinspection unchecked
			guiAreas = advancedGuiHandler.getGuiExtraAreas(guiContainer);
		} else {
			guiAreas = null;
		}

		final int columns = getColumns();
		if (columns < 4) {
			close();
			return;
		}

		final int rows = getRows();
		final int xSize = columns * itemStackWidth;
		final int xEmptySpace = guiProperties.getScreenWidth() - guiProperties.getGuiLeft() - guiProperties.getGuiXSize() - xSize;

		final int leftEdge = guiProperties.getGuiLeft() + guiProperties.getGuiXSize() + (xEmptySpace / 2);
		final int rightEdge = leftEdge + xSize;

		final int yItemButtonSpace = getItemButtonYSpace();
		final int itemButtonsHeight = rows * itemStackHeight;

		final int buttonStartY = buttonSize + (2 * borderPadding) + (yItemButtonSpace - itemButtonsHeight) / 2;
		createItemButtons(guiItemStacks, guiAreas, leftEdge, buttonStartY, columns, rows);

		nextButton = new GuiButtonExt(0, rightEdge - buttonSize, borderPadding, buttonSize, buttonSize, nextLabel);
		backButton = new GuiButtonExt(1, leftEdge, borderPadding, buttonSize, buttonSize, backLabel);

		int configButtonX = rightEdge - buttonSize + 1;
		int configButtonY = guiProperties.getScreenHeight() - buttonSize - borderPadding;
		configButton = new GuiButtonExt(2, configButtonX, configButtonY, buttonSize, buttonSize, null);
		ResourceLocation configButtonIconLocation = new ResourceLocation(Constants.RESOURCE_DOMAIN, Constants.TEXTURE_GUI_PATH + "recipeBackground.png");
		GuiHelper guiHelper = Internal.getHelpers().getGuiHelper();
		configButtonIcon = guiHelper.createDrawable(configButtonIconLocation, 0, 166, 16, 16);
		configButtonCheatIcon = guiHelper.createDrawable(configButtonIconLocation, 16, 166, 16, 16);
		configButtonHoverChecker = new HoverChecker(configButton, 0);

		int searchFieldY = guiProperties.getScreenHeight() - searchHeight - borderPadding - 2;
		int searchFieldWidth = rightEdge - leftEdge - buttonSize - 1;
		FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
		searchField = new GuiTextFieldFilter(0, fontRenderer, leftEdge, searchFieldY, searchFieldWidth, searchHeight);
		setKeyboardFocus(false);
		searchField.setItemFilter(itemFilter);

		updateLayout();

		open();
	}

	@Nullable
	private IAdvancedGuiHandler<?> getAdvancedGuiHandler(@Nonnull GuiScreen guiScreen) {
		if (guiScreen instanceof GuiContainer) {
			GuiContainer guiContainer = (GuiContainer) guiScreen;
			for (IAdvancedGuiHandler<?> advancedGuiHandler : advancedGuiHandlers) {
				if (advancedGuiHandler.getGuiContainerClass().isAssignableFrom(guiContainer.getClass())) {
					return advancedGuiHandler;
				}
			}
		}
		return null;
	}

	public void updateGui(@Nonnull GuiScreen guiScreen) {
		if (this.guiProperties == null) {
			initGui(guiScreen);
		} else {
			GuiProperties guiProperties = GuiProperties.create(guiScreen);
			if (guiProperties == null) {
				return;
			}
			if (!this.guiProperties.equals(guiProperties)) {
				initGui(guiScreen);
			} else if (advancedGuiHandler != null && guiScreen instanceof GuiContainer) {
				GuiContainer guiContainer = (GuiContainer) guiScreen;
				//noinspection unchecked
				List<Rectangle> guiAreas = advancedGuiHandler.getGuiExtraAreas(guiContainer);
				if (!Objects.equals(this.guiAreas, guiAreas)) {
					initGui(guiContainer);
				}
			}
		}
	}

	private static void createItemButtons(@Nonnull GuiItemStackFastList guiItemStacks, @Nullable List<Rectangle> guiAreas, final int xStart, final int yStart, final int columnCount, final int rowCount) {
		guiItemStacks.clear();

		for (int row = 0; row < rowCount; row++) {
			int y = yStart + (row * itemStackHeight);
			for (int column = 0; column < columnCount; column++) {
				int x = xStart + (column * itemStackWidth);
				GuiItemStackFast guiItemStackFast = new GuiItemStackFast(x, y, itemStackPadding);
				if (guiAreas != null) {
					Rectangle stackArea = guiItemStackFast.getArea();
					if (intersects(guiAreas, stackArea)) {<commit_msg>Close #299 allow registration of extra gui areas from multiple sources<commit_after>package mezz.jei.gui;

import com.google.common.collect.ImmutableList;
import mezz.jei.Internal;
import mezz.jei.ItemFilter;
import mezz.jei.JustEnoughItems;
import mezz.jei.api.IItemListOverlay;
import mezz.jei.api.gui.IAdvancedGuiHandler;
import mezz.jei.api.gui.IDrawable;
import mezz.jei.config.Config;
import mezz.jei.config.Constants;
import mezz.jei.config.JEIModConfigGui;
import mezz.jei.gui.ingredients.GuiItemStackFast;
import mezz.jei.gui.ingredients.GuiItemStackFastList;
import mezz.jei.gui.ingredients.GuiItemStackGroup;
import mezz.jei.input.GuiTextFieldFilter;
import mezz.jei.input.ICloseable;
import mezz.jei.input.IKeyable;
import mezz.jei.input.IMouseHandler;
import mezz.jei.input.IShowsRecipeFocuses;
import mezz.jei.network.packets.PacketDeletePlayerItem;
import mezz.jei.network.packets.PacketJEI;
import mezz.jei.util.ItemStackElement;
import mezz.jei.util.Log;
import mezz.jei.util.MathUtil;
import mezz.jei.util.Translator;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatAllowedCharacters;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.client.config.GuiButtonExt;
import net.minecraftforge.fml.client.config.HoverChecker;
import org.lwjgl.input.Keyboard;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class ItemListOverlay implements IItemListOverlay, IShowsRecipeFocuses, IMouseHandler, IKeyable, ICloseable {

	private static final int borderPadding = 2;
	private static final int searchHeight = 16;
	private static final int buttonSize = 20;
	private static final String nextLabel = ">";
	private static final String backLabel = "<";

	private static final int itemStackPadding = 1;
	private static final int itemStackWidth = GuiItemStackGroup.getWidth(itemStackPadding);
	private static final int itemStackHeight = GuiItemStackGroup.getHeight(itemStackPadding);
	private static int firstItemIndex = 0;

	@Nonnull
	private final ItemFilter itemFilter;
	@Nonnull
	private final List<IAdvancedGuiHandler<?>> advancedGuiHandlers;

	private final GuiItemStackFastList guiItemStacks = new GuiItemStackFastList();
	private GuiButton nextButton;
	private GuiButton backButton;
	private GuiButton configButton;
	private IDrawable configButtonIcon;
	private IDrawable configButtonCheatIcon;
	private HoverChecker configButtonHoverChecker;
	private GuiTextFieldFilter searchField;

	private String pageNumDisplayString;
	private int pageNumDisplayX;
	private int pageNumDisplayY;

	private GuiItemStackFast hovered = null;

	// properties of the gui we're beside
	@Nullable
	private GuiProperties guiProperties;
	@Nullable
	private List<Rectangle> guiAreas;
	@Nonnull
	private List<IAdvancedGuiHandler<?>> activeAdvancedGuiHandlers = Collections.emptyList();

	private boolean open = false;

	public ItemListOverlay(@Nonnull ItemFilter itemFilter, @Nonnull List<IAdvancedGuiHandler<?>> advancedGuiHandlers) {
		this.itemFilter = itemFilter;
		this.advancedGuiHandlers = advancedGuiHandlers;
	}

	public void initGui(@Nonnull GuiScreen guiScreen) {
		GuiProperties guiProperties = GuiProperties.create(guiScreen);
		if (guiProperties == null) {
			return;
		}

		this.guiProperties = guiProperties;
		this.activeAdvancedGuiHandlers = getActiveAdvancedGuiHandlers(guiScreen);
		if (!activeAdvancedGuiHandlers.isEmpty() && guiScreen instanceof GuiContainer) {
			GuiContainer guiContainer = (GuiContainer) guiScreen;
			//noinspection unchecked
			guiAreas = getGuiAreas(guiContainer);
		} else {
			guiAreas = null;
		}

		final int columns = getColumns();
		if (columns < 4) {
			close();
			return;
		}

		final int rows = getRows();
		final int xSize = columns * itemStackWidth;
		final int xEmptySpace = guiProperties.getScreenWidth() - guiProperties.getGuiLeft() - guiProperties.getGuiXSize() - xSize;

		final int leftEdge = guiProperties.getGuiLeft() + guiProperties.getGuiXSize() + (xEmptySpace / 2);
		final int rightEdge = leftEdge + xSize;

		final int yItemButtonSpace = getItemButtonYSpace();
		final int itemButtonsHeight = rows * itemStackHeight;

		final int buttonStartY = buttonSize + (2 * borderPadding) + (yItemButtonSpace - itemButtonsHeight) / 2;
		createItemButtons(guiItemStacks, guiAreas, leftEdge, buttonStartY, columns, rows);

		nextButton = new GuiButtonExt(0, rightEdge - buttonSize, borderPadding, buttonSize, buttonSize, nextLabel);
		backButton = new GuiButtonExt(1, leftEdge, borderPadding, buttonSize, buttonSize, backLabel);

		int configButtonX = rightEdge - buttonSize + 1;
		int configButtonY = guiProperties.getScreenHeight() - buttonSize - borderPadding;
		configButton = new GuiButtonExt(2, configButtonX, configButtonY, buttonSize, buttonSize, null);
		ResourceLocation configButtonIconLocation = new ResourceLocation(Constants.RESOURCE_DOMAIN, Constants.TEXTURE_GUI_PATH + "recipeBackground.png");
		GuiHelper guiHelper = Internal.getHelpers().getGuiHelper();
		configButtonIcon = guiHelper.createDrawable(configButtonIconLocation, 0, 166, 16, 16);
		configButtonCheatIcon = guiHelper.createDrawable(configButtonIconLocation, 16, 166, 16, 16);
		configButtonHoverChecker = new HoverChecker(configButton, 0);

		int searchFieldY = guiProperties.getScreenHeight() - searchHeight - borderPadding - 2;
		int searchFieldWidth = rightEdge - leftEdge - buttonSize - 1;
		FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
		searchField = new GuiTextFieldFilter(0, fontRenderer, leftEdge, searchFieldY, searchFieldWidth, searchHeight);
		setKeyboardFocus(false);
		searchField.setItemFilter(itemFilter);

		updateLayout();

		open();
	}

	@Nonnull
	private List<IAdvancedGuiHandler<?>> getActiveAdvancedGuiHandlers(@Nonnull GuiScreen guiScreen) {
		List<IAdvancedGuiHandler<?>> activeAdvancedGuiHandler = new ArrayList<>();
		if (guiScreen instanceof GuiContainer) {
			GuiContainer guiContainer = (GuiContainer) guiScreen;
			for (IAdvancedGuiHandler<?> advancedGuiHandler : advancedGuiHandlers) {
				if (advancedGuiHandler.getGuiContainerClass().isAssignableFrom(guiContainer.getClass())) {
					activeAdvancedGuiHandler.add(advancedGuiHandler);
				}
			}
		}
		return activeAdvancedGuiHandler;
	}

	private List<Rectangle> getGuiAreas(GuiContainer guiContainer) {
		List<Rectangle> guiAreas = new ArrayList<>();
		for (IAdvancedGuiHandler advancedGuiHandler : activeAdvancedGuiHandlers) {
			//noinspection unchecked
			List<Rectangle> guiExtraAreas = advancedGuiHandler.getGuiExtraAreas(guiContainer);
			if (guiExtraAreas != null) {
				guiAreas.addAll(guiExtraAreas);
			}
		}
		return guiAreas;
	}

	public void updateGui(@Nonnull GuiScreen guiScreen) {
		if (this.guiProperties == null) {
			initGui(guiScreen);
		} else {
			GuiProperties guiProperties = GuiProperties.create(guiScreen);
			if (guiProperties == null) {
				return;
			}
			if (!this.guiProperties.equals(guiProperties)) {
				initGui(guiScreen);
			} else if (!activeAdvancedGuiHandlers.isEmpty() && guiScreen instanceof GuiContainer) {
				GuiContainer guiContainer = (GuiContainer) guiScreen;
				List<Rectangle> guiAreas = getGuiAreas(guiContainer);
				if (!Objects.equals(this.guiAreas, guiAreas)) {
					initGui(guiContainer);
				}
			}
		}
	}

	private static void createItemButtons(@Nonnull GuiItemStackFastList guiItemStacks, @Nullable List<Rectangle> guiAreas, final int xStart, final int yStart, final int columnCount, final int rowCount) {
		guiItemStacks.clear();

		for (int row = 0; row < rowCount; row++) {
			int y = yStart + (row * itemStackHeight);
			for (int column = 0; column < columnCount; column++) {
				int x = xStart + (column * itemStackWidth);
				GuiItemStackFast guiItemStackFast = new GuiItemStackFast(x, y, itemStackPadding);
				if (guiAreas != null) {
					Rectangle stackArea = guiItemStackFast.getArea();
					if (intersects(guiAreas, stackArea)) {
{'fraction_non_alphanumeric': 0.09244679542379136, 'fraction_numerical': 0.004859146266453438, 'mean_word_length': 5.696457990115321, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4145523', 'n_tokens_mistral': 5356, 'n_tokens_neox': 4970, 'n_words': 1114}