Merge branch 'bspkrsgui'

This commit is contained in:
cpw 2014-06-25 17:02:40 -04:00
commit 98d6d97c3e
19 changed files with 4674 additions and 28 deletions

View File

@ -1,50 +1,88 @@
package cpw.mods.fml.client;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableSet;
import cpw.mods.fml.client.config.ConfigGuiType;
import cpw.mods.fml.client.config.DummyConfigElement;
import cpw.mods.fml.client.config.GuiConfig;
import cpw.mods.fml.client.config.IConfigElement;
import cpw.mods.fml.client.config.DummyConfigElement.DummyCategoryElement;
import cpw.mods.fml.client.config.DummyConfigElement.DummyListElement;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
public class FMLConfigGuiFactory implements IModGuiFactory {
public static class FMLConfigGuiScreen extends GuiScreen {
private GuiScreen parent;
public class FMLConfigGuiFactory implements IModGuiFactory
{
public static class FMLConfigGuiScreen extends GuiConfig
{
public FMLConfigGuiScreen(GuiScreen parent)
{
this.parent = parent;
super(parent, getConfigElements(), "FML", false, false, I18n.format("fml.config.sample.title"));
}
@SuppressWarnings("unchecked")
@Override
public void initGui()
private static List<IConfigElement> getConfigElements()
{
this.buttonList.add(new GuiButton(1, this.width / 2 - 75, this.height - 38, I18n.format("gui.done")));
}
List<IConfigElement> list = new ArrayList<IConfigElement>();
List<IConfigElement> listsList = new ArrayList<IConfigElement>();
List<IConfigElement> stringsList = new ArrayList<IConfigElement>();
List<IConfigElement> numbersList = new ArrayList<IConfigElement>();
Pattern commaDelimitedPattern = Pattern.compile("([A-Za-z]+((,){1}( )*|$))+?");
// Top Level Settings
list.add(new DummyConfigElement<Boolean>("imABoolean", true, ConfigGuiType.BOOLEAN, "fml.config.sample.imABoolean").setRequiresMcRestart(true));
list.add(new DummyConfigElement<Integer>("imAnInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.imAnInteger", -1, 256).setRequiresMcRestart(true));
list.add(new DummyConfigElement<Double>("imADouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.imADouble", -1.0D, 256.256D).setRequiresMcRestart(true));
list.add(new DummyConfigElement<String>("imAString", "http://www.montypython.net/scripts/string.php", ConfigGuiType.STRING, "fml.config.sample.imAString").setRequiresMcRestart(true));
// Lists category
listsList.add(new DummyListElement<Boolean>("booleanList", new Boolean[] {true, false, true, false, true, false, true, false}, ConfigGuiType.BOOLEAN, "fml.config.sample.booleanList"));
listsList.add(new DummyListElement<Boolean>("booleanListFixed", new Boolean[] {true, false, true, false, true, false, true, false}, ConfigGuiType.BOOLEAN, "fml.config.sample.booleanListFixed", true));
listsList.add(new DummyListElement<Boolean>("booleanListMax", new Boolean[] {true, false, true, false, true, false, true, false}, ConfigGuiType.BOOLEAN, "fml.config.sample.booleanListMax", 10));
listsList.add(new DummyListElement<Double>("doubleList", new Double[] {0.0D, 1.1D, 2.2D, 3.3D, 4.4D, 5.5D, 6.6D, 7.7D, 8.8D, 9.9D}, ConfigGuiType.DOUBLE, "fml.config.sample.doubleList"));
listsList.add(new DummyListElement<Double>("doubleListFixed", new Double[] {0.0D, 1.1D, 2.2D, 3.3D, 4.4D, 5.5D, 6.6D, 7.7D, 8.8D, 9.9D}, ConfigGuiType.DOUBLE, "fml.config.sample.doubleListFixed", true));
listsList.add(new DummyListElement<Double>("doubleListMax", new Double[] {0.0D, 1.1D, 2.2D, 3.3D, 4.4D, 5.5D, 6.6D, 7.7D, 8.8D, 9.9D}, ConfigGuiType.DOUBLE, "fml.config.sample.doubleListMax", 15));
listsList.add(new DummyListElement<Double>("doubleListBounded", new Double[] {0.0D, 1.1D, 2.2D, 3.3D, 4.4D, 5.5D, 6.6D, 7.7D, 8.8D, 9.9D}, ConfigGuiType.DOUBLE, "fml.config.sample.doubleListBounded", -1.0D, 10.0D));
listsList.add(new DummyListElement<Integer>("integerList", new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ConfigGuiType.INTEGER, "fml.config.sample.integerList"));
listsList.add(new DummyListElement<Integer>("integerListFixed", new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ConfigGuiType.INTEGER, "fml.config.sample.integerListFixed", true));
listsList.add(new DummyListElement<Integer>("integerListMax", new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ConfigGuiType.INTEGER, "fml.config.sample.integerListMax", 15));
listsList.add(new DummyListElement<Integer>("integerListBounded", new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ConfigGuiType.INTEGER, "fml.config.sample.integerListBounded", -1, 10));
listsList.add(new DummyListElement<String>("stringList", new String[] {"An", "array", "of", "string", "values"}, ConfigGuiType.STRING, "fml.config.sample.stringList"));
listsList.add(new DummyListElement<String>("stringListFixed", new String[] {"A", "fixed", "length", "array", "of", "string", "values"}, ConfigGuiType.STRING, "fml.config.sample.stringListFixed", true));
listsList.add(new DummyListElement<String>("stringListMax", new String[] {"An", "array", "of", "string", "values", "with", "a", "max", "length", "of", "15"}, ConfigGuiType.STRING, "fml.config.sample.stringListMax", 15));
listsList.add(new DummyListElement<String>("stringListPattern", new String[] {"Valid", "Not Valid", "Is, Valid", "Comma, Separated, Value"}, ConfigGuiType.STRING, "fml.config.sample.stringListPattern", commaDelimitedPattern));
list.add(new DummyCategoryElement("lists", "fml.config.sample.ctgy.lists", listsList));
// Strings category
stringsList.add(new DummyConfigElement<String>("basicString", "Just a regular String value, anything goes.", ConfigGuiType.STRING, "fml.config.sample.basicString"));
stringsList.add(new DummyConfigElement<String>("cycleString", "this", ConfigGuiType.STRING, "fml.config.sample.cycleString", new String[] {"this", "property", "cycles", "through", "a", "list", "of", "valid", "choices"}));
stringsList.add(new DummyConfigElement<String>("patternString", "only, comma, separated, words, can, be, entered, in, this, box", ConfigGuiType.STRING, "fml.config.sample.patternString", commaDelimitedPattern));
stringsList.add(new DummyConfigElement<String>("chatColorPicker", "c", ConfigGuiType.COLOR, "fml.config.sample.chatColorPicker", new String[] {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}));
stringsList.add(new DummyConfigElement<String>("modIDSelector", "FML", ConfigGuiType.MOD_ID, "fml.config.sample.modIDSelector"));
list.add(new DummyCategoryElement("strings", "fml.config.sample.ctgy.strings", stringsList));
// Numbers category
numbersList.add((new DummyConfigElement<Integer>("basicInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.basicInteger")));
numbersList.add((new DummyConfigElement<Integer>("boundedInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.boundedInteger", -1, 256)));
numbersList.add(new DummyConfigElement<Double>("basicDouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.basicDouble"));
numbersList.add(new DummyConfigElement<Double>("boundedDouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.boundedDouble", -1.0D, 256.256D));
@Override
protected void actionPerformed(GuiButton p_73875_1_)
{
if (p_73875_1_.enabled && p_73875_1_.id == 1)
{
FMLClientHandler.instance().showGuiScreen(parent);
}
list.add(new DummyCategoryElement("numbers", "fml.config.sample.ctgy.numbers", numbersList));
return list;
}
@Override
public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_)
{
this.drawDefaultBackground();
this.drawCenteredString(this.fontRendererObj, "Forge Mod Loader test config screen", this.width / 2, 40, 0xFFFFFF);
super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
}
}
@SuppressWarnings("unused")
private Minecraft minecraft;
@Override
public void initialize(Minecraft minecraftInstance)
@ -97,4 +135,4 @@ public class FMLConfigGuiFactory implements IModGuiFactory {
};
}
}
}

View File

@ -0,0 +1,24 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
public enum ConfigGuiType
{
STRING,
INTEGER,
BOOLEAN,
DOUBLE,
COLOR,
MOD_ID,
CONFIG_CATEGORY;
}

View File

