From 7fae3e49688048e294d20d95da90329ffd581d45 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 9 Jun 2021 13:52:52 +0200 Subject: [PATCH] Promp - Changed the layout of save/discard/leave prompts - Leaving with unsaved changes now gives you the option to save - Config tooltips now use standard Create tooltip splitting --- .../config/ui/SubMenuConfigScreen.java | 78 ++++++++++--------- .../config/ui/entries/ValueEntry.java | 12 ++- .../foundation/gui/ConfirmationScreen.java | 60 ++++++++++---- 3 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java index 66dc6afaf..892b57ef9 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java @@ -4,6 +4,7 @@ import java.awt.Color; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -25,6 +26,7 @@ import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.ConfirmationScreen.Response; import com.simibubi.create.foundation.gui.widgets.BoxWidget; import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.networking.AllPackets; @@ -161,8 +163,8 @@ public class SubMenuConfigScreen extends ConfigScreen { .withPadding(2, 2) .withCallback((x, y) -> new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?")) + .centered() + .withText(ITextProperties.plain("Resetting all settings of the " + type.toString() + " config. Are you sure?")) .withAction(success -> { if (success) resetConfig(spec.getValues()); @@ -172,7 +174,7 @@ public class SubMenuConfigScreen extends ConfigScreen { resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll))); resetAll.getToolTip().add(new StringTextComponent("Reset All")); - resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all configs to their default value.", TextFormatting.GRAY, TextFormatting.GRAY)); + resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all settings to their default value.", TextFormatting.GRAY, TextFormatting.GRAY)); saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20) .withPadding(2, 2) @@ -181,8 +183,8 @@ public class SubMenuConfigScreen extends ConfigScreen { return; new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to change " + changes.size() + " value" + (changes.size() != 1 ? "s" : "") + ". Are you sure?")) + .centered() + .withText(ITextProperties.plain("Saving " + changes.size() + " changed value" + (changes.size() != 1 ? "s" : "") + "")) .withAction(success -> { if (success) saveChanges(); @@ -200,8 +202,8 @@ public class SubMenuConfigScreen extends ConfigScreen { return; new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + ". Are you sure?")) + .centered() + .withText(ITextProperties.plain("Discarding " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + "")) .withAction(success -> { if (success) clearChanges(); @@ -282,7 +284,7 @@ public class SubMenuConfigScreen extends ConfigScreen { stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red)); serverLocked.withBorderColors(red); serverLocked.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You don't have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY)); + serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY)); } else { stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0)); stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green)); @@ -338,24 +340,23 @@ public class SubMenuConfigScreen extends ConfigScreen { } private void attemptBackstep() { - if (!changes.isEmpty() && parent instanceof BaseConfigScreen) { - new ConfirmationScreen() - .centered() - .addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config.")) - .addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?")) - .withAction(success -> { - if (!success) - return; - - changes.clear(); - ScreenOpener.open(parent); - }) - .open(this); - } else { + if (changes.isEmpty() || !(parent instanceof BaseConfigScreen)) { ScreenOpener.open(parent); + return; } + + Consumer action = success -> { + if (success == Response.Cancel) + return; + if (success == Response.Confirm) + saveChanges(); + changes.clear(); + ScreenOpener.open(parent); + }; + + showLeavingPrompt(action); } - + @Override public void onClose() { if (changes.isEmpty()) { @@ -364,17 +365,24 @@ public class SubMenuConfigScreen extends ConfigScreen { return; } - new ConfirmationScreen() - .centered() - .addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config.")) - .addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?")) - .withAction(success -> { - if (!success) - return; - - changes.clear(); - super.onClose(); - }) - .open(this); + Consumer action = success -> { + if (success == Response.Cancel) + return; + if (success == Response.Confirm) + saveChanges(); + changes.clear(); + super.onClose(); + }; + + showLeavingPrompt(action); } + + public void showLeavingPrompt(Consumer action) { + new ConfirmationScreen().centered() + .addText(ITextProperties.plain("Leaving with " + changes.size() + " unsaved change" + + (changes.size() != 1 ? "s" : "") + " for this config")) + .withThreeActions(action) + .open(this); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java index 48d1d86a0..18cc5f30c 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java @@ -17,6 +17,7 @@ import com.simibubi.create.foundation.config.ui.ConfigScreenList; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.widgets.BoxWidget; +import com.simibubi.create.foundation.item.TooltipHelper; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.StringTextComponent; @@ -52,7 +53,7 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { listeners.add(resetButton); List path = value.getPath(); - labelTooltip.add(new StringTextComponent(path.get(path.size()-1)).formatted(TextFormatting.GRAY)); + labelTooltip.add(new StringTextComponent(label).formatted(TextFormatting.WHITE)); String comment = spec.getComment(); if (comment == null || comment.isEmpty()) return; @@ -76,8 +77,13 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { u = "in SU"; unit = u; } - //add comment to tooltip - labelTooltip.addAll(Arrays.stream(commentLines).map(StringTextComponent::new).collect(Collectors.toList())); + // add comment to tooltip + labelTooltip.addAll(Arrays.stream(commentLines) + .map(StringTextComponent::new) + .flatMap(stc -> TooltipHelper.cutTextComponent(stc, TextFormatting.GRAY, TextFormatting.GRAY) + .stream()) + .collect(Collectors.toList())); + labelTooltip.add(new StringTextComponent(ConfigScreen.modID + ":" + path.get(path.size()-1)).formatted(TextFormatting.DARK_GRAY)); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java index b0cfe2ffa..bda1fa9ff 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java @@ -12,6 +12,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.widgets.BoxWidget; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.shader.Framebuffer; import net.minecraft.util.text.ITextProperties; @@ -20,17 +21,23 @@ import net.minecraft.util.text.Style; public class ConfirmationScreen extends AbstractSimiScreen { private Screen source; - private Consumer action = _success -> {}; + private Consumer action = _success -> {}; private List text = new ArrayList<>(); private boolean centered = false; private int x; private int y; private int textWidth; private int textHeight; + private boolean tristate; private BoxWidget confirm; + private BoxWidget confirmDontSave; private BoxWidget cancel; private BoxElement textBackground; + + public enum Response { + Confirm, ConfirmDontSave, Cancel + } /* * Removes text lines from the back of the list @@ -70,7 +77,13 @@ public class ConfirmationScreen extends AbstractSimiScreen { } public ConfirmationScreen withAction(Consumer action) { + this.action = r -> action.accept(r == Response.Confirm); + return this; + } + + public ConfirmationScreen withThreeActions(Consumer action) { this.action = action; + this.tristate = true; return this; } @@ -115,32 +128,46 @@ public class ConfirmationScreen extends AbstractSimiScreen { y = height - textHeight - 30; } - TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true); - confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20) - .withCallback(() -> accept(true)); + int buttonX = x + textWidth / 2 - 6 - (int) (70 * (tristate ? 1.5f : 1)); + + TextStencilElement confirmText = + new TextStencilElement(client.fontRenderer, tristate ? "Save" : "Confirm").centered(true, true); + confirm = new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.Confirm)); confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm))); + widgets.add(confirm); + + buttonX += 12 + 70; + + if (tristate) { + TextStencilElement confirmDontSaveText = + new TextStencilElement(client.fontRenderer, "Don't Save").centered(true, true); + confirmDontSave = + new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.ConfirmDontSave)); + confirmDontSave.showingElement( + confirmDontSaveText.withElementRenderer(BoxWidget.gradientFactory.apply(confirmDontSave))); + widgets.add(confirmDontSave); + buttonX += 12 + 70; + } TextStencilElement cancelText = new TextStencilElement(client.fontRenderer, "Cancel").centered(true, true); - cancel = new BoxWidget(x + textWidth/2 + 6, y + textHeight + 2, textWidth/2 - 10, 20) - .withCallback(() -> accept(false)); + cancel = new BoxWidget(buttonX, y + textHeight + 6, 70, 16) + .withCallback(() -> accept(Response.Cancel)); cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel))); - - widgets.add(confirm); widgets.add(cancel); textBackground = new BoxElement() .gradientBorder(Theme.p(Theme.Key.BUTTON_DISABLE)) - .withBounds(textWidth, textHeight) - .at(x, y); + .withBounds(width + 10, textHeight + 35) + .at(-5, y - 5); } @Override public void onClose() { - accept(false); + accept(Response.Cancel); } - private void accept(boolean success) { + private void accept(Response success) { client.currentScreen = source; action.accept(success); } @@ -157,11 +184,12 @@ public class ConfirmationScreen extends AbstractSimiScreen { for (ITextProperties line : text) { lineY = lineY + offset; - if (line == null) continue; - - client.fontRenderer.draw(ms, line.getString(), x, lineY, 0xeaeaea); + int textX = x; + if (text.size() == 1) + x = (width - client.fontRenderer.getWidth(line)) / 2; + client.fontRenderer.draw(ms, line.getString(), textX, lineY, 0xeaeaea); } ms.pop(); @@ -175,7 +203,7 @@ public class ConfirmationScreen extends AbstractSimiScreen { ms.push(); UIRenderHelper.framebuffer.bindFramebuffer(true); - source.render(ms, mouseX, mouseY, 10); + source.render(ms, 0, 0, 10); // zero mouse coords to prevent further tooltips UIRenderHelper.framebuffer.unbindFramebuffer(); Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); ms.pop();