Icon selection

This commit is contained in:
huangyuhui
2017-08-25 08:54:33 +08:00
parent f532df20e6
commit 833247d133
16 changed files with 276 additions and 109 deletions

View File

@@ -17,6 +17,7 @@
*/ */
package org.jackhuang.hmcl.game package org.jackhuang.hmcl.game
import javafx.geometry.Rectangle2D
import javafx.scene.image.Image import javafx.scene.image.Image
import org.jackhuang.hmcl.Main import org.jackhuang.hmcl.Main
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount
@@ -24,6 +25,7 @@ import org.jackhuang.hmcl.setting.Settings
import org.jackhuang.hmcl.task.FileDownloadTask import org.jackhuang.hmcl.task.FileDownloadTask
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.DEFAULT_ICON
import org.jackhuang.hmcl.ui.DialogController import org.jackhuang.hmcl.ui.DialogController
import org.jackhuang.hmcl.util.toURL import org.jackhuang.hmcl.util.toURL
import java.net.Proxy import java.net.Proxy
@@ -63,16 +65,20 @@ object AccountHelper {
} }
private fun getSkinFile(name: String) = SKIN_DIR.resolve("$name.png") private fun getSkinFile(name: String) = SKIN_DIR.resolve("$name.png")
private val DEFAULT_IMAGE = Image("/assets/img/icon.png")
fun getSkin(account: YggdrasilAccount, scaleRatio: Double = 1.0): Image { fun getSkin(account: YggdrasilAccount, scaleRatio: Double = 1.0): Image {
if (account.selectedProfile == null) return DEFAULT_IMAGE if (account.selectedProfile == null) return DEFAULT_ICON
val name = account.selectedProfile?.name ?: return DEFAULT_IMAGE val name = account.selectedProfile?.name ?: return DEFAULT_ICON
val file = getSkinFile(name) val file = getSkinFile(name)
if (file.exists()) { if (file.exists()) {
val original = Image("file:" + file.absolutePath) val original = Image("file:" + file.absolutePath)
return Image("file:" + file.absolutePath, original.width * scaleRatio, original.height * scaleRatio, false, false) return Image("file:" + file.absolutePath, original.width * scaleRatio, original.height * scaleRatio, false, false)
} }
else return DEFAULT_IMAGE else return DEFAULT_ICON
}
fun getViewport(scaleRatio: Double): Rectangle2D {
val size = 8.0 * scaleRatio
return Rectangle2D(size, size, size, size)
} }
} }

View File

@@ -127,6 +127,9 @@ class HMCLGameRepository(val profile: Profile, baseDirectory: File)
return versionSettings[id] return versionSettings[id]
} }
fun getVersionIcon(id: String): File =
getVersionRoot(id).resolve("icon.png")
fun markVersionAsModpack(id: String) { fun markVersionAsModpack(id: String) {
beingModpackVersions += id beingModpackVersions += id
} }

View File

