Add modern implementation of the Slider widget and deprecate the old one (#8496)

This commit is contained in:
Robert Kämpf authored and GitHub committed 2022-04-13 19:59:38 +02:00
1 parent eed24f017f
commit f0b90dc35d
2 files changed
+225

No files matched your search

@@ -0,0 +1,220 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.gui.widget;
import net.minecraft.client.gui.components.AbstractSliderButton;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Mth;
import org.lwjgl.glfw.GLFW;
import java.text.DecimalFormat;
/**
* Slider widget implementation which allows inputting values in a certain range with optional step size.
*/
public class ForgeSlider extends AbstractSliderButton
{
protected Component prefix;
protected Component suffix;
protected double minValue;
protected double maxValue;
/** Allows input of discontinuous values with a certain step */
protected double stepSize;
protected boolean drawString;
private final DecimalFormat format;
/**
* @param x x position of upper left corner
* @param y y position of upper left corner
* @param width Width of the widget
* @param height Height of the widget
* @param prefix {@link Component} displayed before the value string
* @param suffix {@link Component} displayed after the value string
* @param minValue Minimum (left) value of slider
* @param maxValue Maximum (right) value of slider
* @param currentValue Starting value when widget is first displayed
* @param stepSize Size of step used. Precision will automatically be calculated based on this value if this value is not 0.
* @param precision Only used when {@code stepSize} is 0. Limited to a maximum of 4 (inclusive).
* @param drawString Should text be displayed on the widget
*/
public ForgeSlider(int x, int y, int width, int height, Component prefix, Component suffix, double minValue, double maxValue, double currentValue, double stepSize, int precision, boolean drawString)
{
super(x, y, width, height, TextComponent.EMPTY, 0D);
this.prefix = prefix;
this.suffix = suffix;
this.minValue = minValue;
this.maxValue = maxValue;
this.stepSize = Math.abs(stepSize);
this.value = this.snapToNearest((currentValue - minValue) / (maxValue - minValue));
this.drawString = drawString;
if (stepSize == 0D)
{
precision = Math.min(precision, 4);
StringBuilder builder = new StringBuilder("0");
if (precision > 0)
builder.append('.');
while (precision-- > 0)
builder.append('0');
this.format = new DecimalFormat(builder.toString());
}
else if (Mth.equal(this.stepSize, Math.floor(this.stepSize)))
{
this.format = new DecimalFormat("0");
}
else
{
this.format = new DecimalFormat(Double.toString(this.stepSize).replaceAll("\\d", "0"));
}
this.updateMessage();
}
/**
* Overload with {@code stepSize} set to 1, useful for sliders with whole number values.
*/
public ForgeSlider(int x, int y, int width, int height, Component prefix, Component suffix, double minValue, double maxValue, double currentValue, boolean drawString)
{
this(x, y, width, height, prefix, suffix, minValue, maxValue, currentValue, 1D, 0, drawString);
}
/**
* @return Current slider value as a double
*/
public double getValue()
{
return this.value * (maxValue - minValue) + minValue;
}
/**
* @return Current slider value as an long
*/
public long getValueLong()
{
return Math.round(this.getValue());
}
/**
* @return Current slider value as an int
*/
public int getValueInt()
{
return (int) this.getValueLong();
}
/**
* @param value The new slider value
*/
public void setValue(double value)
{
this.value = this.snapToNearest((value - this.minValue) / (this.maxValue - this.minValue));
this.updateMessage();
}
public String getValueString()
{
return this.format.format(this.getValue());
}
@Override
public void onClick(double mouseX, double mouseY)
{
this.setValueFromMouse(mouseX);
}
@Override
protected void onDrag(double mouseX, double mouseY, double dragX, double dragY)
{
super.onDrag(mouseX, mouseY, dragX, dragY);
this.setValueFromMouse(mouseX);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers)
{
boolean flag = keyCode == GLFW.GLFW_KEY_LEFT;
if (flag || keyCode == GLFW.GLFW_KEY_RIGHT)
{
if (this.minValue > this.maxValue)
flag = !flag;
float f = flag ? -1F : 1F;
if (stepSize <= 0D)
this.setSliderValue(this.value + (f / (this.width - 8)));
else
this.setValue(this.getValue() + f * this.stepSize);
}
return false;
}
private void setValueFromMouse(double mouseX)
{
this.setSliderValue((mouseX - (this.x + 4)) / (this.width - 8));
}
/**
* @param value Percentage of slider range
*/
private void setSliderValue(double value)
{
double oldValue = this.value;
this.value = this.snapToNearest(value);
if (!Mth.equal(oldValue, this.value))
this.applyValue();
this.updateMessage();
}
/**
* Snaps the value, so that the displayed value is the nearest multiple of {@code stepSize}.
* If {@code stepSize} is 0, no snapping occurs.
*/
private double snapToNearest(double value)
{
if(stepSize <= 0D)
return Mth.clamp(value, 0D, 1D);
value = Mth.lerp(Mth.clamp(value, 0D, 1D), this.minValue, this.maxValue);
value = (stepSize * Math.round(value / stepSize));
if (this.minValue > this.maxValue)
{
value = Mth.clamp(value, this.maxValue, this.minValue);
}
else
{
value = Mth.clamp(value, this.minValue, this.maxValue);
}
return Mth.map(value, this.minValue, this.maxValue, 0D, 1D);
}
@Override
protected void updateMessage()
{
if (this.drawString)
{
this.setMessage(new TextComponent("").append(prefix).append(this.getValueString()).append(suffix));
}
else
{
this.setMessage(TextComponent.EMPTY);
}
}
@Override
protected void applyValue() {}
}
@@ -16,8 +16,13 @@ import javax.annotation.Nullable;
/**
* This class is blatantly stolen from iChunUtils with permission.
*
* @deprecated This class has a few issues,
* mainly <a href="https://github.com/MinecraftForge/MinecraftForge/issues/8485">MinecraftForge/MinecraftForge#8485</a>.
* Use {@link ForgeSlider} instead.
*
* @author iChun
*/
@Deprecated(since = "1.18.2", forRemoval = true)
public class Slider extends ExtendedButton
{
/** The value of this slider control. */