@ -0,0 +1,418 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.config.GuiEditArrayEntries.IArrayEntry;
import net.minecraft.client.resources.I18n;
/**
* This class's main purpose is to provide the necessary objects for a sample Config GUI for FML, although
* there may be practical uses for the objects defined here such as using the DummyCategoryElement object as a
* wrapper for a custom IGuiConfigListEntry object that opens a special screen.
*
* @author bspkrs
*/
public class DummyConfigElement<T> implements IConfigElement<T>
{
protected boolean isProperty = true;
protected boolean isList = false;
protected ConfigGuiType type;
protected String name;
protected String langKey;
protected Object value;
protected Object defaultValue;
protected T[] values;
protected T[] defaultValues;
protected String[] validValues;
protected Pattern validStringPattern;
protected T minValue;
protected T maxValue;
protected boolean requiresWorldRestart = false;
protected boolean requiresMcRestart = false;
protected boolean isListFixedLength = false;
protected int maxListLength = -1;
protected List<IConfigElement> childElements;
protected Class<? extends IConfigEntry> configEntryClass;
protected Class<? extends IArrayEntry> arrayEntryClass;
/**
* This class provides a Dummy Category IConfigElement. It can be used to define a custom list of GUI entries that will
* appear on the child screen or to specify a custom IGuiConfigListEntryfor a special category.
*/
public static class DummyCategoryElement<T> extends DummyConfigElement<T>
{
public DummyCategoryElement(String name, String langKey, List<IConfigElement> childElements)
{
this(name, langKey, childElements, (Class) null);
}
public DummyCategoryElement(String name, String langKey, Class<? extends IConfigEntry> customListEntryClass)
{
this(name, langKey, new ArrayList<IConfigElement>(), customListEntryClass);
}
public DummyCategoryElement(String name, String langKey, List<IConfigElement> childElements, Class<? extends IConfigEntry> customListEntryClass)
{
super(name, (T) null, ConfigGuiType.CONFIG_CATEGORY, langKey);
this.childElements = childElements;
this.configEntryClass = customListEntryClass;
isProperty = false;
}
}
/**
* This class provides a dummy array-type IConfigElement.
*/
public static class DummyListElement<T> extends DummyConfigElement<T>
{
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, boolean isListFixedLength, int maxListLength, Pattern validStringPattern, T minValue, T maxValue)
{
super(name, (T) null, type, langKey, minValue, maxValue);
this.defaultValues = defaultValues;
this.values = defaultValues;
this.isListFixedLength = isListFixedLength;
this.maxListLength = maxListLength;
this.validStringPattern = validStringPattern;
isList = true;
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey)
{
this(name, defaultValues, type, langKey, false, -1, (Pattern) null, (T) null, (T) null);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, boolean isListFixedLength)
{
this(name, defaultValues, type, langKey, isListFixedLength, -1, (Pattern) null, (T) null, (T) null);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, int maxListLength)
{
this(name, defaultValues, type, langKey, false, maxListLength, (Pattern) null, (T) null, (T) null);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, T minValue, T maxValue)
{
this(name, defaultValues, type, langKey, false, -1, (Pattern) null, minValue, maxValue);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, boolean isListFixedLength, T minValue, T maxValue)
{
this(name, defaultValues, type, langKey, isListFixedLength, -1, (Pattern) null, minValue, maxValue);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, int maxListLength, T minValue, T maxValue)
{
this(name, defaultValues, type, langKey, false, maxListLength, (Pattern) null, minValue, maxValue);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, boolean isListFixedLength, int maxListLength, T minValue, T maxValue)
{
this(name, defaultValues, type, langKey, isListFixedLength, maxListLength, (Pattern) null, minValue, maxValue);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, Pattern validStringPattern)
{
this(name, defaultValues, type, langKey, false, -1, validStringPattern, (T) null, (T) null);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, boolean isListFixedLength, Pattern validStringPattern)
{
this(name, defaultValues, type, langKey, isListFixedLength, -1, validStringPattern, (T) null, (T) null);
}
public DummyListElement(String name, T[] defaultValues, ConfigGuiType type, String langKey, int maxListLength, Pattern validStringPattern)
{
this(name, defaultValues, type, langKey, false, maxListLength, validStringPattern, (T) null, (T) null);
}
public DummyListElement setCustomEditListEntryClass(Class<? extends IArrayEntry> clazz)
{
this.arrayEntryClass = clazz;
return this;
}
@Override
public Object getDefault()
{
return Arrays.toString(this.defaultValues);
}
}
public DummyConfigElement(String name, T defaultValue, ConfigGuiType type, String langKey, String[] validValues, Pattern validStringPattern, T minValue, T maxValue)
{
this.name = name;
this.defaultValue = defaultValue;
this.value = defaultValue;
this.type = type;
this.langKey = langKey;
this.validValues = validValues;
this.validStringPattern = validStringPattern;
if (minValue == null)
{
if (type == ConfigGuiType.INTEGER)
this.minValue = (T) (Integer) Integer.MIN_VALUE;
else if (type == ConfigGuiType.DOUBLE)
this.minValue = (T) (Double) (-Double.MAX_VALUE);
}
else
this.minValue = minValue;
if (maxValue == null)
{
if (type == ConfigGuiType.INTEGER)
this.maxValue = (T) (Integer) Integer.MAX_VALUE;
else if (type == ConfigGuiType.DOUBLE)
this.maxValue = (T) (Double) Double.MAX_VALUE;
}
else
this.maxValue = maxValue;
}
public DummyConfigElement(String name, T defaultValue, ConfigGuiType type, String langKey, Pattern validStringPattern)
{
this(name, defaultValue, type, langKey, (String[]) null, validStringPattern, (T) null, (T) null);
}
public DummyConfigElement(String name, T defaultValue, ConfigGuiType type, String langKey, String[] validValues)
{
this(name, defaultValue, type, langKey, validValues, (Pattern) null, (T) null, (T) null);
}
public DummyConfigElement(String name, T defaultValue, ConfigGuiType type, String langKey)
{
this(name, defaultValue, type, langKey, (String[]) null, (Pattern) null, (T) null, (T) null);
}
public DummyConfigElement(String name, T defaultValue, ConfigGuiType type, String langKey, T minValue, T maxValue)
{
this(name, defaultValue, type, langKey, (String[]) null, (Pattern) null, minValue, maxValue);
}
public DummyConfigElement setCustomListEntryClass(Class<? extends IConfigEntry> clazz)
{
this.configEntryClass = clazz;
return this;
}
@Override
public boolean isProperty()
{
return isProperty;
}
public IConfigElement setConfigEntryClass(Class<? extends IConfigEntry> clazz)
{
this.configEntryClass = clazz;
return this;
}
@Override
public Class<? extends IConfigEntry> getConfigEntryClass()
{
return configEntryClass;
}
public IConfigElement setArrayEntryClass(Class<? extends IArrayEntry> clazz)
{
this.arrayEntryClass = clazz;
return this;
}
@Override
public Class<? extends IArrayEntry> getArrayEntryClass()
{
return arrayEntryClass;
}
@Override
public String getName()
{
return name;
}
@Override
public String getQualifiedName()
{
return name;
}
@Override
public String getLanguageKey()
{
return langKey;
}
@Override
public String getComment()
{
return I18n.format(langKey + ".tooltip");
}
@Override
public List<IConfigElement> getChildElements()
{
return childElements;
}
@Override
public ConfigGuiType getType()
{
return type;
}
@Override
public boolean isList()
{
return isList;
}
@Override
public boolean isListLengthFixed()
{
return this.isListFixedLength;
}
@Override
public int getMaxListLength()
{
return this.maxListLength;
}
@Override
public boolean isDefault()
{
if (isProperty)
{
if (!isList)
{
if (value != null)
return value.equals(defaultValue);
else
return defaultValue == null;
}
else
{
return Arrays.deepEquals(values, defaultValues);
}
}
return true;
}
@Override
public Object getDefault()
{
return defaultValue;
}
@Override
public T[] getDefaults()
{
return defaultValues;
}
@Override
public void setToDefault()
{
if (isList)
this.values = Arrays.copyOf(this.defaultValues, this.defaultValues.length);
else
this.value = defaultValue;
}
public IConfigElement<T> setRequiresWorldRestart(boolean requiresWorldRestart)
{
this.requiresWorldRestart = requiresWorldRestart;
return this;
}
@Override
public boolean requiresWorldRestart()
{
return requiresWorldRestart;
}
@Override
public boolean showInGui()
{
return true;
}
public IConfigElement<T> setRequiresMcRestart(boolean requiresMcRestart)
{
this.requiresMcRestart = this.requiresWorldRestart = requiresMcRestart;
return this;
}
@Override
public boolean requiresMcRestart()
{
return requiresMcRestart;
}
@Override
public String[] getValidValues()
{
return validValues;
}
@Override
public Pattern getValidationPattern()
{
return validStringPattern;
}
@Override
public Object get()
{
return value;
}
@Override
public T[] getList()
{
return values;
}
@Override
public void set(T value)
{
defaultValue = value;
}
@Override
public void set(T[] aVal)
{
defaultValues = aVal;
}
@Override
public T getMinValue()
{
return minValue;
}
@Override
public T getMaxValue()
{
return maxValue;
}
}

View File

