From 118a6cf0d111cc6bcc0d1f00875e4795da09dfc4 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Fri, 8 Jun 2018 12:45:44 +0800 Subject: [PATCH] Fasten version item construction --- .../java/org/jackhuang/hmcl/ui/MainPage.java | 20 ++-- .../org/jackhuang/hmcl/ui/VersionItem.java | 108 +++++++++++++++++- HMCL/src/main/resources/assets/css/root.css | 8 ++ .../resources/assets/fxml/account-add.fxml | 6 +- .../resources/assets/fxml/version-item.fxml | 47 -------- .../resources/assets/lang/I18N.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- .../hmcl/game/DefaultGameRepository.java | 80 ++++++------- .../org/jackhuang/hmcl/task/ParallelTask.java | 9 +- settings.gradle | 2 +- 10 files changed, 174 insertions(+), 110 deletions(-) delete mode 100644 HMCL/src/main/resources/assets/fxml/version-item.fxml 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 baeda2efe..d9cb99f1d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -50,10 +50,11 @@ import org.jackhuang.hmcl.util.OperatingSystem; import java.io.File; import java.io.IOException; -import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; @@ -88,7 +89,8 @@ public final class MainPage extends StackPane implements DecoratorPage { }); EventBus.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(event -> { if (event.getSource() == profile.getRepository()) - JFXUtilities.runInFXAndWait(this::loadingVersions); + // This will occupy 0.5s. Too slow! + JFXUtilities.runInFX(this::loadingVersions); }); EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(event -> { this.profile = event.getProfile(); @@ -173,7 +175,7 @@ public final class MainPage extends StackPane implements DecoratorPage { } catch (MismatchedModpackTypeException e) { Controllers.closeDialog(region.get()); Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); - } catch (IOException e) { + } catch (IOException e) { Controllers.closeDialog(region.get()); Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } @@ -191,7 +193,7 @@ public final class MainPage extends StackPane implements DecoratorPage { Launcher.i18n("modpack.export"), Launcher.i18n("folder.game") )); - versionList.setOnMouseClicked(e ->{ + versionList.setOnMouseClicked(e -> { versionPopup.hide(); switch (versionList.getSelectionModel().getSelectedIndex()) { case 0: @@ -208,7 +210,8 @@ public final class MainPage extends StackPane implements DecoratorPage { break; default: break; - }}); + } + }); versionPopup.show(item, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, event.getX(), event.getY()); } else if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { if (Settings.INSTANCE.getSelectedAccount() == null) @@ -229,10 +232,9 @@ public final class MainPage extends StackPane implements DecoratorPage { } private void loadVersions(HMCLGameRepository repository) { - List children = new LinkedList<>(); - for (Version version : repository.getVersions()) { - children.add(buildNode(repository, version, () -> GameVersion.minecraftVersion(repository.getVersionJar(version.getId())).orElse("Unknown"))); - } + List children = repository.getVersions().parallelStream() + .map(version -> buildNode(repository, version, () -> GameVersion.minecraftVersion(repository.getVersionJar(version.getId())).orElse("Unknown"))) + .collect(Collectors.toList()); JFXUtilities.runInFX(() -> { if (profile == repository.getProfile()) { masonryPane.getChildren().setAll(children); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java index 7843d3d7e..296912872 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java @@ -21,6 +21,8 @@ import com.jfoenix.controls.JFXButton; import javafx.beans.binding.Bindings; import javafx.event.EventHandler; import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.effect.BlurType; import javafx.scene.effect.DropShadow; @@ -28,10 +30,9 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; -import javafx.scene.layout.Pane; -import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; import javafx.scene.paint.Color; +import javafx.scene.text.TextAlignment; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; @@ -65,8 +66,107 @@ public final class VersionItem extends StackPane { private EventHandler launchClickedHandler = null; + private void initializeComponents() { + setPickOnBounds(false); + FXUtils.setLimitWidth(this, 160); + FXUtils.setLimitHeight(this, 156); + + content = new VBox(); + { + header = new StackPane(); + VBox.setVgrow(header, Priority.ALWAYS); + header.setPickOnBounds(false); + header.setPadding(new Insets(8)); + header.setStyle("-fx-background-radius: 2 2 0 0; -fx-background-color: rgb(255,255,255,0.87);"); + { + VBox headerContent = new VBox(); + headerContent.setPadding(new Insets(8, 8, 0, 8)); + { + lblVersionName = new Label(); + lblVersionName.setStyle("-fx-font-size: 15;"); + lblVersionName.setTextAlignment(TextAlignment.JUSTIFY); + lblVersionName.setWrapText(true); + headerContent.getChildren().add(lblVersionName); + + lblGameVersion = new Label(); + lblGameVersion.setStyle("-fx-font-size: 11;"); + lblGameVersion.setTextAlignment(TextAlignment.JUSTIFY); + lblGameVersion.setWrapText(true); + headerContent.getChildren().add(lblGameVersion); + + lblLibraries = new Label(); + lblLibraries.setStyle("-fx-font-size: 10; -fx-text-fill: gray;"); + lblLibraries.setTextAlignment(TextAlignment.JUSTIFY); + lblLibraries.setWrapText(true); + headerContent.getChildren().add(lblLibraries); + } + header.getChildren().add(headerContent); + } + content.getChildren().add(header); + + body = new StackPane(); + body.setStyle("-fx-background-radius: 0 0 2 2; -fx-background-color: rgb(255,255,255,0.87); -fx-padding: 8;"); + body.setMinHeight(40); + body.setPickOnBounds(false); + { + BorderPane bodyContent = new BorderPane(); + { + HBox hbox = new HBox(); + hbox.setSpacing(8); + { + btnSettings = new JFXButton(); + btnSettings.getStyleClass().add("toggle-icon4"); + FXUtils.setLimitWidth(btnSettings, 30); + FXUtils.setLimitHeight(btnSettings, 30); + hbox.getChildren().add(btnSettings); + + btnUpdate = new JFXButton(); + btnUpdate.getStyleClass().add("toggle-icon4"); + FXUtils.setLimitWidth(btnUpdate, 30); + FXUtils.setLimitHeight(btnUpdate, 30); + hbox.getChildren().add(btnUpdate); + } + bodyContent.setLeft(hbox); + } + { + HBox hbox = new HBox(); + hbox.setSpacing(8); + { + btnScript = new JFXButton(); + btnScript.getStyleClass().add("toggle-icon4"); + FXUtils.setLimitWidth(btnScript, 30); + FXUtils.setLimitHeight(btnScript, 30); + hbox.getChildren().add(btnScript); + + btnLaunch = new JFXButton(); + btnLaunch.getStyleClass().add("toggle-icon4"); + FXUtils.setLimitWidth(btnLaunch, 30); + FXUtils.setLimitHeight(btnLaunch, 30); + hbox.getChildren().add(btnLaunch); + } + bodyContent.setRight(hbox); + } + body.getChildren().setAll(bodyContent); + } + content.getChildren().add(body); + } + getChildren().add(content); + + icon = new StackPane(); + StackPane.setAlignment(icon, Pos.TOP_RIGHT); + icon.setPickOnBounds(false); + { + iconView = new ImageView(); + StackPane.setAlignment(iconView, Pos.CENTER_RIGHT); + StackPane.setMargin(iconView, new Insets(0, 12, 0, 0)); + iconView.setImage(new Image("/assets/img/icon.png")); + icon.getChildren().add(iconView); + } + getChildren().add(icon); + } + public VersionItem() { - FXUtils.loadFXML(this, "/assets/fxml/version-item.fxml"); + initializeComponents(); setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.26), 5.0, 0.12, -1.0, 1.0)); btnSettings.setGraphic(SVG.gear(Theme.blackFillBinding(), 15, 15)); btnUpdate.setGraphic(SVG.update(Theme.blackFillBinding(), 15, 15)); diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 61ce4c0de..5fe3cea5d 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -911,6 +911,14 @@ -fx-stroke-width: 5.0; } +.small-spinner { + -jfx-radius: 10; +} + +.small-spinner > .arc { + -fx-stroke-width: 3.0; +} + .second-spinner { -jfx-radius: 30; } diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml index c08f1b2c8..7cd0320dd 100644 --- a/HMCL/src/main/resources/assets/fxml/account-add.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -56,9 +56,11 @@ - diff --git a/HMCL/src/main/resources/assets/fxml/version-item.fxml b/HMCL/src/main/resources/assets/fxml/version-item.fxml deleted file mode 100644 index 55c2766ba..000000000 --- a/HMCL/src/main/resources/assets/fxml/version-item.fxml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 39ddaebc5..0540ae2fd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -18,7 +18,7 @@ about.copyright=Copyright about.copyright.statement=Copyright (c) 2018 huangyuhui. about.author=Author -about.author.statement=huanghongxun (MCF: klkl6523) +about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=Thanks to about.thanks_to.statement=bangbang93 (BMCLAPI, http://bmclapi2.bangbang93.com/)\ngamerteam (Default background image)\nAll contributors. about.dependency=Dependency diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 42e309201..cbd4831dd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -18,7 +18,7 @@ about.copyright=版权 about.copyright.statement=Copyright (c) 2018 huangyuhui. about.author=作者 -about.author.statement=huanghongxun (百度贴吧:huanghongxun20) +about.author.statement=huanghongxun (hmcl@huangyuhui.net) about.thanks_to=鸣谢 about.thanks_to.statement=bangbang93 (BMCLAPI, http://bmclapi2.bangbang93.com/)\ngamerteam (默认背景图)\n所有参与本项目,issue,pull requests的贡献者 about.dependency=依赖 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index 736765cd2..9594d79f5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -30,6 +30,7 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.logging.Level; +import java.util.stream.Stream; /** * An implementation of classic Minecraft game repository. @@ -170,57 +171,50 @@ public class DefaultGameRepository implements GameRepository { File[] files = new File(getBaseDirectory(), "versions").listFiles(); if (files != null) - for (File dir : files) - if (dir.isDirectory()) { - if (Thread.interrupted()) { - this.versions = new HashMap<>(); - loaded = false; - return; - } + Arrays.stream(files).parallel().filter(File::isDirectory).flatMap(dir -> { + String id = dir.getName(); + File json = new File(dir, id + ".json"); - String id = dir.getName(); - File json = new File(dir, id + ".json"); + // If user renamed the json file by mistake or created the json file in a wrong name, + // we will find the only json and rename it to correct name. + if (!json.exists()) { + List jsons = FileUtils.listFilesByExtension(dir, "json"); + if (jsons.size() == 1) + if (!jsons.get(0).renameTo(json)) { + Logging.LOG.warning("Cannot rename json file " + jsons.get(0) + " to " + json + ", ignoring version " + id); + return Stream.empty(); + } + } - // If user renamed the json file by mistake or created the json file in a wrong name, - // we will find the only json and rename it to correct name. - if (!json.exists()) { - List jsons = FileUtils.listFilesByExtension(dir, "json"); - if (jsons.size() == 1) - if (!jsons.get(0).renameTo(json)) { - Logging.LOG.warning("Cannot rename json file " + jsons.get(0) + " to " + json + ", ignoring version " + id); - continue; - } - } + Version version; + try { + version = Objects.requireNonNull(readVersionJson(json)); + } catch (Exception e) { + // JsonSyntaxException or IOException or NullPointerException(!!) + if (EventBus.EVENT_BUS.fireEvent(new GameJsonParseFailedEvent(this, json, id)) != Event.Result.ALLOW) + return Stream.empty(); - Version version; try { version = Objects.requireNonNull(readVersionJson(json)); - } catch (Exception e) { - // JsonSyntaxException or IOException or NullPointerException(!!) - if (EventBus.EVENT_BUS.fireEvent(new GameJsonParseFailedEvent(this, json, id)) != Event.Result.ALLOW) - continue; - - try { - version = Objects.requireNonNull(readVersionJson(json)); - } catch (Exception e2) { - Logging.LOG.log(Level.SEVERE, "User corrected version json is still malformed"); - continue; - } + } catch (Exception e2) { + Logging.LOG.log(Level.SEVERE, "User corrected version json is still malformed"); + return Stream.empty(); } - - if (!id.equals(version.getId())) { - version = version.setId(id); - try { - FileUtils.writeText(json, Constants.GSON.toJson(version)); - } catch (Exception e) { - Logging.LOG.log(Level.WARNING, "Ignoring version " + id + " because wrong id " + version.getId() + " is set and cannot correct it."); - continue; - } - } - - provider.addVersion(version); } + if (!id.equals(version.getId())) { + version = version.setId(id); + try { + FileUtils.writeText(json, Constants.GSON.toJson(version)); + } catch (Exception e) { + Logging.LOG.log(Level.WARNING, "Ignoring version " + id + " because wrong id " + version.getId() + " is set and cannot correct it."); + return Stream.empty(); + } + } + + return Stream.of(version); + }).forEachOrdered(provider::addVersion); + for (Version version : provider.getVersionMap().values()) { try { Version resolved = version.resolve(provider); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java index aa540af81..022a7d45c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java @@ -28,7 +28,7 @@ import java.util.Collection; */ public final class ParallelTask extends Task { - private final Task[] tasks; + private final Collection tasks; /** * Constructor. @@ -36,6 +36,11 @@ public final class ParallelTask extends Task { * @param tasks the tasks that can be executed parallelly. */ public ParallelTask(Task... tasks) { + this.tasks = Arrays.asList(tasks); + setSignificance(TaskSignificance.MINOR); + } + + public ParallelTask(Collection tasks) { this.tasks = tasks; setSignificance(TaskSignificance.MINOR); } @@ -46,7 +51,7 @@ public final class ParallelTask extends Task { @Override public Collection getDependents() { - return Arrays.asList(tasks); + return tasks; } } diff --git a/settings.gradle b/settings.gradle index a15d5837b..d9fd5ba34 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -rootProject.name = 'HMCLKotlin' +rootProject.name = 'HMCL3' include 'HMCL' include 'HMCLCore'