From c775e8368e582aa2388969f87b8fc537cb1e6543 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Sat, 26 Aug 2017 10:53:05 +0800 Subject: [PATCH] Try to asynchronize some time-costly tasks --- .../main/kotlin/org/jackhuang/hmcl/Main.kt | 4 +++ .../jackhuang/hmcl/game/HMCLGameRepository.kt | 28 ++++++++--------- .../org/jackhuang/hmcl/setting/Profile.kt | 6 +--- .../jackhuang/hmcl/setting/VersionSetting.kt | 2 +- .../org/jackhuang/hmcl/ui/Controllers.kt | 7 +++-- .../kotlin/org/jackhuang/hmcl/ui/ModItem.kt | 27 +++++++++++++---- .../hmcl/ui/VersionSettingsController.kt | 19 ++++++++---- .../hmcl/ui/download/InstallWizardProvider.kt | 2 +- .../assets/fxml/version/mod-item.fxml | 30 ------------------- .../resources/assets/fxml/version/mod.fxml | 2 +- .../hmcl/game/DefaultGameRepository.kt | 1 - .../org/jackhuang/hmcl/util/JavaVersion.kt | 24 ++++++++++++--- 12 files changed, 82 insertions(+), 70 deletions(-) delete mode 100644 HMCL/src/main/resources/assets/fxml/version/mod-item.fxml diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/Main.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/Main.kt index c2abc6373..1e740a984 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/Main.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/Main.kt @@ -42,15 +42,19 @@ fun i18n(key: String): String { class Main : Application() { override fun start(stage: Stage) { + println(System.currentTimeMillis()) // When launcher visibility is set to "hide and reopen" without [Platform.implicitExit] = false, // Stage.show() cannot work again because JavaFX Toolkit have already shut down. Platform.setImplicitExit(false) Controllers.initialize(stage) + println("Showing stage: " + System.currentTimeMillis()) + stage.isResizable = false stage.scene = Controllers.scene stage.show() + println("Showed stage: " + System.currentTimeMillis()) } companion object { diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/game/HMCLGameRepository.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/game/HMCLGameRepository.kt index a4e963ea0..8ccd8c080 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/game/HMCLGameRepository.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/game/HMCLGameRepository.kt @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.setting.EnumGameDirectory import org.jackhuang.hmcl.setting.Profile import org.jackhuang.hmcl.setting.Settings import org.jackhuang.hmcl.setting.VersionSetting +import org.jackhuang.hmcl.task.Scheduler import org.jackhuang.hmcl.util.LOG import org.jackhuang.hmcl.util.fromJson import java.io.File @@ -68,30 +69,29 @@ class HMCLGameRepository(val profile: Profile, baseDirectory: File) return File(Settings.commonPath).resolve("libraries/${lib.path}") } + @Synchronized override fun refreshVersionsImpl() { - versionSettings.clear() + Scheduler.NEW_THREAD.schedule { + versionSettings.clear() - super.refreshVersionsImpl() + super.refreshVersionsImpl() - versions.keys.forEach(this::loadVersionSetting) + versions.keys.forEach(this::loadVersionSetting) - checkModpack() + checkModpack() - try { - val file = baseDirectory.resolve("launcher_profiles.json") - if (!file.exists() && versions.isNotEmpty()) - file.writeText(PROFILE) - } catch (ex: IOException) { - LOG.log(Level.WARNING, "Unable to create launcher_profiles.json, Forge/LiteLoader installer will not work.", ex) + try { + val file = baseDirectory.resolve("launcher_profiles.json") + if (!file.exists() && versions.isNotEmpty()) + file.writeText(PROFILE) + } catch (ex: IOException) { + LOG.log(Level.WARNING, "Unable to create launcher_profiles.json, Forge/LiteLoader installer will not work.", ex) + } } - } fun changeDirectory(newDir: File) { baseDirectory = newDir - - - refreshVersions() } diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Profile.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Profile.kt index 76151aaf5..2d4fb2166 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Profile.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/Profile.kt @@ -47,11 +47,7 @@ class Profile(name: String = "Default", initialGameDir: File = File(".minecraft" var modManager = ModManager(repository) init { - gameDirProperty.onChange { newGameDir -> - repository.baseDirectory = newGameDir!! - repository.refreshVersions() - } - + gameDirProperty.onChange { repository.changeDirectory(it!!) } selectedVersionProperty.addListener { _ -> verifySelectedVersion() } EVENT_BUS.channel() += { event -> if (event.source == repository) verifySelectedVersion() } } diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/VersionSetting.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/VersionSetting.kt index 2550e410e..182026c02 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/VersionSetting.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/setting/VersionSetting.kt @@ -191,7 +191,7 @@ class VersionSetting() { return null // Custom Java Directory not found, } } else if (java.isNotBlank()) { - val c = JavaVersion.JAVAS[java] + val c = JavaVersion.getJREs()[java] if (c == null) { java = "Default" return JavaVersion.fromCurrentEnvironment() diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/Controllers.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/Controllers.kt index 002b4bee2..8e9f2d30f 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/Controllers.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/Controllers.kt @@ -25,14 +25,16 @@ import javafx.scene.layout.Region import javafx.stage.Stage import org.jackhuang.hmcl.Main import org.jackhuang.hmcl.setting.Settings +import org.jackhuang.hmcl.task.task +import org.jackhuang.hmcl.util.JavaVersion object Controllers { lateinit var scene: Scene private set lateinit var stage: Stage private set val mainPane = MainPage() - val settingsPane = SettingsPage() - val versionPane = VersionPage() + val settingsPane by lazy { SettingsPage() } + val versionPane by lazy { VersionPage() } lateinit var leftPaneController: LeftPaneController @@ -46,6 +48,7 @@ object Controllers { leftPaneController = LeftPaneController(decorator.leftPane) Settings.onProfileLoading() + task { JavaVersion.initialize() }.start() decorator.isCustomMaximize = false diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/ModItem.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/ModItem.kt index f1fe947d4..f200fe2c5 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/ModItem.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/ModItem.kt @@ -17,21 +17,38 @@ */ package org.jackhuang.hmcl.ui +import com.jfoenix.controls.JFXButton import com.jfoenix.controls.JFXCheckBox import com.jfoenix.effects.JFXDepthManager -import javafx.fxml.FXML +import javafx.geometry.Pos import javafx.scene.control.Label import javafx.scene.layout.BorderPane +import javafx.scene.layout.VBox import org.jackhuang.hmcl.mod.ModInfo import org.jackhuang.hmcl.util.onChange class ModItem(info: ModInfo, private val deleteCallback: (ModItem) -> Unit) : BorderPane() { - @FXML lateinit var lblModFileName: Label - @FXML lateinit var lblModAuthor: Label - @FXML lateinit var chkEnabled: JFXCheckBox + val lblModFileName = Label().apply { style = "-fx-font-size: 15;" } + val lblModAuthor = Label().apply { style = "-fx-font-size: 10;" } + val chkEnabled = JFXCheckBox().apply { BorderPane.setAlignment(this, Pos.CENTER) } init { - loadFXML("/assets/fxml/version/mod-item.fxml") + left = chkEnabled + + center = VBox().apply { + BorderPane.setAlignment(this, Pos.CENTER) + + children += lblModFileName + children += lblModAuthor + } + + right = JFXButton().apply { + setOnMouseClicked { onDelete() } + styleClass += "toggle-icon4" + + BorderPane.setAlignment(this, Pos.CENTER) + graphic = SVG.close("black", 15.0, 15.0) + } style = "-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;" JFXDepthManager.setDepth(this, 1) diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/VersionSettingsController.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/VersionSettingsController.kt index 2c082a4de..1de521e5a 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/VersionSettingsController.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/VersionSettingsController.kt @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui import com.jfoenix.controls.* import javafx.beans.value.ChangeListener import javafx.fxml.FXML +import javafx.scene.Node import javafx.scene.control.Label import javafx.scene.control.ScrollPane import javafx.scene.control.Toggle @@ -106,16 +107,22 @@ class VersionSettingsController { txtMetaspace.setValidators(validator(true)) txtMetaspace.setValidateWhileTextChanged() - javaPane.children.clear() - javaPane.children += createJavaPane(JavaVersion.fromCurrentEnvironment(), javaGroup) - JavaVersion.JAVAS.values.forEach { javaVersion -> - javaPane.children += createJavaPane(javaVersion, javaGroup) - } - javaPane.children += javaPaneCustom javaPaneCustom.limitHeight(20.0) radioCustom.toggleGroup = javaGroup txtJavaDir.disableProperty().bind(radioCustom.selectedProperty().not()) btnJavaSelect.disableProperty().bind(radioCustom.selectedProperty().not()) + + task { + val list = mutableListOf() + list += createJavaPane(JavaVersion.fromCurrentEnvironment(), javaGroup) + JavaVersion.getJREs().values.forEach { javaVersion -> + list += createJavaPane(javaVersion, javaGroup) + } + list += javaPaneCustom + it["list"] = list + }.subscribe(Scheduler.JAVAFX) { + javaPane.children.setAll(it.get>("list")) + } } private fun createJavaPane(java: JavaVersion, group: ToggleGroup): Pane { diff --git a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/download/InstallWizardProvider.kt b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/download/InstallWizardProvider.kt index 127bf7b30..994af127e 100644 --- a/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/download/InstallWizardProvider.kt +++ b/HMCL/src/main/kotlin/org/jackhuang/hmcl/ui/download/InstallWizardProvider.kt @@ -35,7 +35,7 @@ class InstallWizardProvider(val profile: Profile, val gameVersion: String, val v if (settings.containsKey("optifine")) ret = ret with profile.dependency.installLibraryAsync(gameVersion, version, "optifine", settings["optifine"] as String) - return ret with task(Scheduler.JAVAFX) { profile.repository.refreshVersions() } + return ret with task { profile.repository.refreshVersions() } } override fun createPage(controller: WizardController, step: Int, settings: MutableMap): Node { diff --git a/HMCL/src/main/resources/assets/fxml/version/mod-item.fxml b/HMCL/src/main/resources/assets/fxml/version/mod-item.fxml deleted file mode 100644 index 08fd28b54..000000000 --- a/HMCL/src/main/resources/assets/fxml/version/mod-item.fxml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - -
- - -
- - - - - - - -
diff --git a/HMCL/src/main/resources/assets/fxml/version/mod.fxml b/HMCL/src/main/resources/assets/fxml/version/mod.fxml index ea32b55c8..f5b6f51a6 100644 --- a/HMCL/src/main/resources/assets/fxml/version/mod.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/mod.fxml @@ -12,7 +12,7 @@ - + diff --git a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/game/DefaultGameRepository.kt b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/game/DefaultGameRepository.kt index dc793ebf2..1ef78ebe8 100644 --- a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/game/DefaultGameRepository.kt +++ b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/game/DefaultGameRepository.kt @@ -140,7 +140,6 @@ open class DefaultGameRepository(var baseDirectory: File): GameRepository { isLoaded = true } - @Synchronized final override fun refreshVersions() { EVENT_BUS.fireEvent(RefreshingVersionsEvent(this)) refreshVersionsImpl() diff --git a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/util/JavaVersion.kt b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/util/JavaVersion.kt index e0bf7e33f..82ab5512f 100644 --- a/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/util/JavaVersion.kt +++ b/HMCLCore/src/main/kotlin/org/jackhuang/hmcl/util/JavaVersion.kt @@ -18,10 +18,12 @@ package org.jackhuang.hmcl.util import com.google.gson.annotations.SerializedName +import org.jackhuang.hmcl.game.Version import java.io.File import java.io.IOException import java.io.Serializable import java.util.* +import java.util.concurrent.CountDownLatch import java.util.regex.Pattern /** @@ -49,8 +51,6 @@ data class JavaVersion internal constructor( companion object { private val regex = Pattern.compile("java version \"(?[1-9]*\\.[1-9]*\\.[0-9]*(.*?))\"") - val JAVAS: Map - val UNKNOWN: Int = -1 val JAVA_5: Int = 50 val JAVA_6: Int = 60 @@ -132,7 +132,22 @@ data class JavaVersion internal constructor( } fun fromCurrentEnvironment() = currentJava - init { + private var javas: Map? = null + private val await = CountDownLatch(1) + + /** + * This method will block until [initialize] succeeds. + */ + fun getJREs(): Map { + if (javas != null) return javas!! + await.await() + return javas!! + } + + @Synchronized + fun initialize() { + if (javas != null) + throw IllegalStateException("JavaVersions have already been initialized.") val temp = mutableMapOf() (when (OS.CURRENT_OS) { OS.WINDOWS -> queryWindows() @@ -141,7 +156,8 @@ data class JavaVersion internal constructor( }).forEach { javaVersion -> temp.put(javaVersion.longVersion, javaVersion) } - JAVAS = temp + javas = temp + await.countDown() } private fun queryMacintosh() = LinkedList().apply {