@ -0,0 +1,79 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import org.lwjgl.opengl.GL11;
/**
* This class provides a button that fixes several bugs present in the vanilla GuiButton drawing code.
* The gist of it is that it allows buttons of any size without gaps in the graphics and with the
* borders drawn properly. It also prevents button text from extending out of the sides of the button by
* trimming the end of the string and adding an ellipsis.<br/><br/>
*
* The code that handles drawing the button is in GuiUtils.
*
* @author bspkrs
*/
public class GuiButtonExt extends GuiButton
{
public GuiButtonExt(int id, int xPos, int yPos, String displayString)
{
super(id, xPos, yPos, displayString);
}
public GuiButtonExt(int id, int xPos, int yPos, int width, int height, String displayString)
{
super(id, xPos, yPos, width, height, displayString);
}
/**
* Draws this button to the screen.
*/
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY)
{
if (this.visible)
{
this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height;
int k = this.getHoverState(this.field_146123_n);
GuiUtils.drawContinuousTexturedBox(buttonTextures, this.xPosition, this.yPosition, 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.zLevel);
this.mouseDragged(mc, mouseX, mouseY);
int color = 14737632;
if (packedFGColour != 0)
{
color = packedFGColour;
}
else if (!this.enabled)
{
color = 10526880;
}
else if (this.field_146123_n)
{
color = 16777120;
}
String buttonText = this.displayString;
int strWidth = mc.fontRenderer.getStringWidth(buttonText);
int ellipsisWidth = mc.fontRenderer.getStringWidth("...");
if (strWidth > width - 6 && strWidth > ellipsisWidth)
buttonText = mc.fontRenderer.trimStringToWidth(buttonText, width - 6 - ellipsisWidth).trim() + "...";
this.drawCenteredString(mc.fontRenderer, buttonText, this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, color);
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
/**
* This class provides a checkbox style control.
*
* @author bspkrs
*/
public class GuiCheckBox extends GuiButton
{
private boolean isChecked;
private int boxWidth;
public GuiCheckBox(int id, int xPos, int yPos, String displayString, boolean isChecked)
{
super(id, xPos, yPos, displayString);
this.isChecked = isChecked;
this.boxWidth = 11;
this.height = 11;
this.width = this.boxWidth + 2 + Minecraft.getMinecraft().fontRenderer.getStringWidth(displayString);
}
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY)
{
if (this.visible)
{
this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.boxWidth && mouseY < this.yPosition + this.height;
GuiUtils.drawContinuousTexturedBox(buttonTextures, this.xPosition, this.yPosition, 0, 46, this.boxWidth, this.height, 200, 20, 2, 3, 2, 2, this.zLevel);
this.mouseDragged(mc, mouseX, mouseY);
int color = 14737632;
if (packedFGColour != 0)
{
color = packedFGColour;
}
else if (!this.enabled)
{
color = 10526880;
}
if (this.isChecked)
this.drawCenteredString(mc.fontRenderer, "x", this.xPosition + this.boxWidth / 2 + 1, this.yPosition + 1, 14737632);
this.drawString(mc.fontRenderer, displayString, xPosition + this.boxWidth + 2, yPosition + 2, color);
}
}
@Override
public boolean mousePressed(Minecraft p_146116_1_, int p_146116_2_, int p_146116_3_)
{
if (this.enabled && this.visible && p_146116_2_ >= this.xPosition && p_146116_3_ >= this.yPosition && p_146116_2_ < this.xPosition + this.width && p_146116_3_ < this.yPosition + this.height)
{
this.isChecked = !this.isChecked;
return true;
}
return false;
}
public boolean isChecked()
{
return this.isChecked;
}
public void setIsChecked(boolean isChecked)
{
this.isChecked = isChecked;
}
}

View File

@ -0,0 +1,347 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiYesNo;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ChatComponentText;
import org.lwjgl.input.Keyboard;
import static cpw.mods.fml.client.config.GuiUtils.RESET_CHAR;
import static cpw.mods.fml.client.config.GuiUtils.UNDO_CHAR;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import cpw.mods.fml.client.event.ConfigChangedEvent.PostConfigChangedEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.Event.Result;
/**
* This class is the base GuiScreen for all config GUI screens. It can be extended by mods to provide the top-level config screen
* that will be called when the Config button is clicked from the Main Menu Mods list.
*
* @author bspkrs
*/
public class GuiConfig extends GuiScreen
{
/**
* A reference to the screen object that created this. Used for navigating between screens.
*/
public final GuiScreen parentScreen;
public String title = "Config GUI";
public String titleLine2;
public final List<IConfigElement> configElements;
public final List<IConfigEntry> initEntries;
public GuiConfigEntries entryList;
private GuiButtonExt btnDefaultAll;
private GuiButtonExt btnUndoAll;
private GuiCheckBox chkApplyGlobally;
public final String modID;
/**
* When set to a non-null value the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed
* if any configElements were changed (includes child screens). If not defined, the events will be posted if the parent gui is null
* or if the parent gui is not an instance of GuiConfig.
*/
public final String configID;
public final boolean isWorldRunning;
public final boolean allRequireWorldRestart;
public final boolean allRequireMcRestart;
public boolean needsRefresh = true;
private HoverChecker undoHoverChecker;
private HoverChecker resetHoverChecker;
private HoverChecker checkBoxHoverChecker;
/**
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. If a non-null value is passed for configID,
* the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed if any configElements were changed
* (includes child screens). If configID is not defined, the events will be posted if the parent gui is null or if the parent gui
* is not an instance of GuiConfig.
*
* @param parentScreen the parent GuiScreen object
* @param configElements a List of IConfigProperty objects
* @param areAllPropsHotLoadable send true if every property on this screen is able to be modified on the fly while a world is running
* @param modID the mod ID for the mod whose config settings will be edited
* @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events. Setting this value will force
* the save action to be called when the Done button is pressed on this screen if any configElements were changed.
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
* edited.
*/
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, String configID,
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title)
{
this(parentScreen, configElements, modID, configID, allRequireWorldRestart, allRequireMcRestart, title, null);
}
/**
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. This constructor passes null for configID.
* If configID is not defined, the events will be posted if the parent gui is null or if the parent gui is not an instance of GuiConfig.
*
* @param parentScreen the parent GuiScreen object
* @param configElements a List of IConfigProperty objects
* @param areAllPropsHotLoadable send true if every property on this screen is able to be modified on the fly while a world is running
* @param modID the mod ID for the mod whose config settings will be edited
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
* edited.
*/
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID,
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title)
{
this(parentScreen, configElements, modID, null, allRequireWorldRestart, allRequireMcRestart, title, null);
}
/**
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. This constructor passes null for configID.
* If configID is not defined, the events will be posted if the parent gui is null or if the parent gui is not an instance of GuiConfig.
*
* @param parentScreen the parent GuiScreen object
* @param configElements a List of IConfigProperty objects
* @param modID the mod ID for the mod whose config settings will be edited
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
* edited.
* @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category
* currently being edited.
*/
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID,
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title, String titleLine2)
{
this(parentScreen, configElements, modID, null, allRequireWorldRestart, allRequireMcRestart, title, titleLine2);
}
/**
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. titleLine2 is specified in this constructor.
* If a non-null value is passed for configID, the OnConfigChanged and PostConfigChanged events will be posted when the Done button is
* pressed if any configElements were changed (includes child screens). If configID is not defined, the events will be posted if the parent
* gui is null or if the parent gui is not an instance of GuiConfig.
*
* @param parentScreen the parent GuiScreen object
* @param configElements a List of IConfigProperty objects
* @param modID the mod ID for the mod whose config settings will be edited
* @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
* edited.
* @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category
* currently being edited.
*/
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, String configID,
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title, String titleLine2)
{
this.mc = Minecraft.getMinecraft();
this.parentScreen = parentScreen;
this.configElements = configElements;
this.entryList = new GuiConfigEntries(this, mc);
this.initEntries = new ArrayList<IConfigEntry>(entryList.listEntries);
this.allRequireWorldRestart = allRequireWorldRestart;
this.allRequireMcRestart = allRequireMcRestart;
this.modID = modID;
this.configID = configID;
this.isWorldRunning = mc.theWorld != null;
if (title != null)
this.title = title;
this.titleLine2 = titleLine2;
if (this.titleLine2 != null && this.titleLine2.startsWith(" > "))
this.titleLine2 = this.titleLine2.replaceFirst(" > ", "");
}
public static String getAbridgedConfigPath(String path)
{
Minecraft mc = Minecraft.getMinecraft();
if (mc.mcDataDir.getAbsolutePath().endsWith("."))
return path.replace("\\", "/").replace(mc.mcDataDir.getAbsolutePath().replace("\\", "/").substring(0, mc.mcDataDir.getAbsolutePath().length() - 1), "/.minecraft/");
else
return path.replace("\\", "/").replace(mc.mcDataDir.getAbsolutePath().replace("\\", "/"), "/.minecraft");
}
@Override
public void initGui()
{
Keyboard.enableRepeatEvents(true);
if (this.entryList == null || this.needsRefresh)
{
this.entryList = new GuiConfigEntries(this, mc);
this.needsRefresh = false;
}
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
int checkWidth = mc.fontRenderer.getStringWidth(I18n.format("fml.configgui.applyGlobally")) + 13;
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth + 5 + checkWidth) / 2;
this.buttonList.add(new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
this.buttonList.add(this.btnDefaultAll = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
this.buttonList.add(btnUndoAll = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
this.buttonList.add(chkApplyGlobally = new GuiCheckBox(2003, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5 + resetWidth + 5,
this.height - 24, I18n.format("fml.configgui.applyGlobally"), false));
this.undoHoverChecker = new HoverChecker(this.btnUndoAll, 800);
this.resetHoverChecker = new HoverChecker(this.btnDefaultAll, 800);
this.checkBoxHoverChecker = new HoverChecker(chkApplyGlobally, 800);
this.entryList.initGui();
}
@Override
public void onGuiClosed()
{
this.entryList.onGuiClosed();
if (this.configID != null && this.parentScreen instanceof GuiConfig)
{
GuiConfig parentGuiConfig = (GuiConfig) this.parentScreen;
parentGuiConfig.needsRefresh = true;
parentGuiConfig.initGui();
}
if (!(this.parentScreen instanceof GuiConfig))
Keyboard.enableRepeatEvents(false);
}
@Override
protected void actionPerformed(GuiButton button)
{
if (button.id == 2000)
{
boolean flag = true;
try
{
if ((configID != null || this.parentScreen == null || !(this.parentScreen instanceof GuiConfig))
&& (this.entryList.hasChangedEntry(true)))
{
boolean requiresMcRestart = this.entryList.saveConfigElements();
if (Loader.isModLoaded(modID))
{
ConfigChangedEvent event = new OnConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart);
FMLCommonHandler.instance().bus().post(event);
if (!event.getResult().equals(Result.DENY))
FMLCommonHandler.instance().bus().post(new PostConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart));
if (requiresMcRestart)
{
flag = false;
mc.displayGuiScreen(new GuiMessageDialog(parentScreen, "fml.configgui.gameRestartTitle",
new ChatComponentText(I18n.format("fml.configgui.gameRestartRequired")), "fml.configgui.confirmRestartMessage"));
}
if (this.parentScreen instanceof GuiConfig)
((GuiConfig) this.parentScreen).needsRefresh = true;
}
}
}
catch (Throwable e)
{
e.printStackTrace();
}
if (flag)
this.mc.displayGuiScreen(this.parentScreen);
}
else if (button.id == 2001)
{
this.entryList.setAllToDefault(this.chkApplyGlobally.isChecked());
}
else if (button.id == 2002)
{
this.entryList.undoAllChanges(this.chkApplyGlobally.isChecked());
}
}
@Override
protected void mouseClicked(int x, int y, int mouseEvent)
{
if (mouseEvent != 0 || !this.entryList.func_148179_a(x, y, mouseEvent))
{
this.entryList.mouseClicked(x, y, mouseEvent);
super.mouseClicked(x, y, mouseEvent);
}
}
@Override
protected void mouseMovedOrUp(int x, int y, int mouseEvent)
{
if (mouseEvent != 0 || !this.entryList.func_148181_b(x, y, mouseEvent))
{
super.mouseMovedOrUp(x, y, mouseEvent);
}
}
@Override
protected void keyTyped(char eventChar, int eventKey)
{
if (eventKey == Keyboard.KEY_ESCAPE)
this.mc.displayGuiScreen(parentScreen);
else
this.entryList.keyTyped(eventChar, eventKey);
}
@Override
public void updateScreen()
{
super.updateScreen();
this.entryList.updateScreen();
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
this.drawDefaultBackground();
this.entryList.drawScreen(mouseX, mouseY, partialTicks);
this.drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 8, 16777215);
String title2 = this.titleLine2;
if (title2 != null)
{
int strWidth = mc.fontRenderer.getStringWidth(title2);
int elipsisWidth = mc.fontRenderer.getStringWidth("...");
if (strWidth > width - 6 && strWidth > elipsisWidth)
title2 = mc.fontRenderer.trimStringToWidth(title2, width - 6 - elipsisWidth).trim() + "...";
this.drawCenteredString(this.fontRendererObj, title2, this.width / 2, 18, 16777215);
}
this.btnUndoAll.enabled = this.entryList.areAnyEntriesEnabled(this.chkApplyGlobally.isChecked()) && this.entryList.hasChangedEntry(this.chkApplyGlobally.isChecked());
this.btnDefaultAll.enabled = this.entryList.areAnyEntriesEnabled(this.chkApplyGlobally.isChecked()) && !this.entryList.areAllEntriesDefault(this.chkApplyGlobally.isChecked());
super.drawScreen(mouseX, mouseY, partialTicks);
this.entryList.drawScreenPost(mouseX, mouseY, partialTicks);
if (this.undoHoverChecker.checkHover(mouseX, mouseY))
this.drawToolTip(this.mc.fontRenderer.listFormattedStringToWidth(I18n.format("fml.configgui.tooltip.undoAll"), 300), mouseX, mouseY);
if (this.resetHoverChecker.checkHover(mouseX, mouseY))
this.drawToolTip(this.mc.fontRenderer.listFormattedStringToWidth(I18n.format("fml.configgui.tooltip.resetAll"), 300), mouseX, mouseY);
if (this.checkBoxHoverChecker.checkHover(mouseX, mouseY))
this.drawToolTip(this.mc.fontRenderer.listFormattedStringToWidth(I18n.format("fml.configgui.tooltip.applyGlobally"), 300), mouseX, mouseY);
}
public void drawToolTip(List stringList, int x, int y)
{
this.func_146283_a(stringList, x, y);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import static cpw.mods.fml.client.config.GuiUtils.RESET_CHAR;
import static cpw.mods.fml.client.config.GuiUtils.UNDO_CHAR;
import org.lwjgl.input.Keyboard;
/**
* This class is the base screen used for editing an array-type property. It provides a list of array entries for the user to edit.
* This screen is invoked from a GuiConfig screen by controls that use the EditListPropEntry IGuiConfigListEntry object.
*
* @author bspkrs
*/
public class GuiEditArray extends GuiScreen
{
protected GuiScreen parentScreen;
protected IConfigElement configElement;
private GuiEditArrayEntries entryList;
private GuiButtonExt btnUndoChanges, btnDefault, btnDone;
private String title;
protected String titleLine2;
protected String titleLine3;
protected int slotIndex;
private final Object[] beforeValues;
private Object[] currentValues;
private HoverChecker tooltipHoverChecker;
private List toolTip;
protected boolean enabled;
public GuiEditArray(GuiScreen parentScreen, IConfigElement configElement, int slotIndex, Object[] currentValues, boolean enabled)
{
this.mc = Minecraft.getMinecraft();
this.parentScreen = parentScreen;
this.configElement = configElement;
this.slotIndex = slotIndex;
this.beforeValues = currentValues;
this.currentValues = currentValues;
this.toolTip = new ArrayList();
this.enabled = enabled;
String propName = I18n.format(configElement.getLanguageKey());
String comment;
comment = I18n.format(configElement.getLanguageKey() + ".tooltip",
"\n" + EnumChatFormatting.AQUA, configElement.getDefault(), configElement.getMinValue(), configElement.getMaxValue());
if (!comment.equals(configElement.getLanguageKey() + ".tooltip"))
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.YELLOW + comment, 300);
else if (configElement.getComment() != null && !configElement.getComment().trim().isEmpty())
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.YELLOW + configElement.getComment(), 300);
else
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.RED + "No tooltip defined.", 300);
if (parentScreen instanceof GuiConfig)
{
this.title = ((GuiConfig) parentScreen).title;
if (((GuiConfig) parentScreen).titleLine2 != null)
{
this.titleLine2 = ((GuiConfig) parentScreen).titleLine2;
this.titleLine3 = I18n.format(configElement.getLanguageKey());
}
else
this.titleLine2 = I18n.format(configElement.getLanguageKey());
this.tooltipHoverChecker = new HoverChecker(28, 37, 0, parentScreen.width, 800);
}
else
{
this.title = I18n.format(configElement.getLanguageKey());
this.tooltipHoverChecker = new HoverChecker(8, 17, 0, parentScreen.width, 800);
}
}
@Override
public void initGui()
{
this.entryList = new GuiEditArrayEntries(this, this.mc, this.configElement, this.beforeValues, this.currentValues);
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth) / 2;
this.buttonList.add(btnDone = new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
this.buttonList.add(btnDefault = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
this.buttonList.add(btnUndoChanges = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
}
@Override
protected void actionPerformed(GuiButton button)
{
if (button.id == 2000)
{
try
{
this.entryList.saveListChanges();
}
catch (Throwable e)
{
e.printStackTrace();
}
this.mc.displayGuiScreen(this.parentScreen);
}
else if (button.id == 2001)
{
this.currentValues = (String[]) configElement.getDefaults();
this.entryList = new GuiEditArrayEntries(this, this.mc, this.configElement, this.beforeValues, this.currentValues);
}
else if (button.id == 2002)
{
this.currentValues = Arrays.copyOf(beforeValues, beforeValues.length);
this.entryList = new GuiEditArrayEntries(this, this.mc, this.configElement, this.beforeValues, this.currentValues);
}
}
@Override
protected void mouseClicked(int x, int y, int mouseEvent)
{
if (mouseEvent != 0 || !this.entryList.func_148179_a(x, y, mouseEvent))
{
this.entryList.mouseClicked(x, y, mouseEvent);
super.mouseClicked(x, y, mouseEvent);
}
}
@Override
protected void mouseMovedOrUp(int x, int y, int mouseEvent)
{
if (mouseEvent != 0 || !this.entryList.func_148181_b(x, y, mouseEvent))
{
super.mouseMovedOrUp(x, y, mouseEvent);
}
}
@Override
protected void keyTyped(char eventChar, int eventKey)
{
if (eventKey == Keyboard.KEY_ESCAPE)
this.mc.displayGuiScreen(parentScreen);
else
this.entryList.keyTyped(eventChar, eventKey);
}
@Override
public void updateScreen()
{
super.updateScreen();
this.entryList.updateScreen();
}
@Override
public void drawScreen(int par1, int par2, float par3)
{
this.drawDefaultBackground();
this.entryList.drawScreen(par1, par2, par3);
this.drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 8, 16777215);
if (this.titleLine2 != null)
this.drawCenteredString(this.fontRendererObj, this.titleLine2, this.width / 2, 18, 16777215);
if (this.titleLine3 != null)
this.drawCenteredString(this.fontRendererObj, this.titleLine3, this.width / 2, 28, 16777215);
this.btnDone.enabled = this.entryList.isListSavable();
this.btnDefault.enabled = enabled && !this.entryList.isDefault();
this.btnUndoChanges.enabled = enabled && this.entryList.isChanged();
super.drawScreen(par1, par2, par3);
this.entryList.drawScreenPost(par1, par2, par3);
if (this.tooltipHoverChecker != null && this.tooltipHoverChecker.checkHover(par1, par2))
drawToolTip(this.toolTip, par1, par2);
}
public void drawToolTip(List stringList, int x, int y)
{
this.func_146283_a(stringList, x, y);
}
}

