From c830bbc703d456e84a63f1324420dae70a5ec4ea Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sat, 21 Jul 2018 21:58:46 +0800 Subject: [PATCH] reorder version in main page --- .../java/org/jackhuang/hmcl/ui/MainPage.java | 3 + .../org/jackhuang/hmcl/mod/ModManager.java | 2 +- .../hmcl/util/ComposedVersionNumber.java | 55 +++++++++ .../jackhuang/hmcl/util/IntVersionNumber.java | 61 ++++------ .../hmcl/util/StringVersionNumber.java | 19 --- .../jackhuang/hmcl/util/VersionNumber.java | 111 +++++++++++------- 6 files changed, 147 insertions(+), 104 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ComposedVersionNumber.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java index c4664f3c2..8c973a6f8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -49,6 +49,8 @@ import org.jackhuang.hmcl.ui.download.DownloadWizardProvider; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.OperatingSystem; +import org.jackhuang.hmcl.util.VersionNumber; + import java.io.File; import java.io.IOException; import java.util.List; @@ -234,6 +236,7 @@ public final class MainPage extends StackPane implements DecoratorPage { private void loadVersions(HMCLGameRepository repository) { List children = repository.getVersions().parallelStream() + .sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId()))) .map(version -> buildNode(repository, version, () -> GameVersion.minecraftVersion(repository.getVersionJar(version.getId())).orElse("Unknown"))) .collect(Collectors.toList()); JFXUtilities.runInFX(() -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java index c203ebfea..2d3da4a30 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java @@ -41,7 +41,7 @@ public final class ModManager { File modsDirectory = new File(repository.getRunDirectory(id), "mods"); Consumer puter = modFile -> Lang.ignoringException(() -> modCache.put(id, ModInfo.fromFile(modFile))); Optional.ofNullable(modsDirectory.listFiles()).map(Arrays::stream).ifPresent(files -> files.forEach(modFile -> { - if (modFile.isDirectory() && VersionNumber.parseVersion(modFile.getName()) != null) + if (modFile.isDirectory() && VersionNumber.parseVersion(modFile.getName()).isPresent()) Optional.ofNullable(modFile.listFiles()).map(Arrays::stream).ifPresent(x -> x.forEach(puter)); else puter.accept(modFile); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ComposedVersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ComposedVersionNumber.java new file mode 100644 index 000000000..ffae2f218 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ComposedVersionNumber.java @@ -0,0 +1,55 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.util; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * If a version string contains '-', a {@link ComposedVersionNumber} + * will be generated. + * + * Formats like 1.7.10-OptiFine, 1.12.2-Forge + * + * @author huangyuhui + */ +public final class ComposedVersionNumber extends VersionNumber { + List composed; + + public static boolean isComposedVersionNumber(String version) { + return version.contains("-"); + } + + ComposedVersionNumber(String version) { + composed = Arrays.stream(version.split("-")) + .map(VersionNumber::asVersion) + .collect(Collectors.toList()); + } + + @Override + public int hashCode() { + return Objects.hash(composed); + } + + @Override + public String toString() { + return composed.stream().map(VersionNumber::toString).collect(Collectors.joining("-")); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java index b2c5e966d..b6a19590b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IntVersionNumber.java @@ -17,7 +17,10 @@ */ package org.jackhuang.hmcl.util; +import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -28,57 +31,37 @@ import java.util.stream.Collectors; */ public final class IntVersionNumber extends VersionNumber { - private final List version; + final List version; - IntVersionNumber(List version) { - this.version = version; + public static boolean isIntVersionNumber(String version) { + return version.chars().noneMatch(ch -> ch != '.' && (ch < '0' || ch > '9')) + && !version.contains("..") && StringUtils.isNotBlank(version); + } + + IntVersionNumber(String version) { + if (!isIntVersionNumber(version)) + throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed."); + + List versions = Arrays.stream(version.split("\\.")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0) + versions.remove(versions.size() - 1); + + this.version = versions; } public int get(int index) { return version.get(index); } - @Override - public int compareTo(VersionNumber o) { - if (!(o instanceof IntVersionNumber)) - return 0; - IntVersionNumber other = (IntVersionNumber) o; - int len = Math.max(this.version.size(), other.version.size()); - for (int i = 0; i < len; ++i) { - int thisInt = Lang.get(this.version, i).orElse(0); - int otherInt = Lang.get(other.version, i).orElse(0); - if (thisInt != otherInt) - return Integer.compare(thisInt, otherInt); - } - return 0; - } - @Override public int hashCode() { - int hash = 3; - for (int i : version) - hash = 83 * hash + i; - return hash; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof VersionNumber)) - return false; - if (!(obj instanceof IntVersionNumber)) - return true; - IntVersionNumber other = (IntVersionNumber) obj; - if (version.size() != other.version.size()) - return false; - - for (int i = 0; i < version.size(); ++i) - if (!version.get(i).equals(other.version.get(i))) - return false; - return true; + return Objects.hash(version); } @Override public String toString() { - return String.join(".", version.stream().map(Object::toString).collect(Collectors.toList())); + return version.stream().map(Object::toString).collect(Collectors.joining(".")); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringVersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringVersionNumber.java index 9a06d4dcb..10c50939f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringVersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringVersionNumber.java @@ -34,14 +34,6 @@ public final class StringVersionNumber extends VersionNumber { this.version = version; } - @Override - public int compareTo(VersionNumber o) { - if (!(o instanceof StringVersionNumber)) - return 0; - - return version.compareTo(((StringVersionNumber) o).version); - } - public String getVersion() { return version; } @@ -56,15 +48,4 @@ public final class StringVersionNumber extends VersionNumber { return version; } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof VersionNumber)) - return false; - - if (!(obj instanceof StringVersionNumber)) - return true; - - return version.equals(((StringVersionNumber) obj).version); - } - } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java index a510439ab..3ecafe2f1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/VersionNumber.java @@ -17,10 +17,7 @@ */ package org.jackhuang.hmcl.util; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Objects; -import java.util.Optional; +import java.util.*; /** * The formatted version number represents a version string. @@ -29,52 +26,76 @@ import java.util.Optional; */ public abstract class VersionNumber implements Comparable { - /** - * @throws IllegalArgumentException if there are some characters excluding digits and dots. - * @param version version string in form x.x.x - * @return the int version number - */ - public static IntVersionNumber asIntVersionNumber(String version) { - if (version.chars().filter(ch -> ch != '.' && (ch < '0' || ch > '9')).count() > 0 - || version.contains("..") || StringUtils.isBlank(version)) - throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed."); - - String[] s = version.split("\\."); - ArrayList versions = new ArrayList<>(s.length); - for (String value : s) versions.add(Integer.parseInt(value)); - while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0) - versions.remove(versions.size() - 1); - - return new IntVersionNumber(Collections.unmodifiableList(versions)); - } - - public static StringVersionNumber asStringVersionNumber(String version) { - return new StringVersionNumber(version); - } - public static VersionNumber asVersion(String version) { Objects.requireNonNull(version); - try { - return asIntVersionNumber(version); - } catch (IllegalArgumentException e) { - return asStringVersionNumber(version); - } + if (ComposedVersionNumber.isComposedVersionNumber(version)) + return new ComposedVersionNumber(version); + else if (IntVersionNumber.isIntVersionNumber(version)) + return new IntVersionNumber(version); + else + return new StringVersionNumber(version); } public static Optional parseVersion(String str) { - if (str.chars().anyMatch(it -> it != '.' && (it < '0' || it > '9')) || StringUtils.isBlank(str)) + if (IntVersionNumber.isIntVersionNumber(str)) + return Optional.of(new IntVersionNumber(str).toString()); + else return Optional.empty(); - String[] s = str.split("\\."); - for (String i : s) - if (StringUtils.isBlank(i)) - return Optional.empty(); - StringBuilder builder = new StringBuilder(); - int last = s.length - 1; - for (int i = s.length - 1; i >= 0; --i) - if (Integer.parseInt(s[i]) == 0) - last = i; - for (int i = 0; i < last; ++i) - builder.append(s[i]).append("."); - return Optional.of(builder.append(s[last]).toString()); } + + @Override + public int compareTo(VersionNumber o) { + return COMPARATOR.compare(this, o); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + else return toString().equals(obj.toString()); + } + + private static > int compareTo(List a, List b) { + int i; + for (i = 0; i < a.size() && i < b.size(); ++i) { + int res = a.get(i).compareTo(b.get(i)); + if (res != 0) + return res; + } + if (i < a.size()) return 1; + else if (i < b.size()) return -1; + else return 0; + } + + public static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(VersionNumber a, VersionNumber b) { + if (a == null || b == null) + return 0; + else { + if (a instanceof ComposedVersionNumber) { + if (b instanceof ComposedVersionNumber) + return compareTo(((ComposedVersionNumber) a).composed, ((ComposedVersionNumber) b).composed); + else + return compare(((ComposedVersionNumber) a).composed.get(0), b); + } else if (a instanceof IntVersionNumber) { + if (b instanceof ComposedVersionNumber) + return -compare(b, a); + else if (b instanceof IntVersionNumber) + return compareTo(((IntVersionNumber) a).version, ((IntVersionNumber) b).version); + else if (b instanceof StringVersionNumber) + return a.toString().compareTo(b.toString()); + } else if (a instanceof StringVersionNumber) { + if (b instanceof ComposedVersionNumber) + return -compare(b, a); + else if (b instanceof StringVersionNumber) + return a.toString().compareTo(b.toString()); + else if (b instanceof IntVersionNumber) + return a.toString().compareTo(b.toString()); + } + + throw new IllegalArgumentException("Unrecognized VersionNumber " + a + " and " + b); + } + } + + }; }