@@ -98,11 +98,9 @@ class AccountItem(i: Int, val account: Account, group: ToggleGroup) : StackPane(
if (account !is YggdrasilAccount) if (account !is YggdrasilAccount)
return return
pgsSkin.isVisible = false pgsSkin.isVisible = false
val size = 8.0 * 4 portraitView.viewport = AccountHelper.getViewport(4.0)
portraitView.viewport = Rectangle2D(size, size, size, size)
portraitView.image = AccountHelper.getSkin(account, 4.0) portraitView.image = AccountHelper.getSkin(account, 4.0)
portraitView.fitHeight = 32.0 portraitView.limitSize(32.0, 32.0)
portraitView.fitWidth = 32.0
} }
private fun getDefaultColor(i: Int): String { private fun getDefaultColor(i: Int): String {

View File

@@ -37,6 +37,7 @@ import org.jackhuang.hmcl.task.Scheduler
import org.jackhuang.hmcl.task.taskResult import org.jackhuang.hmcl.task.taskResult
import org.jackhuang.hmcl.ui.wizard.DecoratorPage import org.jackhuang.hmcl.ui.wizard.DecoratorPage
import org.jackhuang.hmcl.util.onChange import org.jackhuang.hmcl.util.onChange
import org.jackhuang.hmcl.util.onChangeAndOperate
class AccountsPage() : StackPane(), DecoratorPage { class AccountsPage() : StackPane(), DecoratorPage {
override val titleProperty: StringProperty = SimpleStringProperty(this, "title", "Accounts") override val titleProperty: StringProperty = SimpleStringProperty(this, "title", "Accounts")
@@ -69,7 +70,7 @@ class AccountsPage() : StackPane(), DecoratorPage {
txtPassword.setOnAction { onCreationAccept() } txtPassword.setOnAction { onCreationAccept() }
txtUsername.setOnAction { onCreationAccept() } txtUsername.setOnAction { onCreationAccept() }
Settings.selectedAccountProperty.setChangedListener { account -> Settings.selectedAccountProperty.onChangeAndOperate { account ->
masonryPane.children.forEach { node -> masonryPane.children.forEach { node ->
if (node is AccountItem) { if (node is AccountItem) {
node.chkSelected.isSelected = account?.username == node.lblUser.text node.chkSelected.isSelected = account?.username == node.lblUser.text

View File

@@ -33,6 +33,8 @@ import javafx.scene.Node
import javafx.scene.Parent import javafx.scene.Parent
import javafx.scene.Scene import javafx.scene.Scene
import javafx.scene.control.* import javafx.scene.control.*
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.image.WritableImage import javafx.scene.image.WritableImage
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
import javafx.scene.input.ScrollEvent import javafx.scene.input.ScrollEvent
@@ -248,4 +250,19 @@ fun JFXTextField.setValidateWhileTextChanged() {
fun JFXPasswordField.setValidateWhileTextChanged() { fun JFXPasswordField.setValidateWhileTextChanged() {
textProperty().addListener { _ -> validate() } textProperty().addListener { _ -> validate() }
validate() validate()
} }
fun ImageView.limitSize(maxWidth: Double, maxHeight: Double) {
isPreserveRatio = true
imageProperty().onChangeAndOperate {
if (it != null && (it.width > maxWidth || it.height > maxHeight)) {
fitHeight = maxHeight
fitWidth = maxWidth
} else {
fitHeight = -1.0
fitWidth = -1.0
}
}
}
val DEFAULT_ICON = Image("/assets/img/icon.png")

View File

@@ -19,10 +19,13 @@ package org.jackhuang.hmcl.ui
import com.jfoenix.controls.JFXComboBox import com.jfoenix.controls.JFXComboBox
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount
import org.jackhuang.hmcl.game.AccountHelper
import org.jackhuang.hmcl.i18n import org.jackhuang.hmcl.i18n
import org.jackhuang.hmcl.setting.Settings import org.jackhuang.hmcl.setting.Settings
import org.jackhuang.hmcl.ui.construct.IconedItem import org.jackhuang.hmcl.ui.construct.IconedItem
import org.jackhuang.hmcl.ui.construct.RipplerContainer import org.jackhuang.hmcl.ui.construct.RipplerContainer
import org.jackhuang.hmcl.util.onChangeAndOperate
class LeftPaneController(private val leftPane: AdvancedListBox) { class LeftPaneController(private val leftPane: AdvancedListBox) {
val versionsPane = VBox() val versionsPane = VBox()
@@ -63,7 +66,7 @@ class LeftPaneController(private val leftPane: AdvancedListBox) {
} }
Controllers.mainPane.buttonLaunch.setOnMouseClicked { LauncherHelper.launch() }*/ Controllers.mainPane.buttonLaunch.setOnMouseClicked { LauncherHelper.launch() }*/
Settings.selectedAccountProperty.setChangedListener { Settings.selectedAccountProperty.onChangeAndOperate {
if (it == null) { if (it == null) {
accountItem.lblVersionName.text = "mojang@mojang.com" accountItem.lblVersionName.text = "mojang@mojang.com"
accountItem.lblGameVersion.text = "Yggdrasil" accountItem.lblGameVersion.text = "Yggdrasil"
@@ -71,6 +74,13 @@ class LeftPaneController(private val leftPane: AdvancedListBox) {
accountItem.lblVersionName.text = it.username accountItem.lblVersionName.text = it.username
accountItem.lblGameVersion.text = accountType(it) accountItem.lblGameVersion.text = accountType(it)
} }
if (it is YggdrasilAccount) {
accountItem.imageView.image = AccountHelper.getSkin(it, 4.0)
accountItem.imageView.viewport = AccountHelper.getViewport(4.0)
} else {
accountItem.imageView.image = DEFAULT_ICON
accountItem.imageView.viewport = null
}
} }
if (Settings.getAccounts().isEmpty()) if (Settings.getAccounts().isEmpty())

View File

@@ -25,6 +25,7 @@ import javafx.beans.property.StringProperty
import javafx.fxml.FXML import javafx.fxml.FXML
import javafx.scene.Node import javafx.scene.Node
import javafx.scene.control.ToggleGroup import javafx.scene.control.ToggleGroup
import javafx.scene.image.Image
import javafx.scene.layout.StackPane import javafx.scene.layout.StackPane
import org.jackhuang.hmcl.ProfileChangedEvent import org.jackhuang.hmcl.ProfileChangedEvent
import org.jackhuang.hmcl.ProfileLoadingEvent import org.jackhuang.hmcl.ProfileLoadingEvent
@@ -83,6 +84,9 @@ class MainPage : StackPane(), DecoratorPage {
Controllers.decorator.showPage(Controllers.versionPane) Controllers.decorator.showPage(Controllers.versionPane)
Controllers.versionPane.load(version, profile) Controllers.versionPane.load(version, profile)
} }
val iconFile = profile.repository.getVersionIcon(version)
if (iconFile.exists())
iconView.image = Image("file:" + iconFile.absolutePath)
} }
} }

View File

@@ -25,6 +25,7 @@ import javafx.scene.control.Label
import javafx.scene.control.ToggleGroup import javafx.scene.control.ToggleGroup
import javafx.scene.effect.BlurType import javafx.scene.effect.BlurType
import javafx.scene.effect.DropShadow import javafx.scene.effect.DropShadow
import javafx.scene.image.ImageView
import javafx.scene.layout.Pane import javafx.scene.layout.Pane
import javafx.scene.layout.StackPane import javafx.scene.layout.StackPane
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
@@ -41,6 +42,7 @@ class VersionItem(i: Int, group: ToggleGroup) : StackPane() {
@FXML lateinit var lblVersionName: Label @FXML lateinit var lblVersionName: Label
@FXML lateinit var chkSelected: JFXRadioButton @FXML lateinit var chkSelected: JFXRadioButton
@FXML lateinit var lblGameVersion: Label @FXML lateinit var lblGameVersion: Label
@FXML lateinit var iconView: ImageView
init { init {
loadFXML("/assets/fxml/version-item.fxml") loadFXML("/assets/fxml/version-item.fxml")
@@ -60,6 +62,7 @@ class VersionItem(i: Int, group: ToggleGroup) : StackPane() {
// create image view // create image view
icon.translateYProperty().bind(Bindings.createDoubleBinding(Callable { header.boundsInParent.height - icon.height }, header.boundsInParentProperty(), icon.heightProperty())) icon.translateYProperty().bind(Bindings.createDoubleBinding(Callable { header.boundsInParent.height - icon.height }, header.boundsInParentProperty(), icon.heightProperty()))
iconView.limitSize(32.0, 32.0)
} }
private fun getDefaultColor(i: Int): String { private fun getDefaultColor(i: Int): String {

View File

@@ -20,13 +20,15 @@ package org.jackhuang.hmcl.ui
import javafx.fxml.FXML import javafx.fxml.FXML
import javafx.scene.control.Button import javafx.scene.control.Button
import javafx.scene.control.Label import javafx.scene.control.Label
import javafx.scene.image.ImageView
import javafx.scene.layout.StackPane import javafx.scene.layout.StackPane
class VersionListItem(val versionName: String, val gameVersion: String) : StackPane() { class VersionListItem(versionName: String, gameVersion: String) : StackPane() {
@FXML lateinit var lblVersionName: Label @FXML lateinit var lblVersionName: Label
@FXML lateinit var lblGameVersion: Label @FXML lateinit var lblGameVersion: Label
@FXML lateinit var btnSettings: Button @FXML lateinit var imageView: ImageView
@FXML lateinit var imageViewContainer: StackPane
private var handler: () -> Unit = {} private var handler: () -> Unit = {}
@@ -34,6 +36,10 @@ class VersionListItem(val versionName: String, val gameVersion: String) : StackP
loadFXML("/assets/fxml/version-list-item.fxml") loadFXML("/assets/fxml/version-list-item.fxml")
lblVersionName.text = versionName lblVersionName.text = versionName
lblGameVersion.text = gameVersion lblGameVersion.text = gameVersion
imageView.limitSize(32.0, 32.0)
imageViewContainer.limitWidth(32.0)
imageViewContainer.limitHeight(32.0)
} }
fun onSettings() { fun onSettings() {

View File

@@ -44,6 +44,8 @@ class VersionPage : StackPane(), DecoratorPage {
@FXML lateinit var btnBrowseMenu: JFXButton @FXML lateinit var btnBrowseMenu: JFXButton
@FXML lateinit var btnManagementMenu: JFXButton @FXML lateinit var btnManagementMenu: JFXButton
@FXML lateinit var btnExport: JFXButton @FXML lateinit var btnExport: JFXButton
@FXML lateinit var rootPane: StackPane
@FXML lateinit var contentPane: StackPane
val browsePopup: JFXPopup val browsePopup: JFXPopup
val managementPopup: JFXPopup val managementPopup: JFXPopup
lateinit var profile: Profile lateinit var profile: Profile
@@ -68,7 +70,7 @@ class VersionPage : StackPane(), DecoratorPage {
this.profile = profile this.profile = profile
titleProperty.set(i18n("launcher.title.game") + " - " + id) titleProperty.set(i18n("launcher.title.game") + " - " + id)
versionSettingsController.loadVersionSetting(profile.getVersionSetting(id)) versionSettingsController.loadVersionSetting(profile, id, profile.getVersionSetting(id))
modController.loadMods(profile.modManager, id) modController.loadMods(profile.modManager, id)
installerController.loadVersion(profile, id) installerController.loadVersion(profile, id)
} }

View File

@@ -18,19 +18,24 @@
package org.jackhuang.hmcl.ui package org.jackhuang.hmcl.ui
import com.jfoenix.controls.* import com.jfoenix.controls.*
import javafx.beans.InvalidationListener
import javafx.beans.value.ChangeListener import javafx.beans.value.ChangeListener
import javafx.fxml.FXML import javafx.fxml.FXML
import javafx.scene.control.Label import javafx.scene.control.Label
import javafx.scene.control.ScrollPane import javafx.scene.control.ScrollPane
import javafx.scene.control.Toggle import javafx.scene.control.Toggle
import javafx.scene.control.ToggleGroup import javafx.scene.control.ToggleGroup
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.layout.BorderPane import javafx.scene.layout.BorderPane
import javafx.scene.layout.Pane import javafx.scene.layout.Pane
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser import javafx.stage.DirectoryChooser
import javafx.stage.FileChooser
import org.jackhuang.hmcl.i18n import org.jackhuang.hmcl.i18n
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.task
import org.jackhuang.hmcl.ui.construct.ComponentList import org.jackhuang.hmcl.ui.construct.ComponentList
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
@@ -64,9 +69,15 @@ class VersionSettingsController {
@FXML lateinit var radioCustom: JFXRadioButton @FXML lateinit var radioCustom: JFXRadioButton
@FXML lateinit var btnJavaSelect: JFXButton @FXML lateinit var btnJavaSelect: JFXButton
@FXML lateinit var chkShowLogs: JFXToggleButton @FXML lateinit var chkShowLogs: JFXToggleButton
@FXML lateinit var btnIconSelection: JFXButton
@FXML lateinit var iconView: ImageView
lateinit var profile: Profile
lateinit var versionId: String
val javaGroup = ToggleGroup() 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"
@@ -122,9 +133,12 @@ class VersionSettingsController {
} }
} }
fun loadVersionSetting(version: VersionSetting) { fun loadVersionSetting(profile: Profile, versionId: String, version: VersionSetting) {
rootPane.children -= advancedSettingsPane rootPane.children -= advancedSettingsPane
this.profile = profile
this.versionId = versionId
lastVersionSetting?.apply { lastVersionSetting?.apply {
widthProperty.unbind() widthProperty.unbind()
heightProperty.unbind() heightProperty.unbind()
@@ -192,14 +206,17 @@ class VersionSettingsController {
} }
version.javaDirProperty.setChangedListener { initJavaSubtitle(version) } version.javaDirProperty.setChangedListener { initJavaSubtitle(version) }
version.javaProperty.setChangedListener { initJavaSubtitle(version)} version.javaProperty.setChangedListener { initJavaSubtitle(version) }
initJavaSubtitle(version) initJavaSubtitle(version)
lastVersionSetting = version lastVersionSetting = version
loadIcon()
} }
private fun initJavaSubtitle(version: VersionSetting) { private fun initJavaSubtitle(version: VersionSetting) {
componentJava.subtitle = version.javaVersion?.binary?.absolutePath ?: "Invalid Java Directory" task { it["java"] = version.javaVersion }
.then(task(Scheduler.JAVAFX) { componentJava.subtitle = it.get<JavaVersion?>("java")?.binary?.absolutePath ?: "Invalid Java Directory" })
} }
fun onShowAdvanced() { fun onShowAdvanced() {
@@ -216,4 +233,24 @@ class VersionSettingsController {
if (selectedDir != null) if (selectedDir != null)
txtJavaDir.text = selectedDir.absolutePath txtJavaDir.text = selectedDir.absolutePath
} }
fun onExploreIcon() {
val chooser = FileChooser()
chooser.extensionFilters += FileChooser.ExtensionFilter("Image", "*.png")
val selectedFile = chooser.showOpenDialog(Controllers.stage)
if (selectedFile != null) {
val iconFile = profile.repository.getVersionIcon(versionId)
selectedFile.copyTo(iconFile, overwrite = true)
loadIcon()
}
}
private fun loadIcon() {
val iconFile = profile.repository.getVersionIcon(versionId)
if (iconFile.exists())
iconView.image = Image("file:" + iconFile.absolutePath)
else
iconView.image = DEFAULT_ICON
iconView.limitSize(32.0, 32.0)
}
} }

View File

@@ -42,7 +42,7 @@
</StackPane> </StackPane>
</VBox> </VBox>
<StackPane fx:id="icon" StackPane.alignment="TOP_RIGHT" pickOnBounds="false"> <StackPane fx:id="icon" StackPane.alignment="TOP_RIGHT" pickOnBounds="false">
<ImageView StackPane.alignment="CENTER_RIGHT"> <ImageView fx:id="iconView" StackPane.alignment="CENTER_RIGHT">
<StackPane.margin> <StackPane.margin>
<Insets right="12" /> <Insets right="12" />
</StackPane.margin> </StackPane.margin>

View File

@@ -14,15 +14,17 @@
<BorderPane pickOnBounds="false"> <BorderPane pickOnBounds="false">
<left> <left>
<HBox alignment="CENTER" mouseTransparent="true"> <HBox alignment="CENTER" mouseTransparent="true">
<ImageView> <StackPane fx:id="imageViewContainer">
<ImageView preserveRatio="true" fx:id="imageView" smooth="false">
<Image url="/assets/img/icon.png" requestedWidth="25" requestedHeight="25" /> <Image url="/assets/img/icon.png" requestedWidth="25" requestedHeight="25" />
</ImageView> </ImageView>
</StackPane>
<BorderPane style="-fx-padding: 0 0 0 10;"> <BorderPane style="-fx-padding: 0 0 0 10;">
<top> <top>
<Label fx:id="lblVersionName" maxWidth="100" style="-fx-font-size: 15;" textAlignment="JUSTIFY" /> <Label fx:id="lblVersionName" maxWidth="90" style="-fx-font-size: 15;" textAlignment="JUSTIFY" />
</top> </top>
<bottom> <bottom>
<Label fx:id="lblGameVersion" maxWidth="100" style="-fx-font-size: 10;" textAlignment="JUSTIFY" /> <Label fx:id="lblGameVersion" maxWidth="90" style="-fx-font-size: 10;" textAlignment="JUSTIFY" />
</bottom> </bottom>
</BorderPane> </BorderPane>
</HBox> </HBox>

View File

@@ -1,36 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?> <?import com.jfoenix.controls.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXTextField?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXCheckBox?>
<?import javafx.geometry.Insets?>
<?import com.jfoenix.controls.JFXComboBox?>
<?import javafx.collections.FXCollections?> <?import javafx.collections.FXCollections?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.*?>
<?import org.jackhuang.hmcl.ui.construct.ComponentList?> <?import org.jackhuang.hmcl.ui.construct.ComponentList?>
<?import com.jfoenix.controls.JFXToggleButton?>
<?import com.jfoenix.controls.JFXRadioButton?>
<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">
<ScrollPane fx:id="scroll" fitToHeight="true" fitToWidth="true"> <ScrollPane fx:id="scroll" fitToHeight="true" fitToWidth="true">
<VBox fx:id="rootPane" style="-fx-padding: 20;"> <VBox fx:id="rootPane" style="-fx-padding: 20;">
<ComponentList depth="1"> <ComponentList depth="1">
<ComponentList fx:id="componentJava" title="%settings.java_dir" hasSubtitle="true"> <!-- Java Directory --> <BorderPane> <!-- Icon -->
<left>
<Label text="settings.icon" />
</left>
<right>
<HBox alignment="CENTER_RIGHT" spacing="8">
<ImageView fx:id="iconView" smooth="false" preserveRatio="true">
<StackPane.margin>
<Insets right="12"/>
</StackPane.margin>
<Image url="/assets/img/icon.png"/>
</ImageView>
<JFXButton fx:id="btnIconSelection" onMouseClicked="#onExploreIcon" styleClass="toggle-icon4">
<graphic>
<fx:include source="/assets/svg/pencil.fxml" />
</graphic>
</JFXButton>
</HBox>
</right>
</BorderPane>
<ComponentList fx:id="componentJava" title="%settings.java_dir"
hasSubtitle="true"> <!-- Java Directory -->
<VBox fx:id="javaPane" spacing="8" style="-fx-padding: 0 0 10 0;"> <VBox fx:id="javaPane" spacing="8" style="-fx-padding: 0 0 10 0;">
<BorderPane fx:id="javaPaneCustom" style="-fx-padding: 3;"> <BorderPane fx:id="javaPaneCustom" style="-fx-padding: 3;">
<left> <left>
<JFXRadioButton fx:id="radioCustom" text="%settings.custom" /> <JFXRadioButton fx:id="radioCustom" text="%settings.custom"/>
</left> </left>
<right> <right>
<HBox spacing="3"> <HBox spacing="3">
<JFXTextField fx:id="txtJavaDir" BorderPane.alignment="CENTER_RIGHT" /> <JFXTextField fx:id="txtJavaDir" BorderPane.alignment="CENTER_RIGHT"/>
<JFXButton fx:id="btnJavaSelect" onMouseClicked="#onExploreJavaDir"> <JFXButton fx:id="btnJavaSelect" onMouseClicked="#onExploreJavaDir">
<graphic> <graphic>
<fx:include source="/assets/svg/folder-open.fxml" /> <fx:include source="/assets/svg/folder-open.fxml"/>
</graphic> </graphic>
</JFXButton> </JFXButton>
</HBox> </HBox>
@@ -40,20 +59,29 @@
</ComponentList> </ComponentList>
<BorderPane> <!-- Max Memory --> <BorderPane> <!-- Max Memory -->
<left><VBox><Label text="%settings.max_memory" BorderPane.alignment="CENTER_LEFT" /><Label fx:id="lblPhysicalMemory" styleClass="subtitle-label" /></VBox></left> <left>
<right><JFXTextField fx:id="txtMaxMemory" BorderPane.alignment="CENTER_RIGHT" /></right> <VBox>
<Label text="%settings.max_memory" BorderPane.alignment="CENTER_LEFT"/>
<Label fx:id="lblPhysicalMemory" styleClass="subtitle-label"/>
</VBox>
</left>
<right>
<JFXTextField fx:id="txtMaxMemory" BorderPane.alignment="CENTER_RIGHT"/>
</right>
</BorderPane> </BorderPane>
<BorderPane> <!-- Launcher Visibility --> <BorderPane> <!-- Launcher Visibility -->
<left><Label text="%advancedsettings.launcher_visible" BorderPane.alignment="CENTER_LEFT" /></left> <left>
<Label text="%advancedsettings.launcher_visible" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right> <right>
<JFXComboBox fx:id="cboLauncherVisibility" BorderPane.alignment="CENTER_RIGHT"> <JFXComboBox fx:id="cboLauncherVisibility" BorderPane.alignment="CENTER_RIGHT">
<items> <items>
<FXCollections fx:factory="observableArrayList"> <FXCollections fx:factory="observableArrayList">
<Label text="%advancedsettings.launcher_visibility.close" /> <Label text="%advancedsettings.launcher_visibility.close"/>
<Label text="%advancedsettings.launcher_visibility.hide" /> <Label text="%advancedsettings.launcher_visibility.hide"/>
<Label text="%advancedsettings.launcher_visibility.keep" /> <Label text="%advancedsettings.launcher_visibility.keep"/>
<Label text="%advancedsettings.launcher_visibility.hide_reopen" /> <Label text="%advancedsettings.launcher_visibility.hide_reopen"/>
</FXCollections> </FXCollections>
</items> </items>
</JFXComboBox> </JFXComboBox>
@@ -61,13 +89,15 @@
</BorderPane> </BorderPane>
<BorderPane> <!-- Run Directory --> <BorderPane> <!-- Run Directory -->
<left><Label text="%settings.run_directory" BorderPane.alignment="CENTER_LEFT" /></left> <left>
<Label text="%settings.run_directory" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right> <right>
<JFXComboBox fx:id="cboRunDirectory" BorderPane.alignment="CENTER_RIGHT"> <JFXComboBox fx:id="cboRunDirectory" BorderPane.alignment="CENTER_RIGHT">
<items> <items>
<FXCollections fx:factory="observableArrayList"> <FXCollections fx:factory="observableArrayList">
<Label text="%advancedsettings.game_dir.default" /> <Label text="%advancedsettings.game_dir.default"/>
<Label text="%advancedsettings.game_dir.independent" /> <Label text="%advancedsettings.game_dir.independent"/>
</FXCollections> </FXCollections>
</items> </items>
</JFXComboBox> </JFXComboBox>
@@ -75,18 +105,21 @@
</BorderPane> </BorderPane>
<BorderPane> <!-- Dimension --> <BorderPane> <!-- Dimension -->
<left><Label text="%settings.dimension" BorderPane.alignment="CENTER_LEFT" /></left> <left>
<Label text="%settings.dimension" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right> <right>
<BorderPane> <BorderPane>
<left> <left>
<HBox prefWidth="210" spacing="3" alignment="CENTER" BorderPane.alignment="CENTER"> <HBox prefWidth="210" spacing="3" alignment="CENTER" BorderPane.alignment="CENTER">
<JFXTextField fx:id="txtWidth" promptText="800" prefWidth="100" /> <JFXTextField fx:id="txtWidth" promptText="800" prefWidth="100"/>
<Label>x</Label> <Label>x</Label>
<JFXTextField fx:id="txtHeight" promptText="480" prefWidth="100" /> <JFXTextField fx:id="txtHeight" promptText="480" prefWidth="100"/>
</HBox> </HBox>
</left> </left>
<right> <right>
<JFXCheckBox fx:id="chkFullscreen" text="%settings.fullscreen" alignment="CENTER" BorderPane.alignment="CENTER"> <JFXCheckBox fx:id="chkFullscreen" text="%settings.fullscreen" alignment="CENTER"
BorderPane.alignment="CENTER">
<BorderPane.margin> <BorderPane.margin>
<Insets right="7"/> <Insets right="7"/>
</BorderPane.margin> </BorderPane.margin>
@@ -96,28 +129,62 @@
</right> </right>
</BorderPane> </BorderPane>
<BorderPane><left><Label text="%mainwindow.show_log" /></left><right><JFXToggleButton fx:id="chkShowLogs" size="7" /></right></BorderPane> <BorderPane>
<left>
<Label text="%mainwindow.show_log"/>
</left>
<right>
<JFXToggleButton fx:id="chkShowLogs" size="7"/>
</right>
</BorderPane>
</ComponentList> </ComponentList>
<HBox alignment="CENTER" style="-fx-padding: 10 0 10 0;"> <HBox alignment="CENTER" style="-fx-padding: 10 0 10 0;">
<JFXButton text="%advancedsettings" onMouseClicked="#onShowAdvanced" /> <JFXButton text="%advancedsettings" onMouseClicked="#onShowAdvanced"/>
</HBox> </HBox>
<ComponentList fx:id="advancedSettingsPane" depth="1"> <ComponentList fx:id="advancedSettingsPane" depth="1">
<JFXTextField labelFloat="true" promptText="%advancedsettings.jvm_args" styleClass="fit-width" fx:id="txtJVMArgs"> <JFXTextField labelFloat="true" promptText="%advancedsettings.jvm_args" styleClass="fit-width"
fx:id="txtJVMArgs">
<tooltip> <tooltip>
<Tooltip text="%advancedsettings.java_args_default" /> <Tooltip text="%advancedsettings.java_args_default"/>
</tooltip> </tooltip>
</JFXTextField> </JFXTextField>
<fx:define> <fx:define>
<Insets fx:id="insets" bottom="8" /> <Insets fx:id="insets" bottom="8"/>
</fx:define> </fx:define>
<JFXTextField labelFloat="true" promptText="%advancedsettings.Minecraft_arguments" styleClass="fit-width" fx:id="txtGameArgs" StackPane.margin="$insets" /> <JFXTextField labelFloat="true" promptText="%advancedsettings.Minecraft_arguments"
<JFXTextField labelFloat="true" promptText="%advancedsettings.java_permanent_generation_space" styleClass="fit-width" fx:id="txtMetaspace" StackPane.margin="$insets" /> styleClass="fit-width" fx:id="txtGameArgs" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%advancedsettings.wrapper_launcher" styleClass="fit-width" fx:id="txtWrapper" StackPane.margin="$insets" /> <JFXTextField labelFloat="true" promptText="%advancedsettings.java_permanent_generation_space"
<JFXTextField labelFloat="true" promptText="%advancedsettings.precall_command" styleClass="fit-width" fx:id="txtPrecallingCommand" StackPane.margin="$insets" /> styleClass="fit-width" fx:id="txtMetaspace" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%advancedsettings.server_ip" styleClass="fit-width" fx:id="txtServerIP" StackPane.margin="$insets" /> <JFXTextField labelFloat="true" promptText="%advancedsettings.wrapper_launcher" styleClass="fit-width"
<BorderPane><left><Label text="%advancedsettings.no_jvm_args" /></left><right><JFXToggleButton fx:id="chkNoJVMArgs" size="7" /></right></BorderPane> fx:id="txtWrapper" StackPane.margin="$insets"/>
<BorderPane><left><Label text="%advancedsettings.no_common" /></left><right><JFXToggleButton fx:id="chkNoCommon" size="7" /></right></BorderPane> <JFXTextField labelFloat="true" promptText="%advancedsettings.precall_command" styleClass="fit-width"
<BorderPane><left><Label text="%advancedsettings.dont_check_game_completeness" /></left><right><JFXToggleButton fx:id="chkNoGameCheck" size="7" /></right></BorderPane> fx:id="txtPrecallingCommand" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%advancedsettings.server_ip" styleClass="fit-width"
fx:id="txtServerIP" StackPane.margin="$insets"/>
<BorderPane>
<left>
<Label text="%advancedsettings.no_jvm_args"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoJVMArgs" size="7"/>
</right>
</BorderPane>
<BorderPane>
<left>
<Label text="%advancedsettings.no_common"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoCommon" size="7"/>
</right>
</BorderPane>
<BorderPane>
<left>
<Label text="%advancedsettings.dont_check_game_completeness"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoGameCheck" size="7"/>
</right>
</BorderPane>
</ComponentList> </ComponentList>
</VBox> </VBox>
</ScrollPane> </ScrollPane>

View File

@@ -2,54 +2,64 @@
<?import com.jfoenix.controls.*?> <?import com.jfoenix.controls.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<fx:root xmlns="http://javafx.com/javafx" <fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
type="StackPane"> fx:id="rootPane"
<JFXTabPane> type="StackPane">
<Tab text="%settings"> <JFXRippler />
<fx:include source="version-settings.fxml" fx:id="versionSettings" /> <StackPane fx:id="contentPane">
</Tab> <JFXTabPane>
<Tab text="%mods"> <Tab text="%settings">
<fx:include source="mod.fxml" fx:id="mod" /> <fx:include source="version-settings.fxml" fx:id="versionSettings"/>
</Tab> </Tab>
<Tab text="%settings.tabs.installers"> <Tab text="%mods">
<fx:include source="installer.fxml" fx:id="installer" /> <fx:include source="mod.fxml" fx:id="mod"/>
</Tab> </Tab>
</JFXTabPane> <Tab text="%settings.tabs.installers">
<fx:include source="installer.fxml" fx:id="installer"/>
</Tab>
</JFXTabPane>
<HBox alignment="TOP_RIGHT" style="-fx-padding: 3px;" pickOnBounds="false"> <HBox alignment="TOP_RIGHT" style="-fx-padding: 3px;" pickOnBounds="false">
<JFXButton fx:id="btnExport" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onExport" styleClass="toggle-icon3" ripplerFill="white"> <JFXButton fx:id="btnExport" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onExport"
<graphic> styleClass="toggle-icon3" ripplerFill="white">
<fx:include source="/assets/svg/export.fxml"/> <graphic>
</graphic> <fx:include source="/assets/svg/export.fxml"/>
</JFXButton> </graphic>
<JFXButton fx:id="btnBrowseMenu" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onBrowseMenu" styleClass="toggle-icon3" ripplerFill="white"> </JFXButton>
<graphic> <JFXButton fx:id="btnBrowseMenu" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onBrowseMenu"
<fx:include source="/assets/svg/folder-open.fxml"/> styleClass="toggle-icon3" ripplerFill="white">
</graphic> <graphic>
</JFXButton> <fx:include source="/assets/svg/folder-open.fxml"/>
<JFXButton fx:id="btnManagementMenu" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onManagementMenu" styleClass="toggle-icon3" ripplerFill="white"> </graphic>
<graphic> </JFXButton>
<fx:include source="/assets/svg/wrench-black.fxml"/> <JFXButton fx:id="btnManagementMenu" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onManagementMenu"
</graphic> styleClass="toggle-icon3" ripplerFill="white">
</JFXButton> <graphic>
</HBox> <fx:include source="/assets/svg/wrench-black.fxml"/>
</graphic>
</JFXButton>
</HBox>
</StackPane>
<JFXListView fx:id="browseList" styleClass="option-list-view" onMouseClicked="#onBrowse" maxWidth="150.0" minWidth="150.0"> <JFXListView fx:id="browseList" styleClass="option-list-view" onMouseClicked="#onBrowse" maxWidth="150.0"
<Label text="%folder.game" /> minWidth="150.0">
<Label text="%folder.mod" /> <Label text="%folder.game"/>
<Label text="%folder.coremod" /> <Label text="%folder.mod"/>
<Label text="%folder.config" /> <Label text="%folder.coremod"/>
<Label text="%folder.resourcepacks" /> <Label text="%folder.config"/>
<Label text="%folder.screenshots" /> <Label text="%folder.resourcepacks"/>
<Label text="%folder.saves" /> <Label text="%folder.screenshots"/>
<Label text="%folder.saves"/>
</JFXListView> </JFXListView>
<JFXListView fx:id="managementList" styleClass="option-list-view" onMouseClicked="#onManagement" maxWidth="300.0" minWidth="300.0"> <JFXListView fx:id="managementList" styleClass="option-list-view" onMouseClicked="#onManagement"
<Label text="%versions.manage.rename" /> maxWidth="300.0" minWidth="300.0">
<Label text="%versions.manage.remove" /> <Label text="%versions.manage.rename"/>
<Label text="%versions.manage.redownload_assets_index" /> <Label text="%versions.manage.remove"/>
<Label text="%versions.manage.remove_libraries" /> <Label text="%versions.manage.redownload_assets_index"/>
<Label text="%versions.manage.remove_libraries"/>
</JFXListView> </JFXListView>
</fx:root> </fx:root>

View File

@@ -22,6 +22,7 @@ import javafx.collections.ListChangeListener
import javafx.collections.ObservableList import javafx.collections.ObservableList
fun <T> ObservableValue<T>.onChange(op: (T?) -> Unit) = apply { addListener { _, _, new -> op(new) } } fun <T> ObservableValue<T>.onChange(op: (T?) -> Unit) = apply { addListener { _, _, new -> op(new) } }
fun <T> ObservableValue<T>.onChangeAndOperate(op: (T?) -> Unit) = apply { addListener { _, _, new -> op(new) }; op(value) }
fun ObservableBooleanValue.onChange(op: (Boolean) -> Unit) = apply { addListener { _, _, new -> op(new ?: false) } } fun ObservableBooleanValue.onChange(op: (Boolean) -> Unit) = apply { addListener { _, _, new -> op(new ?: false) } }
fun ObservableIntegerValue.onChange(op: (Int) -> Unit) = apply { addListener { _, _, new -> op((new ?: 0).toInt()) } } fun ObservableIntegerValue.onChange(op: (Int) -> Unit) = apply { addListener { _, _, new -> op((new ?: 0).toInt()) } }
fun ObservableLongValue.onChange(op: (Long) -> Unit) = apply { addListener { _, _, new -> op((new ?: 0L).toLong()) } } fun ObservableLongValue.onChange(op: (Long) -> Unit) = apply { addListener { _, _, new -> op((new ?: 0L).toLong()) } }