View File

@ -0,0 +1,671 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiListExtended;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
import static cpw.mods.fml.client.config.GuiUtils.INVALID;
import static cpw.mods.fml.client.config.GuiUtils.VALID;
import cpw.mods.fml.client.config.GuiConfigEntries.ArrayEntry;
import cpw.mods.fml.common.FMLLog;
/**
* This class implements the scrolling list functionality of the GuiEditList screen. It also provides all the default controls
* for editing array-type properties.
*
* @author bspkrs
*/
public class GuiEditArrayEntries extends GuiListExtended
{
private GuiEditArray owningGui;
public Minecraft mc;
public IConfigElement configElement;
public List<IArrayEntry> listEntries;
public boolean isDefault;
public boolean isChanged;
public boolean canAddMoreEntries;
public final int controlWidth;
public final Object[] beforeValues;
public Object[] currentValues;
public GuiEditArrayEntries(GuiEditArray parent, Minecraft mc, IConfigElement configElement, Object[] beforeValues, Object[] currentValues)
{
super(mc, parent.width, parent.height, parent.titleLine2 != null ? (parent.titleLine3 != null ? 43 : 33) : 23, parent.height - 32, 20);
this.owningGui = parent;
this.mc = mc;
this.configElement = configElement;
this.beforeValues = beforeValues;
this.currentValues = currentValues;
this.setShowSelectionBox(false);
this.isChanged = !Arrays.deepEquals(beforeValues, currentValues);
this.isDefault = Arrays.deepEquals(currentValues, configElement.getDefaults());
this.canAddMoreEntries = !configElement.isListLengthFixed() && (configElement.getMaxListLength() == -1 || currentValues.length < configElement.getMaxListLength());
listEntries = new ArrayList<IArrayEntry>();
controlWidth = (parent.width / 2) - (configElement.isListLengthFixed() ? 0 : 48);
if (configElement.isList() && configElement.getArrayEntryClass() != null)
{
Class<? extends IArrayEntry> clazz = configElement.getArrayEntryClass();
for (Object value : currentValues)
{
try
{
listEntries.add(clazz.getConstructor(GuiEditArray.class, GuiEditArrayEntries.class, IConfigElement.class, Object.class)
.newInstance(this.owningGui, this, configElement, value.toString()));
}
catch (Throwable e)
{
FMLLog.severe("There was a critical error instantiating the custom IGuiEditListEntry for property %s.", configElement.getName());
e.printStackTrace();
}
}
}
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.BOOLEAN))
for (Object value : currentValues)
listEntries.add(new BooleanEntry(this.owningGui, this, configElement, Boolean.valueOf(value.toString())));
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.INTEGER))
for (Object value : currentValues)
listEntries.add(new IntegerEntry(this.owningGui, this, configElement, Integer.parseInt(value.toString())));
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.DOUBLE))
for (Object value : currentValues)
listEntries.add(new DoubleEntry(this.owningGui, this, configElement, Double.parseDouble(value.toString())));
else if (configElement.isList())
for (Object value : currentValues)
listEntries.add(new StringEntry(this.owningGui, this, configElement, value.toString()));
if (!configElement.isListLengthFixed())
listEntries.add(new BaseEntry(this.owningGui, this, configElement));
}
@Override
protected int getScrollBarX()
{
return width - (width / 4);
}
/**
* Gets the width of the list
*/
@Override
public int getListWidth()
{
return owningGui.width;
}
@Override
public IArrayEntry getListEntry(int index)
{
return listEntries.get(index);
}
@Override
protected int getSize()
{
return listEntries.size();
}
public void addNewEntry(int index)
{
if (configElement.isList() && configElement.getType() == ConfigGuiType.BOOLEAN)
listEntries.add(index, new BooleanEntry(this.owningGui, this, this.configElement, Boolean.valueOf(true)));
else if (configElement.isList() && configElement.getType() == ConfigGuiType.INTEGER)
listEntries.add(index, new IntegerEntry(this.owningGui, this, this.configElement, 0));
else if (configElement.isList() && configElement.getType() == ConfigGuiType.DOUBLE)
listEntries.add(index, new DoubleEntry(this.owningGui, this, this.configElement, 0.0D));
else if (configElement.isList())
listEntries.add(index, new StringEntry(this.owningGui, this, this.configElement, ""));
this.canAddMoreEntries = !configElement.isListLengthFixed()
&& (configElement.getMaxListLength() == -1 || this.listEntries.size() - 1 < configElement.getMaxListLength());
keyTyped((char) Keyboard.CHAR_NONE, Keyboard.KEY_END);
}
public void removeEntry(int index)
{
this.listEntries.remove(index);
this.canAddMoreEntries = !configElement.isListLengthFixed()
&& (configElement.getMaxListLength() == -1 || this.listEntries.size() - 1 < configElement.getMaxListLength());
keyTyped((char) Keyboard.CHAR_NONE, Keyboard.KEY_END);
}
public boolean isChanged()
{
return isChanged;
}
public boolean isDefault()
{
return isDefault;
}
public void recalculateState()
{
isDefault = true;
isChanged = false;
int listLength = configElement.isListLengthFixed() ? listEntries.size() : listEntries.size() - 1;
if (listLength != configElement.getDefaults().length)
{
isDefault = false;
}
if (listLength != beforeValues.length)
{
isChanged = true;
}
if (isDefault)
for (int i = 0; i < listLength; i++)
if (!configElement.getDefaults()[i].equals(listEntries.get(i).getValue()))
isDefault = false;
if (!isChanged)
for (int i = 0; i < listLength; i++)
if (!beforeValues[i].equals(listEntries.get(i).getValue()))
isChanged = true;
}
protected void keyTyped(char eventChar, int eventKey)
{
for (IArrayEntry entry : this.listEntries)
entry.keyTyped(eventChar, eventKey);
recalculateState();
}
protected void updateScreen()
{
for (IArrayEntry entry : this.listEntries)
entry.updateCursorCounter();
}
protected void mouseClicked(int x, int y, int mouseEvent)
{
for (IArrayEntry entry : this.listEntries)
entry.mouseClicked(x, y, mouseEvent);
}
protected boolean isListSavable()
{
for (IArrayEntry entry : this.listEntries)
if (!entry.isValueSavable())
return false;
return true;
}
protected void saveListChanges()
{
int listLength = configElement.isListLengthFixed() ? listEntries.size() : listEntries.size() - 1;
if (owningGui.slotIndex != -1 && owningGui.parentScreen != null
&& owningGui.parentScreen instanceof GuiConfig
&& ((GuiConfig) owningGui.parentScreen).entryList.getListEntry(owningGui.slotIndex) instanceof ArrayEntry)
{
ArrayEntry entry = (ArrayEntry) ((GuiConfig) owningGui.parentScreen).entryList.getListEntry(owningGui.slotIndex);
Object[] ao = new Object[listLength];
for (int i = 0; i < listLength; i++)
ao[i] = listEntries.get(i).getValue();
entry.setListFromChildScreen(ao);
}
else
{
if (configElement.isList() && configElement.getType() == ConfigGuiType.BOOLEAN)
{
Boolean[] abol = new Boolean[listLength];
for (int i = 0; i < listLength; i++)
abol[i] = Boolean.valueOf(listEntries.get(i).getValue().toString());
configElement.set(abol);
}
else if (configElement.isList() && configElement.getType() == ConfigGuiType.INTEGER)
{
Integer[] ai = new Integer[listLength];
for (int i = 0; i < listLength; i++)
ai[i] = Integer.valueOf(listEntries.get(i).getValue().toString());
configElement.set(ai);
}
else if (configElement.isList() && configElement.getType() == ConfigGuiType.DOUBLE)
{
Double[] ad = new Double[listLength];
for (int i = 0; i < listLength; i++)
ad[i] = Double.valueOf(listEntries.get(i).getValue().toString());
configElement.set(ad);
}
else if (configElement.isList())
{
String[] as = new String[listLength];
for (int i = 0; i < listLength; i++)
as[i] = listEntries.get(i).getValue().toString();
configElement.set(as);
}
}
}
protected void drawScreenPost(int mouseX, int mouseY, float f)
{
for (IArrayEntry entry : this.listEntries)
entry.drawToolTip(mouseX, mouseY);
}
/**
* IGuiListEntry Inner Classes
*/
public static class DoubleEntry extends StringEntry
{
public DoubleEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Double value)
{
super(owningScreen, owningEntryList, configElement, value);
this.isValidated = true;
}
@Override
public void keyTyped(char eventChar, int eventKey)
{
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
{
String validChars = "0123456789";
String before = this.textFieldValue.getText();
if (validChars.contains(String.valueOf(eventChar)) ||
(!before.startsWith("-") && this.textFieldValue.getCursorPosition() == 0 && eventChar == '-')
|| (!before.contains(".") && eventChar == '.')
|| eventKey == Keyboard.KEY_BACK || eventKey == Keyboard.KEY_DELETE || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
if (!textFieldValue.getText().trim().isEmpty() && !textFieldValue.getText().trim().equals("-"))
{
try
{
double value = Double.parseDouble(textFieldValue.getText().trim());
if (value < Double.valueOf(configElement.getMinValue().toString()) || value > Double.valueOf(configElement.getMaxValue().toString()))
this.isValidValue = false;
else
this.isValidValue = true;
}
catch (Throwable e)
{
this.isValidValue = false;
}
}
else
this.isValidValue = false;
}
}
@Override
public Double getValue()
{
try
{
return Double.valueOf(this.textFieldValue.getText().trim());
}
catch (Throwable e)
{
return Double.MAX_VALUE;
}
}
}
public static class IntegerEntry extends StringEntry
{
public IntegerEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Integer value)
{
super(owningScreen, owningEntryList, configElement, value);
this.isValidated = true;
}
@Override
public void keyTyped(char eventChar, int eventKey)
{
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
{
String validChars = "0123456789";
String before = this.textFieldValue.getText();
if (validChars.contains(String.valueOf(eventChar))
|| (!before.startsWith("-") && this.textFieldValue.getCursorPosition() == 0 && eventChar == '-')
|| eventKey == Keyboard.KEY_BACK || eventKey == Keyboard.KEY_DELETE
|| eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT || eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
if (!textFieldValue.getText().trim().isEmpty() && !textFieldValue.getText().trim().equals("-"))
{
try
{
long value = Long.parseLong(textFieldValue.getText().trim());
if (value < Integer.valueOf(configElement.getMinValue().toString()) || value > Integer.valueOf(configElement.getMaxValue().toString()))
this.isValidValue = false;
else
this.isValidValue = true;
}
catch (Throwable e)
{
this.isValidValue = false;
}
}
else
this.isValidValue = false;
}
}
@Override
public Integer getValue()
{
try
{
return Integer.valueOf(this.textFieldValue.getText().trim());
}
catch (Throwable e)
{
return Integer.MAX_VALUE;
}
}
}
public static class StringEntry extends BaseEntry
{
protected final GuiTextField textFieldValue;
public StringEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Object value)
{
super(owningScreen, owningEntryList, configElement);
this.textFieldValue = new GuiTextField(owningEntryList.mc.fontRenderer, owningEntryList.width / 4 + 1, 0, owningEntryList.controlWidth - 3, 16);
this.textFieldValue.setMaxStringLength(10000);
this.textFieldValue.setText(value.toString());
this.isValidated = configElement.getValidationPattern() != null;
if (configElement.getValidationPattern() != null)
{
if (configElement.getValidationPattern().matcher(this.textFieldValue.getText().trim()).matches())
isValidValue = true;
else
isValidValue = false;
}
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isSelected)
{
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, tessellator, mouseX, mouseY, isSelected);
if (configElement.isListLengthFixed() || slotIndex != owningEntryList.listEntries.size() - 1)
{
this.textFieldValue.setVisible(true);
this.textFieldValue.yPosition = y + 1;
this.textFieldValue.drawTextBox();
}
else
this.textFieldValue.setVisible(false);
}
@Override
public void keyTyped(char eventChar, int eventKey)
{
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
{
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
if (configElement.getValidationPattern() != null)
{
if (configElement.getValidationPattern().matcher(this.textFieldValue.getText().trim()).matches())
isValidValue = true;
else
isValidValue = false;
}
}
}
@Override
public void updateCursorCounter()
{
this.textFieldValue.updateCursorCounter();
}
@Override
public void mouseClicked(int x, int y, int mouseEvent)
{
this.textFieldValue.mouseClicked(x, y, mouseEvent);
}
@Override
public Object getValue()
{
return this.textFieldValue.getText().trim();
}
}
public static class BooleanEntry extends BaseEntry
{
protected final GuiButtonExt btnValue;
private boolean value;
public BooleanEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, boolean value)
{
super(owningScreen, owningEntryList, configElement);
this.value = value;
this.btnValue = new GuiButtonExt(0, 0, 0, owningEntryList.controlWidth, 18, I18n.format(String.valueOf(value)));
this.btnValue.enabled = owningScreen.enabled;
this.isValidated = false;
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isSelected)
{
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, tessellator, mouseX, mouseY, isSelected);
this.btnValue.xPosition = listWidth / 4;
this.btnValue.yPosition = y;
String trans = I18n.format(String.valueOf(value));
if (!trans.equals(String.valueOf(value)))
this.btnValue.displayString = trans;
else
this.btnValue.displayString = String.valueOf(value);
btnValue.packedFGColour = value ? GuiUtils.getColorCode('2', true) : GuiUtils.getColorCode('4', true);
this.btnValue.drawButton(owningEntryList.mc, mouseX, mouseY);
}
@Override
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
if (this.btnValue.mousePressed(owningEntryList.mc, x, y))
{
btnValue.func_146113_a(owningEntryList.mc.getSoundHandler());
value = !value;
owningEntryList.recalculateState();
return true;
}
return super.mousePressed(index, x, y, mouseEvent, relativeX, relativeY);
}
@Override
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
this.btnValue.mouseReleased(x, y);
super.mouseReleased(index, x, y, mouseEvent, relativeX, relativeY);
}
@Override
public Object getValue()
{
return Boolean.valueOf(value);
}
}
public static class BaseEntry implements IArrayEntry
{
protected final GuiEditArray owningScreen;
protected final GuiEditArrayEntries owningEntryList;
protected final IConfigElement configElement;
protected final GuiButtonExt btnAddNewEntryAbove;
private final HoverChecker addNewEntryAboveHoverChecker;
protected final GuiButtonExt btnRemoveEntry;
private final HoverChecker removeEntryHoverChecker;
private List addNewToolTip, removeToolTip;
protected boolean isValidValue = true;
protected boolean isValidated = false;
public BaseEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement)
{
this.owningScreen = owningScreen;
this.owningEntryList = owningEntryList;
this.configElement = configElement;
this.btnAddNewEntryAbove = new GuiButtonExt(0, 0, 0, 18, 18, "+");
this.btnAddNewEntryAbove.packedFGColour = GuiUtils.getColorCode('2', true);
this.btnAddNewEntryAbove.enabled = owningScreen.enabled;
this.btnRemoveEntry = new GuiButtonExt(0, 0, 0, 18, 18, "x");
this.btnRemoveEntry.packedFGColour = GuiUtils.getColorCode('c', true);
this.btnRemoveEntry.enabled = owningScreen.enabled;
this.addNewEntryAboveHoverChecker = new HoverChecker(this.btnAddNewEntryAbove, 800);
this.removeEntryHoverChecker = new HoverChecker(this.btnRemoveEntry, 800);
this.addNewToolTip = new ArrayList();
this.removeToolTip = new ArrayList();
addNewToolTip.add(I18n.format("fml.configgui.tooltip.addNewEntryAbove"));
removeToolTip.add(I18n.format("fml.configgui.tooltip.removeEntry"));
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isSelected)
{
if (this.getValue() != null && this.isValidated)
owningEntryList.mc.fontRenderer.drawString(
isValidValue ? EnumChatFormatting.GREEN + VALID : EnumChatFormatting.RED + INVALID,
listWidth / 4 - owningEntryList.mc.fontRenderer.getStringWidth(VALID) - 2,
y + slotHeight / 2 - owningEntryList.mc.fontRenderer.FONT_HEIGHT / 2,
16777215);
int half = listWidth / 2;
if (owningEntryList.canAddMoreEntries)
{
this.btnAddNewEntryAbove.visible = true;
this.btnAddNewEntryAbove.xPosition = half + ((half / 2) - 44);
this.btnAddNewEntryAbove.yPosition = y;
this.btnAddNewEntryAbove.drawButton(owningEntryList.mc, mouseX, mouseY);
}
else
this.btnAddNewEntryAbove.visible = false;
if (!configElement.isListLengthFixed() && slotIndex != owningEntryList.listEntries.size() - 1)
{
this.btnRemoveEntry.visible = true;
this.btnRemoveEntry.xPosition = half + ((half / 2) - 22);
this.btnRemoveEntry.yPosition = y;
this.btnRemoveEntry.drawButton(owningEntryList.mc, mouseX, mouseY);
}
else
this.btnRemoveEntry.visible = false;
}
@Override
public void drawToolTip(int mouseX, int mouseY)
{
boolean canHover = mouseY < owningEntryList.bottom && mouseY > owningEntryList.top;
if (this.btnAddNewEntryAbove.visible && this.addNewEntryAboveHoverChecker.checkHover(mouseX, mouseY, canHover))
owningScreen.drawToolTip(this.addNewToolTip, mouseX, mouseY);
if (this.btnRemoveEntry.visible && this.removeEntryHoverChecker.checkHover(mouseX, mouseY, canHover))
owningScreen.drawToolTip(this.removeToolTip, mouseX, mouseY);
}
@Override
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
if (this.btnAddNewEntryAbove.mousePressed(owningEntryList.mc, x, y))
{
btnAddNewEntryAbove.func_146113_a(owningEntryList.mc.getSoundHandler());
owningEntryList.addNewEntry(index);
owningEntryList.recalculateState();
return true;
}
else if (this.btnRemoveEntry.mousePressed(owningEntryList.mc, x, y))
{
btnRemoveEntry.func_146113_a(owningEntryList.mc.getSoundHandler());
owningEntryList.removeEntry(index);
owningEntryList.recalculateState();
return true;
}
return false;
}
@Override
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
this.btnAddNewEntryAbove.mouseReleased(x, y);
this.btnRemoveEntry.mouseReleased(x, y);
}
@Override
public void keyTyped(char eventChar, int eventKey)
{}
@Override
public void updateCursorCounter()
{}
@Override
public void mouseClicked(int x, int y, int mouseEvent)
{}
@Override
public boolean isValueSavable()
{
return isValidValue;
}
@Override
public Object getValue()
{
return null;
}
}
public static interface IArrayEntry extends GuiListExtended.IGuiListEntry
{
public void keyTyped(char eventChar, int eventKey);
public void updateCursorCounter();
public void mouseClicked(int x, int y, int mouseEvent);
public void drawToolTip(int mouseX, int mouseY);
public boolean isValueSavable();
public Object getValue();
}
}

