Added custom game directory. Closes #199

This commit is contained in:
huanghongxun 2017-09-04 15:55:18 +08:00
parent 41337f66a8
commit 5f7f885d99
15 changed files with 207 additions and 114 deletions

View File

@ -56,6 +56,7 @@ class HMCLGameRepository(val profile: Profile, baseDirectory: File)
return when (vs.gameDirType) { return when (vs.gameDirType) {
EnumGameDirectory.VERSION_FOLDER -> getVersionRoot(id) EnumGameDirectory.VERSION_FOLDER -> getVersionRoot(id)
EnumGameDirectory.ROOT_FOLDER -> super.getRunDirectory(id) EnumGameDirectory.ROOT_FOLDER -> super.getRunDirectory(id)
EnumGameDirectory.CUSTOM -> File(vs.gameDir)
} }
} }
} }

View File

@ -19,5 +19,6 @@ package org.jackhuang.hmcl.setting
enum class EnumGameDirectory { enum class EnumGameDirectory {
ROOT_FOLDER, ROOT_FOLDER,
VERSION_FOLDER VERSION_FOLDER,
CUSTOM
} }

View File

@ -166,9 +166,15 @@ class VersionSetting() {
* 0 - .minecraft<br/> * 0 - .minecraft<br/>
* 1 - .minecraft/versions/&lt;version&gt;/<br/> * 1 - .minecraft/versions/&lt;version&gt;/<br/>
*/ */
val gameDirTypeProperty = ImmediateObjectProperty<EnumGameDirectory>(this, "gameDirTypeProperty", EnumGameDirectory.ROOT_FOLDER) val gameDirTypeProperty = ImmediateObjectProperty<EnumGameDirectory>(this, "gameDirType", EnumGameDirectory.ROOT_FOLDER)
var gameDirType: EnumGameDirectory by gameDirTypeProperty var gameDirType: EnumGameDirectory by gameDirTypeProperty
/**
* Your custom gameDir
*/
val gameDirProperty = ImmediateStringProperty(this, "gameDir", "")
var gameDir: String by gameDirProperty
// launcher settings // launcher settings
/** /**
@ -220,6 +226,7 @@ class VersionSetting() {
widthProperty.addListener(listener) widthProperty.addListener(listener)
heightProperty.addListener(listener) heightProperty.addListener(listener)
gameDirTypeProperty.addListener(listener) gameDirTypeProperty.addListener(listener)
gameDirProperty.addListener(listener)
launcherVisibilityProperty.addListener(listener) launcherVisibilityProperty.addListener(listener)
} }
@ -272,6 +279,7 @@ class VersionSetting() {
addProperty("notCheckGame", src.notCheckGame) addProperty("notCheckGame", src.notCheckGame)
addProperty("noCommon", src.noCommon) addProperty("noCommon", src.noCommon)
addProperty("showLogs", src.showLogs) addProperty("showLogs", src.showLogs)
addProperty("gameDir", src.gameDir)
addProperty("launcherVisibility", src.launcherVisibility.ordinal) addProperty("launcherVisibility", src.launcherVisibility.ordinal)
addProperty("gameDirType", src.gameDirType.ordinal) addProperty("gameDirType", src.gameDirType.ordinal)
} }
@ -299,6 +307,7 @@ class VersionSetting() {
serverIp = json["serverIp"]?.asString ?: "" serverIp = json["serverIp"]?.asString ?: ""
java = json["java"]?.asString ?: "" java = json["java"]?.asString ?: ""
wrapper = json["wrapper"]?.asString ?: "" wrapper = json["wrapper"]?.asString ?: ""
gameDir = json["gameDir"]?.asString ?: ""
fullscreen = json["fullscreen"]?.asBoolean ?: false fullscreen = json["fullscreen"]?.asBoolean ?: false
noJVMArgs = json["noJVMArgs"]?.asBoolean ?: false noJVMArgs = json["noJVMArgs"]?.asBoolean ?: false
notCheckGame = json["notCheckGame"]?.asBoolean ?: false notCheckGame = json["notCheckGame"]?.asBoolean ?: false

View File

@ -61,4 +61,5 @@ object SVG {
fun launch(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M1008 6.286q18.857 13.714 15.429 36.571l-146.286 877.714q-2.857 16.571-18.286 25.714-8 4.571-17.714 4.571-6.286 0-13.714-2.857l-258.857-105.714-138.286 168.571q-10.286 13.143-28 13.143-7.429 0-12.571-2.286-10.857-4-17.429-13.429t-6.571-20.857v-199.429l493.714-605.143-610.857 528.571-225.714-92.571q-21.143-8-22.857-31.429-1.143-22.857 18.286-33.714l950.857-548.571q8.571-5.143 18.286-5.14311.429 0 20.571 6.286z", fill, width, height) fun launch(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M1008 6.286q18.857 13.714 15.429 36.571l-146.286 877.714q-2.857 16.571-18.286 25.714-8 4.571-17.714 4.571-6.286 0-13.714-2.857l-258.857-105.714-138.286 168.571q-10.286 13.143-28 13.143-7.429 0-12.571-2.286-10.857-4-17.429-13.429t-6.571-20.857v-199.429l493.714-605.143-610.857 528.571-225.714-92.571q-21.143-8-22.857-31.429-1.143-22.857 18.286-33.714l950.857-548.571q8.571-5.143 18.286-5.14311.429 0 20.571 6.286z", fill, width, height)
fun pencil(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M20.71,4.04C21.1,3.65 21.1,3 20.71,2.63L18.37,0.29C18,-0.1 17.35,-0.1 16.96,0.29L15,2.25L18.75,6M17.75,7L14,3.25L4,13.25V17H7.75L17.75,7Z", fill, width, height) fun pencil(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M20.71,4.04C21.1,3.65 21.1,3 20.71,2.63L18.37,0.29C18,-0.1 17.35,-0.1 16.96,0.29L15,2.25L18.75,6M17.75,7L14,3.25L4,13.25V17H7.75L17.75,7Z", fill, width, height)
fun refresh(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z", fill, width, height) fun refresh(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z", fill, width, height)
fun folderOpen(fill: String = "white", width: Double = 20.0, height: Double = 20.0) = createSVGPath("M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z", fill, width, height)
} }

View File

@ -33,11 +33,13 @@ import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser import javafx.stage.DirectoryChooser
import javafx.stage.FileChooser import javafx.stage.FileChooser
import org.jackhuang.hmcl.i18n import org.jackhuang.hmcl.i18n
import org.jackhuang.hmcl.setting.EnumGameDirectory
import org.jackhuang.hmcl.setting.Profile import org.jackhuang.hmcl.setting.Profile
import org.jackhuang.hmcl.setting.VersionSetting import org.jackhuang.hmcl.setting.VersionSetting
import org.jackhuang.hmcl.task.Scheduler import org.jackhuang.hmcl.task.Scheduler
import org.jackhuang.hmcl.task.task import org.jackhuang.hmcl.task.task
import org.jackhuang.hmcl.ui.construct.ComponentList import org.jackhuang.hmcl.ui.construct.ComponentList
import org.jackhuang.hmcl.ui.construct.MultiFileItem
import org.jackhuang.hmcl.ui.construct.NumberValidator import org.jackhuang.hmcl.ui.construct.NumberValidator
import org.jackhuang.hmcl.util.JavaVersion import org.jackhuang.hmcl.util.JavaVersion
import org.jackhuang.hmcl.util.OS import org.jackhuang.hmcl.util.OS
@ -55,20 +57,15 @@ class VersionSettingsController {
@FXML lateinit var txtWrapper: JFXTextField @FXML lateinit var txtWrapper: JFXTextField
@FXML lateinit var txtPrecallingCommand: JFXTextField @FXML lateinit var txtPrecallingCommand: JFXTextField
@FXML lateinit var txtServerIP: JFXTextField @FXML lateinit var txtServerIP: JFXTextField
@FXML lateinit var txtJavaDir: JFXTextField
@FXML lateinit var advancedSettingsPane: ComponentList @FXML lateinit var advancedSettingsPane: ComponentList
@FXML lateinit var cboLauncherVisibility: JFXComboBox<*> @FXML lateinit var cboLauncherVisibility: JFXComboBox<*>
@FXML lateinit var cboRunDirectory: JFXComboBox<*>
@FXML lateinit var chkFullscreen: JFXCheckBox @FXML lateinit var chkFullscreen: JFXCheckBox
@FXML lateinit var lblPhysicalMemory: Label @FXML lateinit var lblPhysicalMemory: Label
@FXML lateinit var chkNoJVMArgs: JFXToggleButton @FXML lateinit var chkNoJVMArgs: JFXToggleButton
@FXML lateinit var chkNoCommon: JFXToggleButton @FXML lateinit var chkNoCommon: JFXToggleButton
@FXML lateinit var chkNoGameCheck: JFXToggleButton @FXML lateinit var chkNoGameCheck: JFXToggleButton
@FXML lateinit var componentJava: ComponentList @FXML lateinit var javaItem: MultiFileItem
@FXML lateinit var javaPane: VBox @FXML lateinit var gameDirItem: MultiFileItem
@FXML lateinit var javaPaneCustom: BorderPane
@FXML lateinit var radioCustom: JFXRadioButton
@FXML lateinit var btnJavaSelect: JFXButton
@FXML lateinit var chkShowLogs: JFXToggleButton @FXML lateinit var chkShowLogs: JFXToggleButton
@FXML lateinit var btnIconSelection: JFXButton @FXML lateinit var btnIconSelection: JFXButton
@FXML lateinit var iconView: ImageView @FXML lateinit var iconView: ImageView
@ -76,9 +73,6 @@ class VersionSettingsController {
lateinit var profile: Profile lateinit var profile: Profile
lateinit var versionId: String lateinit var versionId: String
val javaGroup = ToggleGroup()
fun initialize() { fun initialize() {
lblPhysicalMemory.text = i18n("settings.physical_memory") + ": ${OS.TOTAL_MEMORY}MB" lblPhysicalMemory.text = i18n("settings.physical_memory") + ": ${OS.TOTAL_MEMORY}MB"
@ -88,7 +82,6 @@ class VersionSettingsController {
//txtJavaDir.limitWidth(limit) //txtJavaDir.limitWidth(limit)
txtMaxMemory.limitWidth(limit) txtMaxMemory.limitWidth(limit)
cboLauncherVisibility.limitWidth(limit) cboLauncherVisibility.limitWidth(limit)
cboRunDirectory.limitWidth(limit)
val limitHeight = 10.0 val limitHeight = 10.0
chkNoJVMArgs.limitHeight(limitHeight) chkNoJVMArgs.limitHeight(limitHeight)
@ -107,37 +100,18 @@ class VersionSettingsController {
txtMetaspace.setValidators(validator(true)) txtMetaspace.setValidators(validator(true))
txtMetaspace.setValidateWhileTextChanged() txtMetaspace.setValidateWhileTextChanged()
javaPaneCustom.limitHeight(20.0)
radioCustom.toggleGroup = javaGroup
txtJavaDir.disableProperty().bind(radioCustom.selectedProperty().not())
btnJavaSelect.disableProperty().bind(radioCustom.selectedProperty().not())
task { task {
val list = mutableListOf<Node>() it["list"] = JavaVersion.getJREs().values.map { javaVersion ->
list += createJavaPane(JavaVersion.fromCurrentEnvironment(), javaGroup) javaItem.createChildren(javaVersion.longVersion, javaVersion.binary.absolutePath, javaVersion)
JavaVersion.getJREs().values.forEach { javaVersion ->
list += createJavaPane(javaVersion, javaGroup)
} }
list += javaPaneCustom
it["list"] = list
}.subscribe(Scheduler.JAVAFX) { }.subscribe(Scheduler.JAVAFX) {
javaPane.children.setAll(it.get<List<Node>>("list")) javaItem.loadChildren(it.get<Collection<Node>>("list"))
} }
}
private fun createJavaPane(java: JavaVersion, group: ToggleGroup): Pane { gameDirItem.loadChildren(listOf(
return BorderPane().apply { gameDirItem.createChildren(i18n("advancedsettings.game_dir.default"), userData = EnumGameDirectory.ROOT_FOLDER),
style = "-fx-padding: 3;" gameDirItem.createChildren(i18n("advancedsettings.game_dir.independent"), userData = EnumGameDirectory.VERSION_FOLDER)
limitHeight(20.0) ))
left = JFXRadioButton(java.longVersion).apply {
toggleGroup = group
userData = java
}
right = Label(java.binary.absolutePath).apply {
styleClass += "subtitle-label"
style += "-fx-font-size: 10;"
}
}
} }
fun loadVersionSetting(profile: Profile, versionId: String, version: VersionSetting) { fun loadVersionSetting(profile: Profile, versionId: String, version: VersionSetting) {
@ -162,13 +136,13 @@ class VersionSettingsController {
javaDirProperty.unbind() javaDirProperty.unbind()
showLogsProperty.unbind() showLogsProperty.unbind()
unbindEnum(cboLauncherVisibility) unbindEnum(cboLauncherVisibility)
unbindEnum(cboRunDirectory)
} }
bindInt(txtWidth, version.widthProperty) bindInt(txtWidth, version.widthProperty)
bindInt(txtHeight, version.heightProperty) bindInt(txtHeight, version.heightProperty)
bindInt(txtMaxMemory, version.maxMemoryProperty) bindInt(txtMaxMemory, version.maxMemoryProperty)
bindString(txtJavaDir, version.javaDirProperty) bindString(javaItem.txtCustom, version.javaDirProperty)
bindString(gameDirItem.txtCustom, version.gameDirProperty)
bindString(txtJVMArgs, version.javaArgsProperty) bindString(txtJVMArgs, version.javaArgsProperty)
bindString(txtGameArgs, version.minecraftArgsProperty) bindString(txtGameArgs, version.minecraftArgsProperty)
bindString(txtMetaspace, version.permSizeProperty) bindString(txtMetaspace, version.permSizeProperty)
@ -176,7 +150,6 @@ class VersionSettingsController {
bindString(txtPrecallingCommand, version.precalledCommandProperty) bindString(txtPrecallingCommand, version.precalledCommandProperty)
bindString(txtServerIP, version.serverIpProperty) bindString(txtServerIP, version.serverIpProperty)
bindEnum(cboLauncherVisibility, version.launcherVisibilityProperty) bindEnum(cboLauncherVisibility, version.launcherVisibilityProperty)
bindEnum(cboRunDirectory, version.gameDirTypeProperty)
bindBoolean(chkFullscreen, version.fullscreenProperty) bindBoolean(chkFullscreen, version.fullscreenProperty)
bindBoolean(chkNoGameCheck, version.notCheckGameProperty) bindBoolean(chkNoGameCheck, version.notCheckGameProperty)
bindBoolean(chkNoCommon, version.noCommonProperty) bindBoolean(chkNoCommon, version.noCommonProperty)
@ -184,29 +157,30 @@ class VersionSettingsController {
val javaGroupKey = "java_group.listener" val javaGroupKey = "java_group.listener"
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
if (javaGroup.properties.containsKey(javaGroupKey)) (javaItem.group.properties[javaGroupKey] as? ChangeListener<in Toggle>?)
javaGroup.selectedToggleProperty().removeListener(javaGroup.properties[javaGroupKey] as ChangeListener<in Toggle>) ?.run(javaItem.group.selectedToggleProperty()::removeListener)
var flag = false var flag = false
var defaultToggle: JFXRadioButton? = null var defaultToggle: JFXRadioButton? = null
for (toggle in javaGroup.toggles) var customToggle = javaItem.radioCustom
if (toggle is JFXRadioButton) javaItem.group.toggles.filter { it is JFXRadioButton }.forEach { toggle ->
if (toggle.userData == version.javaVersion) { if (toggle.userData == version.javaVersion) {
toggle.isSelected = true toggle.isSelected = true
flag = true flag = true
} else if (toggle.userData == JavaVersion.fromCurrentEnvironment()) { } else if (toggle.userData == JavaVersion.fromCurrentEnvironment()) {
defaultToggle = toggle defaultToggle = toggle as JFXRadioButton
} }
}
val listener = ChangeListener<Toggle> { _, _, newValue -> val listener = ChangeListener<Toggle> { _, _, newValue ->
if (newValue == radioCustom) { // Custom if (newValue == javaItem.radioCustom) { // Custom
version.java = "Custom" version.java = "Custom"
} else { } else {
version.java = ((newValue as JFXRadioButton).userData as JavaVersion).longVersion version.java = ((newValue as JFXRadioButton).userData as JavaVersion).longVersion
} }
} }
javaGroup.properties[javaGroupKey] = listener javaItem.group.properties[javaGroupKey] = listener
javaGroup.selectedToggleProperty().addListener(listener) javaItem.group.selectedToggleProperty().addListener(listener)
if (!flag) { if (!flag) {
defaultToggle?.isSelected = true defaultToggle?.isSelected = true
@ -216,6 +190,30 @@ class VersionSettingsController {
version.javaProperty.setChangedListener { initJavaSubtitle(version) } version.javaProperty.setChangedListener { initJavaSubtitle(version) }
initJavaSubtitle(version) initJavaSubtitle(version)
val gameDirKey = "game_dir.listener"
@Suppress("UNCHECKED_CAST")
(gameDirItem.group.properties[gameDirKey] as? ChangeListener<in Toggle>?)
?.run(gameDirItem.group.selectedToggleProperty()::removeListener)
gameDirItem.group.toggles.filter { it is JFXRadioButton }.forEach { toggle ->
if (toggle.userData == version.gameDirType) {
toggle.isSelected = true
flag = true
}
}
gameDirItem.radioCustom.userData = EnumGameDirectory.CUSTOM
val gameDirListener = ChangeListener<Toggle> { _, _, newValue ->
version.gameDirType = (newValue as JFXRadioButton).userData as EnumGameDirectory
}
gameDirItem.group.properties[gameDirKey] = gameDirListener
gameDirItem.group.selectedToggleProperty().addListener(gameDirListener)
version.gameDirProperty.setChangedListener { initGameDirSubtitle(version) }
version.gameDirTypeProperty.setChangedListener { initGameDirSubtitle(version) }
initGameDirSubtitle(version)
lastVersionSetting = version lastVersionSetting = version
loadIcon() loadIcon()
@ -223,7 +221,11 @@ class VersionSettingsController {
private fun initJavaSubtitle(version: VersionSetting) { private fun initJavaSubtitle(version: VersionSetting) {
task { it["java"] = version.javaVersion } task { it["java"] = version.javaVersion }
.subscribe(task(Scheduler.JAVAFX) { componentJava.subtitle = it.get<JavaVersion?>("java")?.binary?.absolutePath ?: "Invalid Java Directory" }) .subscribe(task(Scheduler.JAVAFX) { javaItem.subtitle = it.get<JavaVersion?>("java")?.binary?.absolutePath ?: "Invalid Java Directory" })
}
private fun initGameDirSubtitle(version: VersionSetting) {
gameDirItem.subtitle = profile.repository.getRunDirectory(versionId).absolutePath
} }
fun onShowAdvanced() { fun onShowAdvanced() {
@ -233,14 +235,6 @@ class VersionSettingsController {
rootPane.children.remove(advancedSettingsPane) rootPane.children.remove(advancedSettingsPane)
} }
fun onExploreJavaDir() {
val chooser = DirectoryChooser()
chooser.title = i18n("settings.choose_javapath")
val selectedDir = chooser.showDialog(Controllers.stage)
if (selectedDir != null)
txtJavaDir.text = selectedDir.absolutePath
}
fun onExploreIcon() { fun onExploreIcon() {
val chooser = FileChooser() val chooser = FileChooser()
chooser.extensionFilters += FileChooser.ExtensionFilter("Image", "*.png") chooser.extensionFilters += FileChooser.ExtensionFilter("Image", "*.png")

View File

@ -32,9 +32,9 @@ import kotlin.collections.plusAssign
import kotlin.collections.set import kotlin.collections.set
@DefaultProperty("content") @DefaultProperty("content")
class ComponentList: StackPane() { open class ComponentList: StackPane() {
val vbox: VBox val vbox = VBox()
val content: ObservableList<Node> = FXCollections.observableArrayList<Node>().apply { val content: ObservableList<Node> = FXCollections.observableArrayList<Node>().apply {
addListener { change: ListChangeListener.Change<out Node> -> addListener { change: ListChangeListener.Change<out Node> ->
@ -47,8 +47,6 @@ class ComponentList: StackPane() {
} }
init { init {
vbox = VBox().apply {
}
children.setAll(vbox) children.setAll(vbox)
styleClass += "options-list" styleClass += "options-list"

View File

@ -0,0 +1,111 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
*
* 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.ui.construct
import com.jfoenix.controls.JFXButton
import com.jfoenix.controls.JFXRadioButton
import com.jfoenix.controls.JFXTextField
import javafx.beans.property.SimpleStringProperty
import javafx.geometry.Pos
import javafx.scene.Node
import javafx.scene.control.Label
import javafx.scene.control.ToggleGroup
import javafx.scene.layout.BorderPane
import javafx.scene.layout.HBox
import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser
import org.jackhuang.hmcl.i18n
import org.jackhuang.hmcl.ui.Controllers
import org.jackhuang.hmcl.ui.SVG
import org.jackhuang.hmcl.ui.limitHeight
import org.jackhuang.hmcl.util.*
class MultiFileItem : ComponentList() {
val customTextProperty = SimpleStringProperty(this, "customText", "Custom")
var customText by customTextProperty
val chooserTitleProperty = SimpleStringProperty(this, "chooserTitle", "Select a file")
var chooserTitle by chooserTitleProperty
val group = ToggleGroup()
val txtCustom = JFXTextField().apply {
BorderPane.setAlignment(this, Pos.CENTER_RIGHT)
}
val btnSelect = JFXButton().apply {
graphic = SVG.folderOpen("black", 15.0, 15.0)
setOnMouseClicked {
// TODO
}
}
val radioCustom = JFXRadioButton().apply {
textProperty().bind(customTextProperty)
toggleGroup = group
}
val custom = BorderPane().apply {
left = radioCustom
style = "-fx-padding: 3;"
right = HBox().apply {
spacing = 3.0
children += txtCustom
children += btnSelect
}
limitHeight(20.0)
}
val pane = VBox().apply {
style = "-fx-padding: 0 0 10 0;"
spacing = 8.0
children += custom
}
init {
addChildren(pane)
txtCustom.disableProperty().bind(radioCustom.selectedProperty().not())
btnSelect.disableProperty().bind(radioCustom.selectedProperty().not())
}
@JvmOverloads
fun createChildren(title: String, subtitle: String = "", userData: Any? = null): Node {
return BorderPane().apply {
style = "-fx-padding: 3;"
limitHeight(20.0)
left = JFXRadioButton(title).apply {
toggleGroup = group
this.userData = userData
}
right = Label(subtitle).apply {
styleClass += "subtitle-label"
style += "-fx-font-size: 10;"
}
}
}
fun loadChildren(list: Collection<Node>) {
pane.children.setAll(list)
pane.children += custom
}
fun onExploreJavaDir() {
val chooser = DirectoryChooser()
chooser.title = i18n(chooserTitle)
val selectedDir = chooser.showDialog(Controllers.stage)
if (selectedDir != null)
txtCustom.text = selectedDir.absolutePath
}
}

View File

@ -8,6 +8,7 @@
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.jackhuang.hmcl.ui.construct.ComponentList?> <?import org.jackhuang.hmcl.ui.construct.ComponentList?>
<?import org.jackhuang.hmcl.ui.construct.MultiFileItem?>
<StackPane xmlns="http://javafx.com/javafx" <StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
fx:controller="org.jackhuang.hmcl.ui.VersionSettingsController"> fx:controller="org.jackhuang.hmcl.ui.VersionSettingsController">
@ -37,26 +38,11 @@
</right> </right>
</BorderPane> </BorderPane>
<ComponentList fx:id="componentJava" title="%settings.java_dir" <MultiFileItem fx:id="javaItem" title="%settings.java_dir" chooserTitle="%settings.choose_javapath"
hasSubtitle="true"> <!-- Java Directory --> hasSubtitle="true" customText="%settings.custom" />
<VBox fx:id="javaPane" spacing="8" style="-fx-padding: 0 0 10 0;">
<BorderPane fx:id="javaPaneCustom" style="-fx-padding: 3;"> <MultiFileItem fx:id="gameDirItem" title="%settings.game_directory" chooserTitle="%settings.choose_gamedir"
<left> hasSubtitle="true" customText="%settings.custom" />
<JFXRadioButton fx:id="radioCustom" text="%settings.custom"/>
</left>
<right>
<HBox spacing="3">
<JFXTextField fx:id="txtJavaDir" BorderPane.alignment="CENTER_RIGHT"/>
<JFXButton fx:id="btnJavaSelect" onMouseClicked="#onExploreJavaDir">
<graphic>
<fx:include source="/assets/svg/folder-open.fxml"/>
</graphic>
</JFXButton>
</HBox>
</right>
</BorderPane>
</VBox>
</ComponentList>
<BorderPane> <!-- Max Memory --> <BorderPane> <!-- Max Memory -->
<left> <left>
@ -88,22 +74,6 @@
</right> </right>
</BorderPane> </BorderPane>
<BorderPane> <!-- Run Directory -->
<left>
<Label text="%settings.run_directory" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right>
<JFXComboBox fx:id="cboRunDirectory" BorderPane.alignment="CENTER_RIGHT">
<items>
<FXCollections fx:factory="observableArrayList">
<Label text="%advancedsettings.game_dir.default"/>
<Label text="%advancedsettings.game_dir.independent"/>
</FXCollections>
</items>
</JFXComboBox>
</right>
</BorderPane>
<BorderPane> <!-- Dimension --> <BorderPane> <!-- Dimension -->
<left> <left>
<Label text="%settings.dimension" BorderPane.alignment="CENTER_LEFT"/> <Label text="%settings.dimension" BorderPane.alignment="CENTER_LEFT"/>

View File

@ -163,7 +163,7 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
} }
// Optional Minecraft arguments // Optional Minecraft arguments
if (options.height != null && options.width != null) { if (options.height != null && options.height != 0 && options.width != null && options.width != 0) {
res.add("--height") res.add("--height")
res.add(options.height.toString()) res.add(options.height.toString())
res.add("--width") res.add("--width")

View File

@ -149,6 +149,7 @@ data class JavaVersion internal constructor(
if (javas != null) if (javas != null)
throw IllegalStateException("JavaVersions have already been initialized.") throw IllegalStateException("JavaVersions have already been initialized.")
val temp = mutableMapOf<String, JavaVersion>() val temp = mutableMapOf<String, JavaVersion>()
temp += currentJava.longVersion to currentJava
(when (OS.CURRENT_OS) { (when (OS.CURRENT_OS) {
OS.WINDOWS -> queryWindows() OS.WINDOWS -> queryWindows()
OS.OSX -> queryMacintosh() OS.OSX -> queryMacintosh()

View File

@ -34,3 +34,11 @@ fun <T> ObservableList<T>.onChange(op: (ListChangeListener.Change<out T>) -> Uni
} }
fun <T> ObservableValue<*>.onInvalidated(op: () -> T) = apply { addListener { _ -> op() } } fun <T> ObservableValue<*>.onInvalidated(op: () -> T) = apply { addListener { _ -> op() } }
fun <T> ObservableValue<T>.setOnChangeListener(properties: MutableMap<Any, Any>, key: String = "changeListener", changeListener: ChangeListener<in T>) {
@Suppress("UNCHECKED_CAST")
if (properties.containsKey(key))
removeListener(properties[key] as ChangeListener<in T>)
properties[key] = changeListener
addListener(changeListener)
}

Binary file not shown.

View File

@ -1,6 +1,5 @@
#Wed Jul 19 17:02:19 CST 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip

8
gradlew vendored
View File

@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
warn ( ) { warn () {
echo "$*" echo "$*"
} }
die ( ) { die () {
echo echo
echo "$*" echo "$*"
echo echo
@ -155,7 +155,7 @@ if $cygwin ; then
fi fi
# Escape application args # Escape application args
save ( ) { save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }
@ -164,7 +164,7 @@ APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules # Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when execute from Finder on Mac, the cwd is wrong # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")" cd "$(dirname "$0")"
fi fi

4
gradlew.bat vendored
View File

@ -5,7 +5,7 @@
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables then windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
@ -69,7 +69,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end :end
@rem End local scope for the variables then windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if "%ERRORLEVEL%"=="0" goto mainEnd
:fail :fail