Browse Source

ColorEntry

Signed-off-by: shedaniel <daniel@shedaniel.me>
shedaniel 5 years ago
parent
commit
8577ab28fc

+ 2 - 2
build.gradle

@@ -133,7 +133,7 @@ curseforge {
     if (apiKey != null)
         project {
             id = '319057'
-            releaseType = 'release'
+            releaseType = 'beta'
             addGameVersion '1.16-Snapshot'
             addGameVersion 'Fabric'
             addGameVersion 'Java 8'
@@ -141,7 +141,7 @@ curseforge {
                 requiredDependency 'fabric-api'
             }
             mainArtifact(file("${project.buildDir}/libs/${project.archivesBaseName}-${project.version}.jar")) {
-                displayName = "[Fabric 20w10a] ClothConfig2-$project.version"
+                displayName = "[Fabric 20w12a] ClothConfig2-$project.version"
             }
             addArtifact(file("${project.buildDir}/libs/${project.archivesBaseName}-${project.version}-sources.jar"))
             afterEvaluate {

+ 1 - 1
gradle.properties

@@ -2,6 +2,6 @@ minecraft_version=20w12a
 yarn_mappings=20w12a+build.3
 loader_version=0.7.8+build.186
 fabric_version=0.5.4+build.310-1.16
-mod_version=3.1.0-unstable
+mod_version=3.2.0-unstable
 modmenu_version=1.11.0+build.2
 nec_version=1.2.3+1.15.1

+ 2 - 1
src/main/java/me/shedaniel/clothconfig2/ClothConfigInitializer.java

@@ -302,7 +302,8 @@ public class ClothConfigInitializer implements ClientModInitializer {
         testing.addEntry(entryBuilder.startDoubleList("A list of Doubles", Arrays.asList(1d, 2d, 3d)).setDefaultValue(Arrays.asList(1d, 2d, 3d)).build());
         testing.addEntry(entryBuilder.startLongList("A list of Longs", Arrays.asList(1L, 2L, 3L)).setDefaultValue(Arrays.asList(1L, 2L, 3L)).build());
         testing.addEntry(entryBuilder.startStrList("A list of Strings", Arrays.asList("abc", "xyz")).setDefaultValue(Arrays.asList("abc", "xyz")).build());
-        testing.addEntry(entryBuilder.startColorField("A color field", 0x00ffff).setDefaultValue(0xff0000).build());
+        testing.addEntry(entryBuilder.startColorField("A color field", 0x00ffff).setDefaultValue(0x00ffff).build());
+        testing.addEntry(entryBuilder.startColorField("An alpha color field", 0xff00ffff).setDefaultValue(0xff00ffff).setAlphaMode(true).build());
         return builder;
     }
     

+ 6 - 2
src/main/java/me/shedaniel/clothconfig2/api/ConfigEntryBuilder.java

@@ -44,9 +44,13 @@ public interface ConfigEntryBuilder {
     BooleanToggleBuilder startBooleanToggle(String fieldNameKey, boolean value);
     
     StringFieldBuilder startStrField(String fieldNameKey, String value);
-
+    
     ColorFieldBuilder startColorField(String fieldNameKey, int value);
-
+    
+    default ColorFieldBuilder startAlphaColorField(String fieldNameKey, int value) {
+        return startColorField(fieldNameKey, value).setAlphaMode(true);
+    }
+    
     TextFieldBuilder startTextField(String fieldNameKey, String value);
     
     TextDescriptionBuilder startTextDescription(String value);

+ 1 - 1
src/main/java/me/shedaniel/clothconfig2/gui/entries/AbstractTextFieldListListEntry.java

@@ -56,7 +56,7 @@ public abstract class AbstractTextFieldListListEntry<T, C extends AbstractTextFi
             widget.setText(Objects.toString(finalValue));
             widget.setChangedListener(s -> {
                 widget.setEditableColor(getPreferredTextColor());
-                if (!Objects.equals(s, Objects.toString(finalValue))) {
+                if (listListEntry.getScreen() != null && !Objects.equals(s, Objects.toString(finalValue))) {
                     this.listListEntry.getScreen().setEdited(true, this.listListEntry.isRequiresRestart());
                 }
             });

+ 140 - 41
src/main/java/me/shedaniel/clothconfig2/gui/entries/ColorEntry.java

@@ -1,107 +1,206 @@
 package me.shedaniel.clothconfig2.gui.entries;
 
 import me.shedaniel.clothconfig2.gui.widget.ColorDisplayWidget;
+import me.shedaniel.clothconfig2.mixin.ButtonWidgetHooks;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.widget.TextFieldWidget;
+import net.minecraft.client.resource.language.I18n;
 import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
 
+import java.util.Locale;
 import java.util.Optional;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 public class ColorEntry extends TextFieldListEntry<Integer> {
-
+    
     private ColorDisplayWidget colorDisplayWidget;
     private Consumer<Integer> saveConsumer;
-    private static boolean alpha = false;
-
+    private boolean alpha;
+    
+    @ApiStatus.Internal
     @Deprecated
     public ColorEntry(String fieldName, int value, String resetButtonKey, Supplier<Integer> defaultValue, Consumer<Integer> saveConsumer, Supplier<Optional<String[]>> tooltipSupplier, boolean requiresRestart) {
-        super(fieldName, value, resetButtonKey, defaultValue, tooltipSupplier, requiresRestart);
+        super(fieldName, 0, resetButtonKey, defaultValue, tooltipSupplier, requiresRestart);
+        this.alpha = true;
+        ColorValue colorValue = getColorValue(String.valueOf(value));
+        if (colorValue.hasError())
+            throw new IllegalArgumentException("Invalid Color: " + colorValue.getError().name());
+        this.alpha = false;
         this.saveConsumer = saveConsumer;
-        this.colorDisplayWidget = new ColorDisplayWidget(0, 0, 18, getValidIntColor(textFieldWidget.getText()));
+        this.textFieldWidget.setText(getHexColorString(value));
+        this.colorDisplayWidget = new ColorDisplayWidget(0, 0, 20, getColorValueColor(textFieldWidget.getText()));
+        this.original = value;
+        ((ButtonWidgetHooks) this.resetButton).setOnPress(button -> {
+            this.textFieldWidget.setText(getHexColorString(original));
+            getScreen().setEdited(true, isRequiresRestart());
+        });
     }
-
+    
     @Override
     public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
         super.render(index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
-        this.colorDisplayWidget.y = y + 1;
-        if (isValidHexColorString(textFieldWidget.getText()))
-            colorDisplayWidget.setColor(getValidIntColor(textFieldWidget.getText()));
+        this.colorDisplayWidget.y = y;
+        ColorValue value = getColorValue(textFieldWidget.getText());
+        if (!value.hasError())
+            colorDisplayWidget.setColor(alpha ? value.getColor() : 0xff000000 | value.getColor());
         if (MinecraftClient.getInstance().textRenderer.isRightToLeft()) {
             this.colorDisplayWidget.x = x + resetButton.getWidth() + textFieldWidget.getWidth();
         } else {
-            this.colorDisplayWidget.x = textFieldWidget.x - 21;
+            this.colorDisplayWidget.x = textFieldWidget.x - 23;
         }
         colorDisplayWidget.render(mouseX, mouseY, delta);
     }
-
+    
     @Override
     protected void textFieldPreRender(TextFieldWidget widget) {
-        if (isValidHexColorString(textFieldWidget.getText())) {
+        if (!getError().isPresent()) {
             widget.setEditableColor(14737632);
         } else {
             widget.setEditableColor(16733525);
         }
     }
-
+    
     @Override
     public void save() {
         if (saveConsumer != null)
             saveConsumer.accept(getValue());
     }
-
+    
     @Override
     protected boolean isMatchDefault(String text) {
-        return getDefaultValue().isPresent() && (getValidIntColor(text) == getDefaultValue().get());
+        if (!getDefaultValue().isPresent())
+            return false;
+        ColorValue colorValue = getColorValue(text);
+        return colorValue.hasError() && colorValue.color == getDefaultValue().get();
     }
-
+    
     @Override
     public Integer getValue() {
-        return getValidIntColor(textFieldWidget.getText());
+        return getColorValueColor(textFieldWidget.getText());
     }
-
+    
+    @Deprecated
+    public void setValue(int color) {
+        textFieldWidget.setText(getHexColorString(color));
+    }
+    
+    @Override
+    public Optional<String> getError() {
+        ColorValue colorValue = getColorValue(this.textFieldWidget.getText());
+        if (colorValue.hasError())
+            return Optional.of(I18n.translate("text.cloth-config.error.color." + colorValue.getError().name().toLowerCase(Locale.ROOT)));
+        return super.getError();
+    }
+    
     public void withAlpha() {
         if (!alpha) {
             this.alpha = true;
+            textFieldWidget.setText(getHexColorString(original));
         }
-        //textFieldWidget.setText(getHexColorString(original));
     }
-
+    
     public void withoutAlpha() {
         if (alpha) {
             alpha = false;
+            textFieldWidget.setText(getHexColorString(original));
         }
-        //textFieldWidget.setText(getHexColorString(original));
     }
-
+    
     protected String stripHexStarter(String hex) {
         if (hex.startsWith("#")) {
             return hex.substring(1);
         } else return hex;
     }
-
-    protected boolean isValidHexColorString(String hex) {
-        try {
-            String stripped = stripHexStarter(hex);
-            Long.parseLong(stripped, 16);
-            return alpha ? stripped.length() == 8 : stripped.length() == 6;
-        } catch (NumberFormatException ex) {
-            return false;
-        }
+    
+    protected boolean isValidColorString(String str) {
+        return !getColorValue(str).hasError();
     }
-
-    protected int getValidIntColor(String hex) {
-        if (isValidHexColorString(hex)) {
-            try {
-                return (int) (Long.parseLong(stripHexStarter(hex), 16));
-            } catch (NumberFormatException ex) {
-                return -1;
+    
+    protected int getColorValueColor(String str) {
+        return getColorValue(str).getColor();
+    }
+    
+    protected ColorValue getColorValue(String str) {
+        try {
+            int color;
+            if (str.startsWith("#")) {
+                String stripHexStarter = stripHexStarter(str);
+                if (stripHexStarter.length() > 8) return ColorError.INVALID_COLOR.toValue();
+                if (!alpha && stripHexStarter.length() > 6) return ColorError.NO_ALPHA_ALLOWED.toValue();
+                color = (int) Long.parseLong(stripHexStarter, 16);
+            } else {
+                color = (int) Long.parseLong(str);
             }
-        } else return -1;
+            int a = color >> 24 & 0xFF;
+            if (!alpha && a > 0)
+                return ColorError.NO_ALPHA_ALLOWED.toValue();
+            if (a < 0 || a > 255)
+                return ColorError.INVALID_ALPHA.toValue();
+            int r = color >> 16 & 0xFF;
+            if (r < 0 || r > 255)
+                return ColorError.INVALID_RED.toValue();
+            int g = color >> 8 & 0xFF;
+            if (g < 0 || g > 255)
+                return ColorError.INVALID_GREEN.toValue();
+            int b = color & 0xFF;
+            if (b < 0 || b > 255)
+                return ColorError.INVALID_BLUE.toValue();
+            return new ColorValue(color);
+        } catch (NumberFormatException e) {
+            return ColorError.INVALID_COLOR.toValue();
+        }
     }
-
-    protected static String getHexColorString(int color) {
+    
+    protected String getHexColorString(int color) {
         return "#" + StringUtils.leftPad(Integer.toHexString(color), alpha ? 8 : 6, '0');
     }
+    
+    protected enum ColorError {
+        NO_ALPHA_ALLOWED,
+        INVALID_ALPHA,
+        INVALID_RED,
+        INVALID_GREEN,
+        INVALID_BLUE,
+        INVALID_COLOR;
+        
+        private ColorValue value;
+        
+        ColorError() {
+            this.value = new ColorValue(this);
+        }
+        
+        public ColorValue toValue() {
+            return value;
+        }
+    }
+    
+    protected static class ColorValue {
+        private int color = -1;
+        @Nullable
+        private ColorError error = null;
+        
+        public ColorValue(int color) {
+            this.color = color;
+        }
+        
+        public ColorValue(ColorError error) {
+            this.error = error;
+        }
+        
+        public int getColor() {
+            return color;
+        }
+        
+        @Nullable
+        public ColorError getError() {
+            return error;
+        }
+        
+        public boolean hasError() {
+            return getError() != null;
+        }
+    }
 }

+ 1 - 1
src/main/java/me/shedaniel/clothconfig2/gui/entries/DropdownBoxEntry.java

@@ -689,7 +689,7 @@ public class DropdownBoxEntry<T> extends TooltipListEntry<T> {
             textFieldWidget.setMaxLength(999999);
             textFieldWidget.setText(toStringFunction.apply(value));
             textFieldWidget.setChangedListener(s -> {
-                if (!toStringFunction.apply(value).equals(s))
+                if (getParent() != null && getParent().getScreen() != null && !toStringFunction.apply(value).equals(s))
                     getParent().getScreen().setEdited(true, getParent().isRequiresRestart());
             });
         }

+ 1 - 1
src/main/java/me/shedaniel/clothconfig2/gui/entries/TextFieldListEntry.java

@@ -53,7 +53,7 @@ public abstract class TextFieldListEntry<T> extends TooltipListEntry<T> {
         textFieldWidget.setMaxLength(999999);
         textFieldWidget.setText(String.valueOf(original));
         textFieldWidget.setChangedListener(s -> {
-            if (!original.equals(s))
+            if (getScreen() != null && !original.equals(s))
                 getScreen().setEdited(true, isRequiresRestart());
         });
         this.resetButton = new ButtonWidget(0, 0, MinecraftClient.getInstance().textRenderer.getStringWidth(I18n.translate(resetButtonKey)) + 6, 20, I18n.translate(resetButtonKey), widget -> {

+ 9 - 9
src/main/java/me/shedaniel/clothconfig2/gui/widget/ColorDisplayWidget.java

@@ -3,32 +3,32 @@ package me.shedaniel.clothconfig2.gui.widget;
 import net.minecraft.client.gui.widget.AbstractButtonWidget;
 
 public class ColorDisplayWidget extends AbstractButtonWidget {
-
+    
     protected int color;
     protected int size;
-
+    
     public ColorDisplayWidget(int x, int y, int size, int color) {
         super(x, y, size, size, "");
-        this.color = 0xff000000 | color;
+        this.color = color;
         this.size = size;
     }
-
+    
     @Override
     public void renderButton(int mouseX, int mouseY, float delta) {
         fillGradient(this.x, this.y, this.x + size, this.y + size, -0x5F5F60, -0x5F5F60);
-        fillGradient(this.x + 1, this.y + 1, this.x + size - 1, this.y + size - 1, 0xff000000, 0xff000000);
+        fillGradient(this.x + 1, this.y + 1, this.x + size - 1, this.y + size - 1, 0xffffffff, 0xffffffff);
         fillGradient(this.x + 1, this.y + 1, this.x + size - 1, this.y + size - 1, color, color);
     }
-
+    
     @Override
     public void onClick(double mouseX, double mouseY) {
     }
-
+    
     @Override
     public void onRelease(double mouseX, double mouseY) {
     }
-
+    
     public void setColor(int color) {
-        this.color = 0xff000000 | color;
+        this.color = color;
     }
 }

+ 15 - 15
src/main/java/me/shedaniel/clothconfig2/impl/builders/ColorFieldBuilder.java

@@ -13,69 +13,69 @@ import java.util.function.Supplier;
 
 @Environment(EnvType.CLIENT)
 public class ColorFieldBuilder extends FieldBuilder<String, ColorEntry> {
-
+    
     private Consumer<Integer> saveConsumer = null;
     private Function<Integer, Optional<String>> errorSupplier;
     private Function<Integer, Optional<String[]>> tooltipSupplier = str -> Optional.empty();
     private final int value;
     private Supplier<Integer> defaultValue;
-    private boolean alpha;
-
+    private boolean alpha = false;
+    
     public ColorFieldBuilder(String resetButtonKey, String fieldNameKey, int value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
-
+    
     public ColorFieldBuilder setErrorSupplier(Function<Integer, Optional<String>> errorSupplier) {
         this.errorSupplier = errorSupplier;
         return this;
     }
-
+    
     public ColorFieldBuilder requireRestart() {
         requireRestart(true);
         return this;
     }
-
+    
     public ColorFieldBuilder setSaveConsumer(Consumer<Integer> saveConsumer) {
         this.saveConsumer = saveConsumer;
         return this;
     }
-
+    
     public ColorFieldBuilder setDefaultValue(Supplier<Integer> defaultValue) {
         this.defaultValue = defaultValue;
         return this;
     }
-
+    
     public ColorFieldBuilder setAlphaMode(boolean withAlpha) {
         this.alpha = withAlpha;
         return this;
     }
-
+    
     public ColorFieldBuilder setDefaultValue(int defaultValue) {
         this.defaultValue = () -> Objects.requireNonNull(defaultValue);
         return this;
     }
-
+    
     public ColorFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = str -> tooltipSupplier.get();
         return this;
     }
-
+    
     public ColorFieldBuilder setTooltipSupplier(Function<Integer, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
-
+    
     public ColorFieldBuilder setTooltip(Optional<String[]> tooltip) {
         this.tooltipSupplier = str -> tooltip;
         return this;
     }
-
+    
     public ColorFieldBuilder setTooltip(String... tooltip) {
         this.tooltipSupplier = str -> Optional.ofNullable(tooltip);
         return this;
     }
-
+    
     @NotNull
     @Override
     public ColorEntry build() {
@@ -90,5 +90,5 @@ public class ColorFieldBuilder extends FieldBuilder<String, ColorEntry> {
             entry.setErrorSupplier(() -> errorSupplier.apply(entry.getValue()));
         return entry;
     }
-
+    
 }

+ 13 - 0
src/main/java/me/shedaniel/clothconfig2/mixin/ButtonWidgetHooks.java

@@ -0,0 +1,13 @@
+package me.shedaniel.clothconfig2.mixin;
+
+import net.minecraft.client.gui.widget.ButtonWidget;
+import org.jetbrains.annotations.ApiStatus;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(ButtonWidget.class)
+@ApiStatus.Internal
+public interface ButtonWidgetHooks {
+    @Accessor("onPress")
+    void setOnPress(ButtonWidget.PressAction action);
+}

+ 7 - 0
src/main/resources/assets/cloth-config2/lang/en_us.json

@@ -14,6 +14,13 @@
   "text.cloth-config.error.not_valid_number_double": "Not a valid number! (Double)",
   "text.cloth-config.error.too_large": "Too Large! (Maximum: %d)",
   "text.cloth-config.error.too_small": "Too Small! (Minimum: %d)",
+  "text.cloth-config.error.color.no_alpha_allowed": "No Alpha Allowed!",
+  "text.cloth-config.error.color.invalid_alpha": "Not a valid value! (Alpha)",
+  "text.cloth-config.error.color.invalid_red": "Not a valid value! (Red)",
+  "text.cloth-config.error.color.invalid_green": "Not a valid value! (Green)",
+  "text.cloth-config.error.color.invalid_blue": "Not a valid value! (Blue)",
+  "text.cloth-config.error.color.invalid_color": "Not a valid color!",
+  "text.cloth-config.error.color.no_hash": "Not a valid color! (Missing #)",
   "text.cloth-config.list.add": "Insert New",
   "text.cloth-config.list.remove": "Delete Selected",
   "text.cloth-config.error_cannot_save": "Error!",

+ 1 - 7
src/main/resources/mixin.cloth-config2.json

@@ -3,13 +3,7 @@
   "package": "me.shedaniel.clothconfig2.mixin",
   "minVersion": "0.7.11",
   "compatibilityLevel": "JAVA_8",
-  "mixins": [],
-  "client": [
-    "MixinControlsOptionsScreen",
-    "MixinGameOptions",
-    "MixinKeyBinding",
-    "MouseHooks"
-  ],
+  "client": ["ButtonWidgetHooks", "MixinControlsOptionsScreen", "MixinGameOptions", "MixinKeyBinding", "MouseHooks"],
   "injectors": {
     "defaultRequire": 1
   }