View File

@ -0,0 +1,24 @@
package cpw.mods.fml.client.config;
import net.minecraft.client.gui.GuiDisconnected;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.IChatComponent;
public class GuiMessageDialog extends GuiDisconnected
{
private String buttonText;
public GuiMessageDialog(GuiScreen nextScreen, String title, IChatComponent message, String buttonText)
{
super(nextScreen, title, message);
this.buttonText = buttonText;
}
public void initGui()
{
super.initGui();
((GuiButton) buttonList.get(0)).displayString = I18n.format(buttonText);
}
}

View File

@ -0,0 +1,172 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import static cpw.mods.fml.client.config.GuiUtils.RESET_CHAR;
import static cpw.mods.fml.client.config.GuiUtils.UNDO_CHAR;
/**
* This class provides a screen that allows the user to select a value from a list.
*
* @author bspkrs
*/
public class GuiSelectString extends GuiScreen
{
protected GuiScreen parentScreen;
protected IConfigElement configElement;
private GuiSelectStringEntries entriesList;
private GuiButtonExt btnUndoChanges, btnDefault, btnDone;
private String title;
protected String titleLine2;
protected String titleLine3;
protected int slotIndex;
private final Map<Object, String> selectableValues;
public final Object beforeValue;
public Object currentValue;
private HoverChecker tooltipHoverChecker;
private List toolTip;
protected boolean enabled;
public GuiSelectString(GuiScreen parentScreen, IConfigElement configElement, int slotIndex, Map<Object, String> selectableValues, Object currentValue, boolean enabled)
{
this.mc = Minecraft.getMinecraft();
this.parentScreen = parentScreen;
this.configElement = configElement;
this.slotIndex = slotIndex;
this.selectableValues = selectableValues;
this.beforeValue = currentValue;
this.currentValue = currentValue;
this.toolTip = new ArrayList();
this.enabled = enabled;
String propName = I18n.format(configElement.getLanguageKey());
String comment;
comment = I18n.format(configElement.getLanguageKey() + ".tooltip",
"\n" + EnumChatFormatting.AQUA, configElement.getDefault(), configElement.getMinValue(), configElement.getMaxValue());
if (!comment.equals(configElement.getLanguageKey() + ".tooltip"))
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.YELLOW + comment, 300);
else if (configElement.getComment() != null && !configElement.getComment().trim().isEmpty())
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.YELLOW + configElement.getComment(), 300);
else
toolTip = mc.fontRenderer.listFormattedStringToWidth(
EnumChatFormatting.GREEN + propName + "\n" + EnumChatFormatting.RED + "No tooltip defined.", 300);
if (parentScreen instanceof GuiConfig)
{
this.title = ((GuiConfig) parentScreen).title;
this.titleLine2 = ((GuiConfig) parentScreen).titleLine2;
this.titleLine3 = I18n.format(configElement.getLanguageKey());
this.tooltipHoverChecker = new HoverChecker(28, 37, 0, parentScreen.width, 800);
}
else
{
this.title = I18n.format(configElement.getLanguageKey());
this.tooltipHoverChecker = new HoverChecker(8, 17, 0, parentScreen.width, 800);
}
}
@Override
public void initGui()
{
this.entriesList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth) / 2;
this.buttonList.add(btnDone = new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
this.buttonList.add(btnDefault = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
this.buttonList.add(btnUndoChanges = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
}
@Override
protected void actionPerformed(GuiButton button)
{
if (button.id == 2000)
{
try
{
this.entriesList.saveChanges();
}
catch (Throwable e)
{
e.printStackTrace();
}
this.mc.displayGuiScreen(this.parentScreen);
}
else if (button.id == 2001)
{
this.currentValue = configElement.getDefault();
this.entriesList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
}
else if (button.id == 2002)
{
this.currentValue = beforeValue;
this.entriesList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
}
}
@Override
protected void mouseMovedOrUp(int x, int y, int mouseEvent)
{
if (mouseEvent != 0 || !this.entriesList.func_148181_b(x, y, mouseEvent))
{
super.mouseMovedOrUp(x, y, mouseEvent);
}
}
@Override
public void drawScreen(int par1, int par2, float par3)
{
this.drawDefaultBackground();
this.entriesList.drawScreen(par1, par2, par3);
this.drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 8, 16777215);
if (this.titleLine2 != null)
this.drawCenteredString(this.fontRendererObj, this.titleLine2, this.width / 2, 18, 16777215);
if (this.titleLine3 != null)
this.drawCenteredString(this.fontRendererObj, this.titleLine3, this.width / 2, 28, 16777215);
this.btnDone.enabled = currentValue != null;
this.btnDefault.enabled = enabled && !this.entriesList.isDefault();
this.btnUndoChanges.enabled = enabled && this.entriesList.isChanged();
super.drawScreen(par1, par2, par3);
if (this.tooltipHoverChecker != null && this.tooltipHoverChecker.checkHover(par1, par2))
drawToolTip(this.toolTip, par1, par2);
}
public void drawToolTip(List stringList, int x, int y)
{
this.func_146283_a(stringList, x, y);
}
}

