Started refactoring number entry dialogs to use shared code.

This commit is contained in:
Sebastian Hartte
2020-07-19 20:04:08 +02:00
parent d5f113eb35
commit 6187e6a7bb
7 changed files with 200 additions and 134 deletions
@@ -69,7 +69,7 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
subGui.addBackButton(this::addButton, 154, 0); subGui.addBackButton(this::addButton, 154, 0);
this.amountToCraft = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT, this.amountToCraft = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT,
Integer.class); Integer.class, value -> {});
this.amountToCraft.setEnableBackgroundDrawing(false); this.amountToCraft.setEnableBackgroundDrawing(false);
this.amountToCraft.setMaxStringLength(16); this.amountToCraft.setMaxStringLength(16);
this.amountToCraft.setTextColor(0xFFFFFF); this.amountToCraft.setTextColor(0xFFFFFF);
@@ -80,7 +80,7 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
private void confirm(Button button) { private void confirm(Button button) {
NetworkHandler.instance() NetworkHandler.instance()
.sendToServer(new CraftRequestPacket(Integer.parseInt(this.amountToCraft.getText()), hasShiftDown())); .sendToServer(new CraftRequestPacket((int) this.amountToCraft.getValue(), hasShiftDown()));
} }
@Override @Override
@@ -18,8 +18,6 @@
package appeng.client.gui.implementations; package appeng.client.gui.implementations;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
@@ -29,28 +27,16 @@ import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.Upgrades; import appeng.api.config.Upgrades;
import appeng.api.config.YesNo; import appeng.api.config.YesNo;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.widgets.ServerSettingToggleButton; import appeng.client.gui.widgets.ServerSettingToggleButton;
import appeng.client.gui.widgets.SettingToggleButton; import appeng.client.gui.widgets.SettingToggleButton;
import appeng.container.implementations.LevelEmitterContainer; import appeng.container.implementations.LevelEmitterContainer;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText; import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket; import appeng.core.sync.packets.ConfigValuePacket;
public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer> { public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer> {
private NumberBox level; private NumberEntryWidget level;
private Button plus1;
private Button plus10;
private Button plus100;
private Button plus1000;
private Button minus1;
private Button minus10;
private Button minus100;
private Button minus1000;
private SettingToggleButton<LevelType> levelMode; private SettingToggleButton<LevelType> levelMode;
private SettingToggleButton<YesNo> craftingMode; private SettingToggleButton<YesNo> craftingMode;
@@ -62,16 +48,15 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
public void init() { public void init() {
super.init(); super.init();
this.level = new NumberBox(this.font, this.guiLeft + 24, this.guiTop + 43, 79, this.font.FONT_HEIGHT, this.level = new NumberEntryWidget(this, 20, 17, 79, this::onLevelChange);
Long.class); this.level.addButtons(children::add, this::addButton);
this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF);
this.level.setVisible(true);
this.level.setFocused2(true);
container.setTextField(this.level); container.setTextField(this.level);
} }
private void onLevelChange(long level) {
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", String.valueOf(level)));
}
@Override @Override
protected void addButtons() { protected void addButtons() {
this.levelMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 8, Settings.LEVEL_TYPE, this.levelMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 8, Settings.LEVEL_TYPE,
@@ -82,29 +67,6 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
FuzzyMode.IGNORE_ALL); FuzzyMode.IGNORE_ALL);
this.craftingMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 48, this.craftingMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 48,
Settings.CRAFT_VIA_REDSTONE, YesNo.NO); Settings.CRAFT_VIA_REDSTONE, YesNo.NO);
final int a = AEConfig.instance().levelByStackAmounts(0);
final int b = AEConfig.instance().levelByStackAmounts(1);
final int c = AEConfig.instance().levelByStackAmounts(2);
final int d = AEConfig.instance().levelByStackAmounts(3);
this.addButton(this.plus1 = new Button(this.guiLeft + 20, this.guiTop + 17, 22, 20, "+" + a, btn -> addQty(a)));
this.addButton(
this.plus10 = new Button(this.guiLeft + 48, this.guiTop + 17, 28, 20, "+" + b, btn -> addQty(b)));
this.addButton(
this.plus100 = new Button(this.guiLeft + 82, this.guiTop + 17, 32, 20, "+" + c, btn -> addQty(c)));
this.addButton(
this.plus1000 = new Button(this.guiLeft + 120, this.guiTop + 17, 38, 20, "+" + d, btn -> addQty(d)));
this.addButton(
this.minus1 = new Button(this.guiLeft + 20, this.guiTop + 59, 22, 20, "-" + a, btn -> addQty(-a)));
this.addButton(
this.minus10 = new Button(this.guiLeft + 48, this.guiTop + 59, 28, 20, "-" + b, btn -> addQty(-b)));
this.addButton(
this.minus100 = new Button(this.guiLeft + 82, this.guiTop + 59, 32, 20, "-" + c, btn -> addQty(-c)));
this.addButton(
this.minus1000 = new Button(this.guiLeft + 120, this.guiTop + 59, 38, 20, "-" + d, btn -> addQty(-d)));
this.addButton(this.levelMode); this.addButton(this.levelMode);
this.addButton(this.redstoneMode); this.addButton(this.redstoneMode);
this.addButton(this.craftingMode); this.addButton(this.craftingMode);
@@ -115,15 +77,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
final boolean notCraftingMode = this.bc.getInstalledUpgrades(Upgrades.CRAFTING) == 0; final boolean notCraftingMode = this.bc.getInstalledUpgrades(Upgrades.CRAFTING) == 0;
// configure enabled status... // configure enabled status...
this.level.setEnabled(notCraftingMode); this.level.setActive(notCraftingMode);
this.plus1.active = notCraftingMode;
this.plus10.active = notCraftingMode;
this.plus100.active = notCraftingMode;
this.plus1000.active = notCraftingMode;
this.minus1.active = notCraftingMode;
this.minus10.active = notCraftingMode;
this.minus100.active = notCraftingMode;
this.minus1000.active = notCraftingMode;
this.levelMode.active = notCraftingMode; this.levelMode.active = notCraftingMode;
this.redstoneMode.active = notCraftingMode; this.redstoneMode.active = notCraftingMode;
@@ -160,70 +114,14 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
return GuiText.LevelEmitter; return GuiText.LevelEmitter;
} }
private void addQty(final long i) {
try {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
long result = Long.parseLong(Out);
result += i;
if (result < 0) {
result = 0;
}
this.level.setText(Out = Long.toString(result));
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", Out));
} catch (final NumberFormatException e) {
// nope..
this.level.setText("0");
}
}
@Override @Override
public boolean charTyped(char character, int key) { public boolean charTyped(char character, int key) {
// Forward entered characters to the number-text-field return super.charTyped(character, key);
return level.charTyped(character, key);
} }
@Override public void tick() {
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) { super.tick();
if (!this.checkHotbarKeys(InputMappings.getInputByCode(keyCode, scanCode))) { this.level.tick();
if (keyCode == 211 || keyCode == 205 || keyCode == 203 || keyCode == 14) {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", Out));
return true;
}
}
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
} }
} }
@@ -0,0 +1,111 @@
package appeng.client.gui.implementations;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.NumberBox;
import appeng.core.AEConfig;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.widget.button.Button;
import java.util.function.Consumer;
import java.util.function.LongConsumer;
/**
* A utility widget that consists of a text-field to enter a number with attached buttons to
* increment/decrement the number in fixed intervals.
*/
public class NumberEntryWidget {
private final AEBaseScreen<?> parent;
private final int x;
private final int y;
private final NumberBox level;
private Button plus1;
private Button plus10;
private Button plus100;
private Button plus1000;
private Button minus1;
private Button minus10;
private Button minus100;
private Button minus1000;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, LongConsumer changeListener) {
this.parent = parent;
this.x = x;
this.y = y;
FontRenderer font = parent.getMinecraft().fontRenderer;
this.level = new NumberBox(font, parent.getGuiLeft() + x + 5, parent.getGuiTop() + y + 27, width, font.FONT_HEIGHT,
Long.class, changeListener);
this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF);
this.level.setVisible(true);
this.level.setFocused2(true);
parent.setFocusedDefault(this.level);
}
public void setActive(boolean active) {
this.level.setEnabled(active);
this.plus1.active = active;
this.plus10.active = active;
this.plus100.active = active;
this.plus1000.active = active;
this.minus1.active = active;
this.minus10.active = active;
this.minus100.active = active;
this.minus1000.active = active;
}
public void addButtons(Consumer<IGuiEventListener> addChildren, Consumer<Button> addButton) {
final int a = AEConfig.instance().levelByStackAmounts(0);
final int b = AEConfig.instance().levelByStackAmounts(1);
final int c = AEConfig.instance().levelByStackAmounts(2);
final int d = AEConfig.instance().levelByStackAmounts(3);
int left = parent.getGuiLeft() + x;
int top = parent.getGuiTop() + y;
addButton.accept(this.plus1 = new Button(left, top, 22, 20, "+" + a, btn -> addQty(a)));
addButton.accept(
this.plus10 = new Button(left + 28, top, 28, 20, "+" + b, btn -> addQty(b)));
addButton.accept(
this.plus100 = new Button(left + 62, top, 32, 20, "+" + c, btn -> addQty(c)));
addButton.accept(
this.plus1000 = new Button(left + 100, top, 38, 20, "+" + d, btn -> addQty(d)));
// Placing this here will give a sensible tab order
addChildren.accept(this.level);
addButton.accept(
this.minus1 = new Button(left, top + 42, 22, 20, "-" + a, btn -> addQty(-a)));
addButton.accept(
this.minus10 = new Button(left + 28, top + 42, 28, 20, "-" + b, btn -> addQty(-b)));
addButton.accept(
this.minus100 = new Button(left + 62, top + 42, 32, 20, "-" + c, btn -> addQty(-c)));
addButton.accept(
this.minus1000 = new Button(left + 100, top + 42, 38, 20, "-" + d, btn -> addQty(-d)));
}
private void addQty(final long i) {
long currentValue = this.level.getValue();
this.level.setText(String.valueOf(Math.max(0, currentValue + i)));
}
public void render(int mouseX, int mouseY, float partialTicks) {
this.level.render(mouseX, mouseY, partialTicks);
}
public void setValue(long value) {
// This check avoid changing the cursor position needlessly
if (value != this.level.getValue()) {
this.level.setText(String.valueOf(value));
}
}
public void tick() {
this.level.tick();
}
}
@@ -64,7 +64,7 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
this.subGui.addBackButton(this::addButton, 154, 0); this.subGui.addBackButton(this::addButton, 154, 0);
this.priority = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT, this.priority = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT,
Long.class); Long.class, value -> NetworkHandler.instance().sendToServer(new ConfigValuePacket("PriorityHost.Priority", String.valueOf(value))));
this.priority.setEnableBackgroundDrawing(false); this.priority.setEnableBackgroundDrawing(false);
this.priority.setMaxStringLength(16); this.priority.setMaxStringLength(16);
this.priority.setTextColor(0xFFFFFF); this.priority.setTextColor(0xFFFFFF);
@@ -21,32 +21,89 @@ package appeng.client.gui.widgets;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.gui.widget.TextFieldWidget;
// FIXME: Fix this piece of crap (i.e. onChange listener) import java.util.function.LongConsumer;
import java.util.regex.Pattern;
public class NumberBox extends TextFieldWidget { public class NumberBox extends TextFieldWidget {
private final Class type; private final Class<?> type;
private final LongConsumer changeListener;
private long lastValue;
public NumberBox(final FontRenderer fontRenderer, final int x, final int y, final int width, final int height, public NumberBox(final FontRenderer fontRenderer, final int x, final int y, final int width, final int height,
final Class type) { final Class<?> type, LongConsumer changeListener) {
super(fontRenderer, x, y, width, height, "0"); super(fontRenderer, x, y, width, height, "0");
this.type = type; this.type = type;
this.setText("0");
setResponder(this::onTextChanged);
this.lastValue = 0;
this.changeListener = changeListener;
} }
@Override private void onTextChanged(String text) {
public void writeText(final String selectedText) { if (text.isEmpty() || !isValidNumber()) {
final String original = this.getText(); setText("0"); // Will call onTextChanged recursively
super.writeText(selectedText); return;
}
StringBuilder sanitized = new StringBuilder(text);
boolean encounteredNonZero = false;
for (int i = 0; i < sanitized.length(); i++) {
char ch = sanitized.charAt(i);
if (ch >= '1' && ch <= '9') {
encounteredNonZero = true;
continue;
}
if (ch != '0' || !encounteredNonZero) {
sanitized.deleteCharAt(i--);
}
}
if (sanitized.length() == 0) {
sanitized.append('0');
}
String sanitizedStr = sanitized.toString();
if (!sanitizedStr.equals(text)) {
setText(sanitizedStr); // Will call onTextChanged recursively
return;
}
reportChange();
}
private void reportChange() {
long value = getValue();
if (value != lastValue) {
lastValue = value;
changeListener.accept(value);
}
}
private boolean isValidNumber() {
try { try {
if (this.type == int.class || this.type == Integer.class) { if (this.type == int.class || this.type == Integer.class) {
Integer.parseInt(this.getText()); Integer.parseInt(this.getText());
} else if (this.type == long.class || this.type == Long.class) { } else if (this.type == long.class || this.type == Long.class) {
Long.parseLong(this.getText()); Long.parseLong(this.getText());
} else if (this.type == double.class || this.type == Double.class) {
Double.parseDouble(this.getText());
} }
return true;
} catch (final NumberFormatException e) { } catch (final NumberFormatException e) {
this.setText(original); return false;
} }
} }
public long getValue() {
return Long.parseLong(getText());
}
@Override
public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_) {
if (super.keyPressed(p_keyPressed_1_, p_keyPressed_2_, p_keyPressed_3_)) {
return true;
}
// Swallow key presses for numbers because they would otherwise trigger the hotbar swapping unintentionally
return isFocused() && p_keyPressed_1_ >= '0' && p_keyPressed_1_ <= '9';
}
} }
@@ -18,7 +18,7 @@
package appeng.container.implementations; package appeng.container.implementations;
import net.minecraft.client.gui.widget.TextFieldWidget; import appeng.client.gui.implementations.NumberEntryWidget;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.ContainerType;
@@ -58,7 +58,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
private final LevelEmitterPart lvlEmitter; private final LevelEmitterPart lvlEmitter;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private TextFieldWidget textField; private NumberEntryWidget textField;
@GuiSync(2) @GuiSync(2)
public LevelType lvType; public LevelType lvType;
@GuiSync(3) @GuiSync(3)
@@ -72,9 +72,9 @@ public class LevelEmitterContainer extends UpgradeableContainer {
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void setTextField(final TextFieldWidget level) { public void setTextField(final NumberEntryWidget level) {
this.textField = level; this.textField = level;
this.textField.setText(String.valueOf(this.EmitterValue)); this.textField.setValue(this.EmitterValue);
} }
public void setLevel(final long l, final PlayerEntity player) { public void setLevel(final long l, final PlayerEntity player) {
@@ -140,7 +140,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
public void onUpdate(final String field, final Object oldValue, final Object newValue) { public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("EmitterValue")) { if (field.equals("EmitterValue")) {
if (this.textField != null) { if (this.textField != null) {
this.textField.setText(String.valueOf(this.EmitterValue)); this.textField.setValue(this.EmitterValue);
} }
} }
} }
@@ -31,7 +31,7 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
super.init(); super.init();
this.level = new NumberBox(this.font, this.guiLeft + 24, this.guiTop + 43, 79, this.font.FONT_HEIGHT, this.level = new NumberBox(this.font, this.guiLeft + 24, this.guiTop + 43, 79, this.font.FONT_HEIGHT,
Long.class); Long.class, value -> NetworkHandler.instance().sendToServer(new ConfigValuePacket("FluidLevelEmitter.Value", String.valueOf(value))));
this.level.setEnableBackgroundDrawing(false); this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16); this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF); this.level.setTextColor(0xFFFFFF);