View File

@ -0,0 +1,196 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiListExtended;
import net.minecraft.client.renderer.Tessellator;
import cpw.mods.fml.client.config.GuiConfigEntries.SelectValueEntry;
/**
* This class implements the scrolling list functionality of the GuiSelectString screen.
*
* @author bspkrs
*/
public class GuiSelectStringEntries extends GuiListExtended
{
public GuiSelectString owningScreen;
public Minecraft mc;
public IConfigElement configElement;
public List<IGuiSelectStringListEntry> listEntries;
public final Map<Object, String> selectableValues;
public int selectedIndex = -1;
public int maxEntryWidth = 0;
public GuiSelectStringEntries(GuiSelectString owningScreen, Minecraft mc, IConfigElement configElement, Map<Object, String> selectableValues)
{
super(mc, owningScreen.width, owningScreen.height, owningScreen.titleLine2 != null ? (owningScreen.titleLine3 != null ? 43 : 33) : 23,
owningScreen.height - 32, 11);
this.owningScreen = owningScreen;
this.mc = mc;
this.configElement = configElement;
this.selectableValues = selectableValues;
this.setShowSelectionBox(true);
listEntries = new ArrayList<IGuiSelectStringListEntry>();
int index = 0;
List<Entry<Object, String>> sortedList = new ArrayList<Entry<Object, String>>(selectableValues.entrySet());
Collections.sort(sortedList, new EntryComparator());
for (Entry<Object, String> entry : sortedList)
{
listEntries.add(new ListEntry(this, entry));
if (mc.fontRenderer.getStringWidth(entry.getValue()) > maxEntryWidth)
maxEntryWidth = mc.fontRenderer.getStringWidth(entry.getValue());
if (owningScreen.currentValue.equals(entry.getKey()))
{
this.selectedIndex = index;
}
index++;
}
}
public static class EntryComparator implements Comparator<Entry<Object, String>>
{
@Override
public int compare(Entry<Object, String> o1, Entry<Object, String> o2)
{
int compare = o1.getValue().toLowerCase(Locale.US).compareTo(o2.getValue().toLowerCase(Locale.US));
if (compare == 0)
compare = o1.getKey().toString().toLowerCase(Locale.US).compareTo(o2.getKey().toString().toLowerCase(Locale.US));
return compare;
}
}
/**
* The element in the slot that was clicked, boolean for whether it was double clicked or not
*/
@Override
protected void elementClicked(int index, boolean doubleClick, int mouseX, int mouseY)
{
selectedIndex = index;
owningScreen.currentValue = listEntries.get(index).getValue();
}
/**
* Returns true if the element passed in is currently selected
*/
@Override
protected boolean isSelected(int index)
{
return index == selectedIndex;
}
@Override
protected int getScrollBarX()
{
return width / 2 + this.maxEntryWidth / 2 + 5;
}
/**
* Gets the width of the list
*/
@Override
public int getListWidth()
{
return maxEntryWidth + 5;
}
@Override
public IGuiSelectStringListEntry getListEntry(int index)
{
return listEntries.get(index);
}
@Override
protected int getSize()
{
return listEntries.size();
}
public boolean isChanged()
{
return owningScreen.beforeValue != null ? !owningScreen.beforeValue.equals(owningScreen.currentValue) : owningScreen.currentValue != null;
}
public boolean isDefault()
{
return owningScreen.currentValue != null ? owningScreen.currentValue.equals(configElement.getDefault()) : configElement.getDefault() == null;
}
public void saveChanges()
{
if (owningScreen.slotIndex != -1 && owningScreen.parentScreen != null
&& owningScreen.parentScreen instanceof GuiConfig
&& ((GuiConfig) owningScreen.parentScreen).entryList.getListEntry(owningScreen.slotIndex) instanceof SelectValueEntry)
{
SelectValueEntry entry = (SelectValueEntry) ((GuiConfig) owningScreen.parentScreen).entryList.getListEntry(owningScreen.slotIndex);
entry.setValueFromChildScreen(owningScreen.currentValue);
}
else
configElement.set(owningScreen.currentValue);
}
public static class ListEntry implements IGuiSelectStringListEntry
{
protected final GuiSelectStringEntries owningList;
protected final Entry<Object, String> value;
public ListEntry(GuiSelectStringEntries owningList, Entry<Object, String> value)
{
this.owningList = owningList;
this.value = value;
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isSelected)
{
owningList.mc.fontRenderer.drawString(value.getValue(), x + 1, y, slotIndex == owningList.selectedIndex ? 16777215 : 14737632);
}
@Override
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
return false;
}
@Override
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{}
@Override
public Object getValue()
{
return value.getKey();
}
}
public static interface IGuiSelectStringListEntry extends GuiListExtended.IGuiListEntry
{
public Object getValue();
}
}

View File

@ -0,0 +1,83 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL11;
/**
* This class provides a button that shows a string glyph at the beginning. The glyph can be scaled using the glyphScale parameter.
*
* @author bspkrs
*/
public class GuiUnicodeGlyphButton extends GuiButtonExt
{
public String glyph;
public float glyphScale;
public GuiUnicodeGlyphButton(int id, int xPos, int yPos, int width, int height, String displayString, String glyph, float glyphScale)
{
super(id, xPos, yPos, width, height, displayString);
this.glyph = glyph;
this.glyphScale = glyphScale;
}
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY)
{
if (this.visible)
{
this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height;
int k = this.getHoverState(this.field_146123_n);
GuiUtils.drawContinuousTexturedBox(buttonTextures, this.xPosition, this.yPosition, 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.zLevel);
this.mouseDragged(mc, mouseX, mouseY);
int color = 14737632;
if (packedFGColour != 0)
{
color = packedFGColour;
}
else if (!this.enabled)
{
color = 10526880;
}
else if (this.field_146123_n)
{
color = 16777120;
}
String buttonText = this.displayString;
int glyphWidth = (int) (mc.fontRenderer.getStringWidth(glyph) * glyphScale);
int strWidth = mc.fontRenderer.getStringWidth(buttonText);
int elipsisWidth = mc.fontRenderer.getStringWidth("...");
int totalWidth = strWidth + glyphWidth;
if (totalWidth > width - 6 && totalWidth > elipsisWidth)
buttonText = mc.fontRenderer.trimStringToWidth(buttonText, width - 6 - elipsisWidth).trim() + "...";
strWidth = mc.fontRenderer.getStringWidth(buttonText);
totalWidth = glyphWidth + strWidth;
GL11.glPushMatrix();
GL11.glScalef(glyphScale, glyphScale, 1.0F);
this.drawCenteredString(mc.fontRenderer, glyph,
(int) (((this.xPosition + (this.width / 2) - (strWidth / 2)) / glyphScale) - (glyphWidth / (2 * glyphScale)) + 2),
(int) (((this.yPosition + ((this.height - 8) / glyphScale) / 2) - 1) / glyphScale), color);
GL11.glPopMatrix();
this.drawCenteredString(mc.fontRenderer, buttonText, (int) (this.xPosition + (this.width / 2) + (glyphWidth / glyphScale)),
this.yPosition + (this.height - 8) / 2, color);
}
}
}

View File

@ -0,0 +1,194 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
/**
* This class provides several methods and constants used by the Config GUI classes.
*
* @author bspkrs
*/
public class GuiUtils
{
public static final String UNDO_CHAR = "\u21B6";
public static final String RESET_CHAR = "\u2604";
public static final String VALID = "\u2714";
public static final String INVALID = "\u2715";
private static int[] colorCodes = new int[] { 0, 170, 43520, 43690, 11141120, 11141290, 16755200, 11184810, 5592405, 5592575, 5635925, 5636095, 16733525, 16733695, 16777045, 16777215,
0, 42, 10752, 10794, 2752512, 2752554, 2763264, 2763306, 1381653, 1381695, 1392405, 1392447, 4134165, 4134207, 4144917, 4144959 };
public static int getColorCode(char c, boolean isLighter)
{
return colorCodes[isLighter ? "0123456789abcdef".indexOf(c) : "0123456789abcdef".indexOf(c) + 16];
}
/**
* Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders
* and filler. It is assumed that the desired texture ResourceLocation object has been bound using
* Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation).
*
* @param x x axis offset
* @param y y axis offset
* @param u bound resource location image x offset
* @param v bound resource location image y offset
* @param width the desired box width
* @param height the desired box height
* @param textureWidth the width of the box texture in the resource location image
* @param textureHeight the height of the box texture in the resource location image
* @param borderSize the size of the box's borders
* @param zLevel the zLevel to draw at
*/
public static void drawContinuousTexturedBox(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight,
int borderSize, float zLevel)
{
drawContinuousTexturedBox(x, y, u, v, width, height, textureWidth, textureHeight, borderSize, borderSize, borderSize, borderSize, zLevel);
}
/**
* Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders
* and filler. The provided ResourceLocation object will be bound using
* Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation).
*
* @param res the ResourceLocation object that contains the desired image
* @param x x axis offset
* @param y y axis offset
* @param u bound resource location image x offset
* @param v bound resource location image y offset
* @param width the desired box width
* @param height the desired box height
* @param textureWidth the width of the box texture in the resource location image
* @param textureHeight the height of the box texture in the resource location image
* @param borderSize the size of the box's borders
* @param zLevel the zLevel to draw at
*/
public static void drawContinuousTexturedBox(ResourceLocation res, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight,
int borderSize, float zLevel)
{
drawContinuousTexturedBox(res, x, y, u, v, width, height, textureWidth, textureHeight, borderSize, borderSize, borderSize, borderSize, zLevel);
}
/**
* Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders
* and filler. The provided ResourceLocation object will be bound using
* Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation).
*
* @param res the ResourceLocation object that contains the desired image
* @param x x axis offset
* @param y y axis offset
* @param u bound resource location image x offset
* @param v bound resource location image y offset
* @param width the desired box width
* @param height the desired box height
* @param textureWidth the width of the box texture in the resource location image
* @param textureHeight the height of the box texture in the resource location image
* @param topBorder the size of the box's top border
* @param bottomBorder the size of the box's bottom border
* @param leftBorder the size of the box's left border
* @param rightBorder the size of the box's right border
* @param zLevel the zLevel to draw at
*/
public static void drawContinuousTexturedBox(ResourceLocation res, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight,
int topBorder, int bottomBorder, int leftBorder, int rightBorder, float zLevel)
{
Minecraft.getMinecraft().getTextureManager().bindTexture(res);
drawContinuousTexturedBox(x, y, u, v, width, height, textureWidth, textureHeight, topBorder, bottomBorder, leftBorder, rightBorder, zLevel);
}
/**
* Draws a textured box of any size (smallest size is borderSize * 2 square) based on a fixed size textured box with continuous borders
* and filler. It is assumed that the desired texture ResourceLocation object has been bound using
* Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation).
*
* @param x x axis offset
* @param y y axis offset
* @param u bound resource location image x offset
* @param v bound resource location image y offset
* @param width the desired box width
* @param height the desired box height
* @param textureWidth the width of the box texture in the resource location image
* @param textureHeight the height of the box texture in the resource location image
* @param topBorder the size of the box's top border
* @param bottomBorder the size of the box's bottom border
* @param leftBorder the size of the box's left border
* @param rightBorder the size of the box's right border
* @param zLevel the zLevel to draw at
*/
public static void drawContinuousTexturedBox(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight,
int topBorder, int bottomBorder, int leftBorder, int rightBorder, float zLevel)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glEnable(GL11.GL_BLEND);
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
int fillerWidth = textureWidth - leftBorder - rightBorder;
int fillerHeight = textureHeight - topBorder - bottomBorder;
int canvasWidth = width - leftBorder - rightBorder;
int canvasHeight = height - topBorder - bottomBorder;
int xPasses = canvasWidth / fillerWidth;
int remainderWidth = canvasWidth % fillerWidth;
int yPasses = canvasHeight / fillerHeight;
int remainderHeight = canvasHeight % fillerHeight;
// Draw Border
// Top Left
drawTexturedModalRect(x, y, u, v, leftBorder, topBorder, zLevel);
// Top Right
drawTexturedModalRect(x + leftBorder + canvasWidth, y, u + leftBorder + fillerWidth, v, rightBorder, topBorder, zLevel);
// Bottom Left
drawTexturedModalRect(x, y + topBorder + canvasHeight, u, v + topBorder + fillerHeight, leftBorder, bottomBorder, zLevel);
// Bottom Right
drawTexturedModalRect(x + leftBorder + canvasWidth, y + topBorder + canvasHeight, u + leftBorder + fillerWidth, v + topBorder + fillerHeight, rightBorder, bottomBorder, zLevel);
for (int i = 0; i < xPasses + (remainderWidth > 0 ? 1 : 0); i++)
{
// Top Border
drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y, u + leftBorder, v, (i == xPasses ? remainderWidth : fillerWidth), topBorder, zLevel);
// Bottom Border
drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y + topBorder + canvasHeight, u + leftBorder, v + topBorder + fillerHeight, (i == xPasses ? remainderWidth : fillerWidth), bottomBorder, zLevel);
// Throw in some filler for good measure
for (int j = 0; j < yPasses + (remainderHeight > 0 ? 1 : 0); j++)
drawTexturedModalRect(x + leftBorder + (i * fillerWidth), y + topBorder + (j * fillerHeight), u + leftBorder, v + topBorder, (i == xPasses ? remainderWidth : fillerWidth), (j == yPasses ? remainderHeight : fillerHeight), zLevel);
}
// Side Borders
for (int j = 0; j < yPasses + (remainderHeight > 0 ? 1 : 0); j++)
{
// Left Border
drawTexturedModalRect(x, y + topBorder + (j * fillerHeight), u, v + topBorder, leftBorder, (j == yPasses ? remainderHeight : fillerHeight), zLevel);
// Right Border
drawTexturedModalRect(x + leftBorder + canvasWidth, y + topBorder + (j * fillerHeight), u + leftBorder + fillerWidth, v + topBorder, rightBorder, (j == yPasses ? remainderHeight : fillerHeight), zLevel);
}
}
public static void drawTexturedModalRect(int x, int y, int u, int v, int width, int height, float zLevel)
{
float var7 = 0.00390625F;
float var8 = 0.00390625F;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((x + 0), (y + height), zLevel, ((u + 0) * var7), ((v + height) * var8));
tessellator.addVertexWithUV((x + width), (y + height), zLevel, ((u + width) * var7), ((v + height) * var8));
tessellator.addVertexWithUV((x + width), (y + 0), zLevel, ((u + width) * var7), ((v + 0) * var8));
tessellator.addVertexWithUV((x + 0), (y + 0), zLevel, ((u + 0) * var7), ((v + 0) * var8));
tessellator.draw();
}
}

View File

@ -0,0 +1,96 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import net.minecraft.client.gui.GuiButton;
/**
* This class implements an easy way to check if the mouse has hovered within a certain region of the screen for a given
* period of time. The region can be defined manually or by supplying a GuiButton object.
*
* @author bspkrs
*/
public class HoverChecker
{
private int top, bottom, left, right, threshold;
private GuiButton button;
private long hoverStart;
public HoverChecker(int top, int bottom, int left, int right, int threshold)
{
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
this.threshold = threshold;
this.hoverStart = -1;
}
public HoverChecker(GuiButton button, int threshold)
{
this.button = button;
this.threshold = threshold;
}
/**
* Call this method if the intended region has changed such as if the region must follow a scrolling list.
* It is not necessary to call this method if a GuiButton defines the hover region.
*/
public void updateBounds(int top, int bottom, int left, int right)
{
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
}
/**
* Checks if the mouse is in the hover region. If the specified time period has elapsed the method returns true.
* The hover timer is reset if the mouse is not within the region.
*/
public boolean checkHover(int mouseX, int mouseY)
{
return checkHover(mouseX, mouseY, true);
}
/**
* Checks if the mouse is in the hover region. If the specified time period has elapsed the method returns true.
* The hover timer is reset if the mouse is not within the region.
*/
public boolean checkHover(int mouseX, int mouseY, boolean canHover)
{
if (this.button != null)
{
this.top = button.yPosition;
this.bottom = button.yPosition + button.height;
this.left = button.xPosition;
this.right = button.xPosition + button.width;
canHover = canHover && button.visible;
}
if (canHover && hoverStart == -1 && mouseY >= top && mouseY <= bottom && mouseX >= left && mouseX <= right)
hoverStart = System.currentTimeMillis();
else if (!canHover || mouseY < top || mouseY > bottom || mouseX < left || mouseX > right)
resetHoverTimer();
return canHover && hoverStart != -1 && System.currentTimeMillis() - hoverStart >= threshold;
}
/**
* Manually resets the hover timer.
*/
public void resetHoverTimer()
{
hoverStart = -1;
}
}

View File

@ -0,0 +1,170 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.config;
import java.util.List;
import java.util.regex.Pattern;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.config.GuiEditArrayEntries.IArrayEntry;
/**
* This interface provides the information needed by GuiConfig and GuiConfigEntries to display config elements for editing.
*
* @author bspkrs
*/
public interface IConfigElement<T>
{
/**
* [Property, Category] Is this object a property object?
*/
public boolean isProperty();
/**
* This method returns a class that implements {@code IConfigEntry} or null. This class MUST
* provide a constructor with the following parameter types: {@code GuiConfig}, {@code GuiConfigEntries}, {@code IConfigElement}
*/
public Class<? extends IConfigEntry> getConfigEntryClass();
/**
* This method returns a class that implements {@code IArrayEntry}. This class MUST provide a constructor with the
* following parameter types: {@code GuiEditArray}, {@code GuiEditArrayEntries}, {@code IConfigElement}, {@code Object}
*/
public Class<? extends IArrayEntry> getArrayEntryClass();
/**
* [Property, Category] Gets the name of this object.
*/
public String getName();
/**
* [Category] Gets the qualified name of this object. This is typically only used for category objects.
*/
public String getQualifiedName();
/**
* [Property, Category] Gets a language key for localization of config GUI entry names. If the same key is specified with .tooltip
* appended to the end, that key will return a localized tooltip when the mouse hovers over the property label/category button.
*/
public String getLanguageKey();
/**
* [Property, Category] Gets the comment for this object. Used for the tooltip if getLanguageKey() + ".tooltip" is not defined in the
* .lang file.
*/
public String getComment();
/**
* [Category] Gets this category's child categories/properties.
*/
public List<IConfigElement> getChildElements();
/**
* [Property, Category] Gets the ConfigGuiType value corresponding to the type of this property object, or CONFIG_CATEGORY if this is a
* category object.
*/
public ConfigGuiType getType();
/**
* [Property] Is this property object a list?
*/
public boolean isList();
/**
* [Property] Does this list property have to remain a fixed length?
*/
public boolean isListLengthFixed();
/**
* [Property] Gets the max length of this list property, or -1 if the length is unlimited.
*/
public int getMaxListLength();
/**
* [Property] Is this property value equal to the default value?
*/
public boolean isDefault();
/**
* [Property] Gets this property's default value. If this element is an array, this method should return a String
* representation of that array using Arrays.toString()
*/
public Object getDefault();
/**
* [Property] Gets this property's default values.
*/
public Object[] getDefaults();
/**
* [Property] Sets this property's value to the default value.
*/
public void setToDefault();
/**
* [Property, Category] Whether or not this element is safe to modify while a world is running. For Categories return false if ANY properties
* in the category are modifiable while a world is running, true if all are not.
*/
public boolean requiresWorldRestart();
/**
* [Property, Category] Whether or not this element should be allowed to show on config GUIs.
*/
public boolean showInGui();
/**
* [Property, Category] Whether or not this element requires Minecraft to be restarted when changed.
*/
public boolean requiresMcRestart();
/**
* [Property] Gets this property value.
*/
public Object get();
/**
* [Property] Gets this property value as a list. Generally you should be sure of whether the property is a list before calling this.
*/
public Object[] getList();
/**
* [Property] Sets this property's value.
*/
public void set(T value);
/**
* [Property] Sets this property's value to the specified array.
*/
public void set(T[] aVal);
/**
* [Property] Gets a String array of valid values for this property. This is generally used for String properties to allow the user to
* select a value from a list of valid values.
*/
public String[] getValidValues();
/**
* [Property] Gets this property's minimum value.
*/
public T getMinValue();
/**
* [Property] Gets this property's maximum value.
*/
public T getMaxValue();
/**
* [Property] Gets a Pattern object used in String property input validation.
*/
public Pattern getValidationPattern();
}

View File

@ -0,0 +1,85 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2014 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors (this class):
* bspkrs - implementation
*/
package cpw.mods.fml.client.event;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.common.eventhandler.Event.HasResult;
/**
* These events are posted from the GuiConfig screen when the done button is pressed. The events are only posted
* if the parent screen is not an instance of GuiConfig or if the configID field has been set for
* the GuiConfig screen.
*
* Listeners for this event should use OnConfigChanged or PostConfigChanged and check for a specific mod ID.
* For best results the listener should refresh any objects/fields that are set based on the mod's config
* and should serialize the modified config.
*
* @author bspkrs
*/
@HasResult
public class ConfigChangedEvent extends Event
{
/**
* The Mod ID of the mod whose configuration just changed.
*/
public final String modID;
/**
* Whether or not a world is currently running.
*/
public final boolean isWorldRunning;
/**
* Will be set to true if any elements were changed that require a restart of Minecraft.
*/
public final boolean requiresMcRestart;
/**
* A String identifier for this ConfigChangedEvent.
*/
public final String configID;
public ConfigChangedEvent(String modID, String configID, boolean isWorldRunning, boolean requiresMcRestart)
{
this.modID = modID;
this.configID = configID;
this.isWorldRunning = isWorldRunning;
this.requiresMcRestart = requiresMcRestart;
}
/**
* This event is intended to be consumed by the mod whose config has been changed. It fires when the Done button
* has been clicked on a GuiConfig screen and the following conditions are met:<br/>
* - at least one config element has been changed<br/>
* - one of these 2 conditions are met:<br/>
* 1) the parent screen is null or is not an instance of GuiConfig<br/>
* 2) the configID field has been set to a non-null value for the GuiConfig screen<br/><br/>
* Modders should check the modID field of the event to ensure they are only acting on their own config screen's event!
*/
public static class OnConfigChangedEvent extends ConfigChangedEvent
{
public OnConfigChangedEvent(String modID, String configID, boolean isWorldRunning, boolean requiresMcRestart)
{
super(modID, configID, isWorldRunning, requiresMcRestart);
}
}
/**
* This event is provided for mods to consume if they want to be able to check if other mods' configs have been changed.
* This event only fires if the OnConfigChangedEvent result is not DENY.
*/
public static class PostConfigChangedEvent extends ConfigChangedEvent
{
public PostConfigChangedEvent(String modID, String configID, boolean isWorldRunning, boolean requiresMcRestart)
{
super(modID, configID, isWorldRunning, requiresMcRestart);
}
}
}

View File

@ -0,0 +1,78 @@
fml.config.sample.basicDouble.tooltip=A double property with no defined bounds.
fml.config.sample.basicDouble=Unbounded Double
fml.config.sample.basicInteger.tooltip=An integer property with no defined bounds.
fml.config.sample.basicInteger=Unbounded Integer
fml.config.sample.basicString.tooltip=A basic string property. The user can enter anything in this textbox.
fml.config.sample.basicString=Basic String
fml.config.sample.booleanList.tooltip=A boolean list with no max length and can be lengthened or shortened.
fml.config.sample.booleanList=Basic Boolean List
fml.config.sample.booleanListFixed.tooltip=A boolean list that has a fixed length of 8.
fml.config.sample.booleanListFixed=Fixed Length Boolean List
fml.config.sample.booleanListMax.tooltip=A boolean list that has a max length of 10.
fml.config.sample.booleanListMax=Max Length Boolean List
fml.config.sample.boundedDouble.tooltip=A double property with defined bounds.
fml.config.sample.boundedDouble=Bounded Double
fml.config.sample.boundedInteger.tooltip=An integer property with defined bounds.
fml.config.sample.boundedInteger=Bounded Integer
fml.config.sample.chatColorPicker.tooltip=A special property that allows the user to select a font color code.
fml.config.sample.chatColorPicker=Chat Color Picker
fml.config.sample.ctgy.lists.tooltip=Provides a variety of array-property controls to play with.
fml.config.sample.ctgy.lists=Sample Array Controls
fml.config.sample.ctgy.numbers.tooltip=Provides a listing of the numeric controls for toying with.
fml.config.sample.ctgy.numbers=Sample Numeric Controls
fml.config.sample.ctgy.strings.tooltip=Provides a listing of the different String-type controls to play with.
fml.config.sample.ctgy.strings=Sample String Controls
fml.config.sample.cycleString.tooltip=A string property that has a defined list of valid values that can be cycled through.
fml.config.sample.cycleString=Cycle Value String
fml.config.sample.doubleList.tooltip=A double list with no max length and can be lengthened or shortened.
fml.config.sample.doubleList=Basic Double List
fml.config.sample.doubleListBounded.tooltip=A double list with specific value bounds.
fml.config.sample.doubleListBounded=Double List with Value Bounds
fml.config.sample.doubleListFixed.tooltip=A double list that has a fixed length of 10.
fml.config.sample.doubleListFixed=Fixed Length Double List
fml.config.sample.doubleListMax.tooltip=A double list that has a max length of 15.
fml.config.sample.doubleListMax=Max Length Double List
fml.config.sample.imABoolean.tooltip=Yep, that's pretty much it... I'm a Boolean control.
fml.config.sample.imABoolean=I'm a Boolean
fml.config.sample.imADouble.tooltip=There are two of me. Or maybe I work for both the CIA and the KGB. Not sure.
fml.config.sample.imADouble=I'm a Double
fml.config.sample.imAString.tooltip=Aah. Now, I understand you want us to advertise your washing powder. <*String.*> String, washing powder, what's the difference? We can sell anything. <*Good. Well I have this large quantity of string, 122,000 miles of it to be exact, which I inherited, and I thought if I advertised it...*> Of course! A national campaign. Useful stuff, string, no trouble there. <*Ah, but there's a snag, you see. Due to bad planning, the 122,000 miles is in three inch lengths. So it's not very useful.*> Well, that's our selling point! SIMPSON'S INDIVIDUAL STRINGETTES! THE NOW STRING! READY CUT, EASY TO HANDLE, SIMPSON'S INDIVIDUAL EMPEROR STRINGETTES - JUST THE RIGHT LENGTH!
fml.config.sample.imAString=I'm a String
fml.config.sample.imAnInteger.tooltip=Did I say that I'm an Integer? Oh, I see.
fml.config.sample.imAnInteger=I'm an Integer
fml.config.sample.integerList.tooltip=An integer list with no max length and can be lengthened or shortened.
fml.config.sample.integerList=Basic Integer List
fml.config.sample.integerListBounded.tooltip=An integer list with specific value bounds.
fml.config.sample.integerListBounded=Integer List with Value Bounds
fml.config.sample.integerListFixed.tooltip=An integer list that has a fixed length of 10.
fml.config.sample.integerListFixed=Fixed Length Integer List
fml.config.sample.integerListMax.tooltip=An integer list that has a max length of 15.
fml.config.sample.integerListMax=Max Length Integer List
fml.config.sample.modIDSelector.tooltip=A special property that allows the user to select a mod ID from a list of all installed mods. There are many possibilities for how this could be used with a little custom code: selecting biomes, selecting entities, selecting items, selecting blocks, etc.
fml.config.sample.modIDSelector=Mod ID Selector
fml.config.sample.patternString.tooltip=A string property that is validated using a Pattern object.
fml.config.sample.patternString=Pattern Validated String
fml.config.sample.stringList.tooltip=A basic string list with no validation.
fml.config.sample.stringList=Basic String List
fml.config.sample.stringListFixed.tooltip=A string list that has a fixed length of 7.
fml.config.sample.stringListFixed=Fixed Length String List
fml.config.sample.stringListMax.tooltip=A string list that has a max length of 15.
fml.config.sample.stringListMax=Max Length String List
fml.config.sample.stringListPattern.tooltip=A string list that validates each value using a Pattern object.
fml.config.sample.stringListPattern=Pattern Validated String List
fml.config.sample.title=This is for playing with the Config GUI behavior. Changes are not saved.
fml.configgui.applyGlobally=Apply globally
fml.configgui.confirmRestartMessage=I Understand
fml.configgui.gameRestartRequired=One or more changed settings requires that Minecraft be restarted before taking effect.
fml.configgui.gameRestartTitle=Minecraft Restart Required
fml.configgui.sampletext=Sample Text
fml.configgui.tooltip.addNewEntryAbove=Add New Entry Above
fml.configgui.tooltip.applyGlobally=Apply Undo Changes or Reset to Default globally.
fml.configgui.tooltip.removeEntry=Remove Entry
fml.configgui.tooltip.resetAll=Reset All to Default. If the Apply globally checkbox is checked values on child screens will also be reset.
fml.configgui.tooltip.resetToDefault=Reset to Default
fml.configgui.tooltip.undoAll=Undo All Changes. If the Apply globally checkbox is checked changes to child screens will also be undone.
fml.configgui.tooltip.undoChanges=Undo Changes
fml.configgui.tooltip.default=[default: %s]
fml.configgui.tooltip.defaultNumeric=[range: %s ~ %s, default: %s]

View File

@ -85,3 +85,21 @@ protected net.minecraft.util.ObjectIntIdentityMap field_148749_a # internal map
protected net.minecraft.util.ObjectIntIdentityMap field_148748_b # internal index list
protected-f net.minecraft.util.RegistryNamespaced field_148759_a # identitymap
protected net.minecraft.util.RegistryNamespaced func_148755_c(Ljava/lang/String;)Ljava/lang/String; # prefix if necessary
# GuiButton
public net.minecraft.client.gui.GuiButton field_146120_f # width - needed for config GUI stuff
public net.minecraft.client.gui.GuiButton field_146121_g # height - needed for config GUI stuff
# GuiTextField
public-f net.minecraft.client.gui.GuiTextField field_146209_f # xPosition - needed for config GUI stuff
public-f net.minecraft.client.gui.GuiTextField field_146210_g # yPosition - needed for config GUI stuff
public-f net.minecraft.client.gui.GuiTextField field_146218_h # width - needed for config GUI stuff
public-f net.minecraft.client.gui.GuiTextField field_146219_i # height - needed for config GUI stuff
# GuiSlot
public net.minecraft.client.gui.GuiSlot field_148149_f # slotHeight - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148151_d # right - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148152_e # left - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148153_b # top - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148154_c # bottom - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148155_a # width - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148158_l # height - needed for config GUI stuff
public net.minecraft.client.gui.GuiSlot field_148160_j # headerPadding - needed for config GUI stuff