perf: slightly speed up VersionSettingsPage loading.

This commit is contained in:
huanghongxun
2021-08-07 18:14:51 +08:00
parent b2594122a8
commit 820c5a563a
2 changed files with 280 additions and 210 deletions

View File

@@ -17,20 +17,19 @@
*/
package org.jackhuang.hmcl.ui.versions;
import com.jfoenix.controls.JFXCheckBox;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXTextField;
import com.jfoenix.controls.JFXToggleButton;
import com.jfoenix.controls.*;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
@@ -44,10 +43,7 @@ import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.ComponentList;
import org.jackhuang.hmcl.ui.construct.ImagePickerItem;
import org.jackhuang.hmcl.ui.construct.MultiFileItem;
import org.jackhuang.hmcl.ui.construct.Navigator;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.io.FileUtils;
@@ -75,56 +71,294 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private String versionId;
private boolean javaItemsLoaded;
@FXML private VBox rootPane;
@FXML private ScrollPane scroll;
@FXML private JFXTextField txtWidth;
@FXML private JFXTextField txtHeight;
@FXML private JFXTextField txtMaxMemory;
@FXML private JFXTextField txtNativesPath;
@FXML private JFXTextField txtJVMArgs;
@FXML private JFXTextField txtGameArgs;
@FXML private JFXTextField txtMetaspace;
@FXML private JFXTextField txtWrapper;
@FXML private JFXTextField txtPrecallingCommand;
@FXML private JFXTextField txtServerIP;
@FXML private ComponentList advancedSettingsPane;
@FXML private ComponentList componentList;
@FXML private ComponentList iconPickerItemWrapper;
@FXML private JFXComboBox<LauncherVisibility> cboLauncherVisibility;
@FXML private JFXCheckBox chkFullscreen;
@FXML private Label lblPhysicalMemory;
@FXML private Label lblCustomizedNativesPath;
@FXML private JFXToggleButton chkNoJVMArgs;
@FXML private JFXToggleButton chkNoGameCheck;
@FXML private JFXToggleButton chkNoJVMCheck;
@FXML private MultiFileItem<JavaVersion> javaItem;
@FXML private MultiFileItem<GameDirectoryType> gameDirItem;
@FXML private MultiFileItem<NativesDirectoryType> nativesDirItem;
@FXML private JFXToggleButton chkShowLogs;
@FXML private ImagePickerItem iconPickerItem;
@FXML private JFXCheckBox chkEnableSpecificSettings;
@FXML private BorderPane settingsTypePane;
private final VBox rootPane;
private final JFXTextField txtWidth;
private final JFXTextField txtHeight;
private final JFXTextField txtMaxMemory;
private final JFXTextField txtJVMArgs;
private final JFXTextField txtGameArgs;
private final JFXTextField txtMetaspace;
private final JFXTextField txtWrapper;
private final JFXTextField txtPrecallingCommand;
private final JFXTextField txtServerIP;
private final ComponentList advancedSettingsPane;
private final ComponentList componentList;
private final ComponentList iconPickerItemWrapper;
private final JFXComboBox<LauncherVisibility> cboLauncherVisibility;
private final JFXCheckBox chkFullscreen;
private final Label lblPhysicalMemory;
private final JFXToggleButton chkNoJVMArgs;
private final JFXToggleButton chkNoGameCheck;
private final JFXToggleButton chkNoJVMCheck;
private final MultiFileItem<JavaVersion> javaItem;
private final MultiFileItem<GameDirectoryType> gameDirItem;
private final MultiFileItem<NativesDirectoryType> nativesDirItem;
private final JFXToggleButton chkShowLogs;
private final ImagePickerItem iconPickerItem;
private final JFXCheckBox chkEnableSpecificSettings;
private final BorderPane settingsTypePane;
private InvalidationListener specificSettingsListener = any -> {
chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal());
};
private final InvalidationListener specificSettingsListener;
private InvalidationListener javaListener = any -> initJavaSubtitle();
private final InvalidationListener javaListener = any -> initJavaSubtitle();
public VersionSettingsPage() {
FXUtils.loadFXML(this, "/assets/fxml/version/version-settings.fxml");
ScrollPane scrollPane = new ScrollPane();
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
getChildren().setAll(scrollPane);
rootPane = new VBox();
scrollPane.setContent(rootPane);
FXUtils.smoothScrolling(scrollPane);
rootPane.getStyleClass().add("card-list");
{
iconPickerItemWrapper = new ComponentList();
iconPickerItem = new ImagePickerItem();
iconPickerItem.setImage(new Image("/assets/img/icon.png"));
iconPickerItem.setTitle(i18n("settings.icon"));
iconPickerItem.setOnSelectButtonClicked(e -> onExploreIcon());
iconPickerItem.setOnDeleteButtonClicked(e -> onDeleteIcon());
iconPickerItemWrapper.getContent().setAll(iconPickerItem);
}
{
settingsTypePane = new BorderPane();
chkEnableSpecificSettings = new JFXCheckBox();
settingsTypePane.setLeft(chkEnableSpecificSettings);
chkEnableSpecificSettings.setText(i18n("settings.type.special.enable"));
BorderPane.setAlignment(chkEnableSpecificSettings, Pos.CENTER_RIGHT);
JFXButton editGlobalSettingsButton = new JFXButton();
settingsTypePane.setRight(editGlobalSettingsButton);
editGlobalSettingsButton.setText(i18n("settings.type.global.edit"));
editGlobalSettingsButton.getStyleClass().add("jfx-button-raised");
editGlobalSettingsButton.setButtonType(JFXButton.ButtonType.RAISED);
editGlobalSettingsButton.disableProperty().bind(chkEnableSpecificSettings.selectedProperty());
BorderPane.setAlignment(editGlobalSettingsButton, Pos.CENTER_RIGHT);
editGlobalSettingsButton.setOnMouseClicked(e -> editGlobalSettings());
}
{
componentList = new ComponentList();
componentList.setDepth(1);
javaItem = new MultiFileItem<>(true);
javaItem.setTitle(i18n("settings.game.java_directory"));
javaItem.setChooserTitle(i18n("settings.game.java_directory.choose"));
javaItem.setHasSubtitle(true);
javaItem.setCustomText(i18n("settings.custom"));
javaItem.setDirectory(false);
gameDirItem = new MultiFileItem<>(true);
gameDirItem.setTitle(i18n("settings.game.working_directory"));
gameDirItem.setChooserTitle(i18n("settings.game.working_directory.choose"));
gameDirItem.setHasSubtitle(true);
gameDirItem.setCustomText(i18n("settings.custom"));
gameDirItem.setDirectory(true);
BorderPane maxMemoryPane = new BorderPane();
{
VBox vbox = new VBox();
maxMemoryPane.setLeft(vbox);
Label maxMemoryLabel = new Label(i18n("settings.max_memory"));
lblPhysicalMemory = new Label();
lblPhysicalMemory.getStyleClass().add("subtitle-label");
vbox.getChildren().setAll(maxMemoryLabel, lblPhysicalMemory);
txtMaxMemory = new JFXTextField();
maxMemoryPane.setRight(txtMaxMemory);
BorderPane.setAlignment(txtMaxMemory, Pos.CENTER_RIGHT);
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
FXUtils.setLimitWidth(txtMaxMemory, 300);
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
}
BorderPane launcherVisibilityPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced.launcher_visible"));
launcherVisibilityPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
cboLauncherVisibility = new JFXComboBox<>();
launcherVisibilityPane.setRight(cboLauncherVisibility);
BorderPane.setAlignment(cboLauncherVisibility, Pos.CENTER_RIGHT);
FXUtils.setLimitWidth(cboLauncherVisibility, 300);
}
BorderPane dimensionPane = new BorderPane();
{
Label label = new Label(i18n("settings.game.dimension"));
dimensionPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
BorderPane right = new BorderPane();
dimensionPane.setRight(right);
{
HBox hbox = new HBox();
right.setLeft(hbox);
hbox.setPrefWidth(210);
hbox.setSpacing(3);
hbox.setAlignment(Pos.CENTER);
BorderPane.setAlignment(hbox, Pos.CENTER);
{
txtWidth = new JFXTextField();
txtWidth.setPromptText("800");
txtWidth.setPrefWidth(100);
FXUtils.setValidateWhileTextChanged(txtWidth, true);
txtWidth.getValidators().setAll(new NumberValidator(i18n("input.number"), false));
Label x = new Label("x");
txtHeight = new JFXTextField();
txtHeight.setPromptText("480");
txtHeight.setPrefWidth(100);
FXUtils.setValidateWhileTextChanged(txtHeight, true);
txtHeight.getValidators().setAll(new NumberValidator(i18n("input.number"), false));
hbox.getChildren().setAll(txtWidth, x, txtHeight);
}
chkFullscreen = new JFXCheckBox();
right.setRight(chkFullscreen);
chkFullscreen.setText(i18n("settings.game.fullscreen"));
chkFullscreen.setAlignment(Pos.CENTER);
BorderPane.setAlignment(chkFullscreen, Pos.CENTER);
BorderPane.setMargin(chkFullscreen, new Insets(0, 0, 0, 7));
}
}
BorderPane showLogsPane = new BorderPane();
{
Label label = new Label(i18n("settings.show_log"));
showLogsPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
chkShowLogs = new JFXToggleButton();
showLogsPane.setRight(chkShowLogs);
chkShowLogs.setSize(8);
FXUtils.setLimitHeight(chkShowLogs, 20);
}
componentList.getContent().setAll(javaItem, gameDirItem, maxMemoryPane, launcherVisibilityPane, dimensionPane, showLogsPane);
}
HBox advancedHintPane = new HBox();
advancedHintPane.setAlignment(Pos.CENTER_LEFT);
advancedHintPane.setPadding(new Insets(8, 0, 0, 0));
{
Label advanced = new Label(i18n("settings.advanced"));
advanced.setStyle("-fx-text-fill: #616161");
advancedHintPane.getChildren().setAll(advanced);
}
advancedSettingsPane = new ComponentList();
advancedSettingsPane.setDepth(1);
{
txtJVMArgs = new JFXTextField();
txtJVMArgs.setLabelFloat(true);
txtJVMArgs.setPromptText(i18n("settings.advanced.jvm_args"));
txtJVMArgs.getStyleClass().add("fit-width");
StackPane.setMargin(txtJVMArgs, new Insets(0, 0, 8, 0));
txtGameArgs = new JFXTextField();
txtGameArgs.setLabelFloat(true);
txtGameArgs.setPromptText(i18n("settings.advanced.minecraft_arguments"));
txtGameArgs.getStyleClass().add("fit-width");
StackPane.setMargin(txtGameArgs, new Insets(0, 0, 8, 0));
txtMetaspace = new JFXTextField();
txtMetaspace.setLabelFloat(true);
txtMetaspace.setPromptText(i18n("settings.advanced.java_permanent_generation_space"));
txtMetaspace.getStyleClass().add("fit-width");
StackPane.setMargin(txtMetaspace, new Insets(0, 0, 8, 0));
FXUtils.setValidateWhileTextChanged(txtMetaspace, true);
txtMetaspace.setValidators(new NumberValidator(i18n("input.number"), true));
txtWrapper = new JFXTextField();
txtWrapper.setLabelFloat(true);
txtWrapper.setPromptText(i18n("settings.advanced.wrapper_launcher"));
txtWrapper.getStyleClass().add("fit-width");
StackPane.setMargin(txtWrapper, new Insets(0, 0, 8, 0));
txtPrecallingCommand = new JFXTextField();
txtPrecallingCommand.setLabelFloat(true);
txtPrecallingCommand.setPromptText(i18n("settings.advanced.precall_command"));
txtPrecallingCommand.getStyleClass().add("fit-width");
StackPane.setMargin(txtPrecallingCommand, new Insets(0, 0, 8, 0));
txtServerIP = new JFXTextField();
txtServerIP.setLabelFloat(true);
txtServerIP.setPromptText(i18n("settings.advanced.server_ip"));
txtServerIP.getStyleClass().add("fit-width");
StackPane.setMargin(txtServerIP, new Insets(0, 0, 8, 0));
nativesDirItem = new MultiFileItem<>(true);
nativesDirItem.setTitle(i18n("settings.advanced.natives_directory"));
nativesDirItem.setChooserTitle(i18n("settings.advanced.natives_directory.choose"));
nativesDirItem.setHasSubtitle(true);
nativesDirItem.setCustomText(i18n("settings.custom"));
nativesDirItem.setDirectory(true);
BorderPane noJVMArgsPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced.no_jvm_args"));
noJVMArgsPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
chkNoJVMArgs = new JFXToggleButton();
noJVMArgsPane.setRight(chkNoJVMArgs);
chkNoJVMArgs.setSize(8);
FXUtils.setLimitHeight(chkNoJVMArgs, 20);
}
BorderPane noGameCheckPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced.dont_check_game_completeness"));
noGameCheckPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
chkNoGameCheck = new JFXToggleButton();
noGameCheckPane.setRight(chkNoGameCheck);
chkNoGameCheck.setSize(8);
FXUtils.setLimitHeight(chkNoGameCheck, 20);
}
BorderPane noJVMCheckPane = new BorderPane();
{
Label label = new Label(i18n("settings.advanced.dont_check_jvm_validity"));
noJVMCheckPane.setLeft(label);
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
chkNoJVMCheck = new JFXToggleButton();
noJVMCheckPane.setRight(chkNoJVMCheck);
chkNoJVMCheck.setSize(8);
FXUtils.setLimitHeight(chkNoJVMCheck, 20);
}
advancedSettingsPane.getContent().setAll(txtJVMArgs, txtGameArgs, txtMetaspace, txtWrapper, txtPrecallingCommand, txtServerIP, nativesDirItem, noJVMArgsPane, noGameCheckPane, noJVMCheckPane);
}
rootPane.getChildren().setAll(iconPickerItemWrapper, settingsTypePane, componentList, advancedHintPane, advancedSettingsPane);
initialize();
specificSettingsListener = any -> {
chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal());
};
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating);
cboLauncherVisibility.getItems().setAll(LauncherVisibility.values());
cboLauncherVisibility.setConverter(stringConverter(e -> i18n("settings.advanced.launcher_visibility." + e.name().toLowerCase())));
}
@FXML
private void initialize() {
lblPhysicalMemory.setText(i18n("settings.physical_memory") + ": " + OperatingSystem.TOTAL_MEMORY + "MB");
FXUtils.smoothScrolling(scroll);
Task.supplyAsync(JavaVersion::getJavas).thenAcceptAsync(Schedulers.javafx(), list -> {
javaItem.loadChildren(list.stream()
.map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
@@ -301,12 +535,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
.start();
}
@FXML
private void editGlobalSettings() {
Versions.modifyGlobalSettings(profile);
}
@FXML
private void onExploreIcon() {
if (versionId == null)
return;
@@ -325,7 +557,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
}
}
@FXML
private void onDeleteIcon() {
if (versionId == null)
return;

View File

@@ -1,161 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.layout.*?>
<?import org.jackhuang.hmcl.ui.construct.*?>
<?import org.jackhuang.hmcl.ui.*?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
type="StackPane">
<ScrollPane fx:id="scroll" fitToHeight="true" fitToWidth="true" vbarPolicy="ALWAYS">
<VBox fx:id="rootPane" styleClass="card-list">
<ComponentList fx:id="iconPickerItemWrapper">
<ImagePickerItem fx:id="iconPickerItem" title="%settings.icon" onSelectButtonClicked="#onExploreIcon" onDeleteButtonClicked="#onDeleteIcon">
<Image url="/assets/img/icon.png"/>
</ImagePickerItem>
</ComponentList>
<BorderPane fx:id="settingsTypePane">
<left>
<JFXCheckBox BorderPane.alignment="CENTER_RIGHT" fx:id="chkEnableSpecificSettings" text="%settings.type.special.enable" />
</left>
<right>
<JFXButton BorderPane.alignment="CENTER_RIGHT" onMouseClicked="#editGlobalSettings"
buttonType="RAISED" styleClass="jfx-button-raised"
text="%settings.type.global.edit" disable="${chkEnableSpecificSettings.selected}" />
</right>
</BorderPane>
<ComponentList fx:id="componentList" depth="1">
<MultiFileItem fx:id="javaItem" title="%settings.game.java_directory" chooserTitle="%settings.game.java_directory.choose"
hasSubtitle="true" customText="%settings.custom" directory="false" />
<MultiFileItem fx:id="gameDirItem" title="%settings.game.working_directory" chooserTitle="%settings.game.working_directory.choose"
hasSubtitle="true" customText="%settings.custom" directory="true" />
<BorderPane> <!-- Max Memory -->
<left>
<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" FXUtils.validateWhileTextChanged="true" FXUtils.limitWidth="300">
<validators>
<NumberValidator message="%input.number" nullable="false" />
</validators>
</JFXTextField>
</right>
</BorderPane>
<BorderPane> <!-- Launcher Visibility -->
<left>
<Label text="%settings.advanced.launcher_visible" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right>
<JFXComboBox fx:id="cboLauncherVisibility" BorderPane.alignment="CENTER_RIGHT" FXUtils.limitWidth="300" />
</right>
</BorderPane>
<BorderPane> <!-- Dimension -->
<left>
<Label text="%settings.game.dimension" BorderPane.alignment="CENTER_LEFT"/>
</left>
<right>
<BorderPane>
<left>
<HBox prefWidth="210" spacing="3" alignment="CENTER" BorderPane.alignment="CENTER">
<JFXTextField fx:id="txtWidth" promptText="800" prefWidth="100" FXUtils.validateWhileTextChanged="true">
<validators>
<NumberValidator message="%input.number" nullable="false" />
</validators>
</JFXTextField>
<Label>x</Label>
<JFXTextField fx:id="txtHeight" promptText="480" prefWidth="100" FXUtils.validateWhileTextChanged="true">
<validators>
<NumberValidator message="%input.number" nullable="false" />
</validators>
</JFXTextField>
</HBox>
</left>
<right>
<JFXCheckBox fx:id="chkFullscreen" text="%settings.game.fullscreen" alignment="CENTER"
BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets right="7"/>
</BorderPane.margin>
</JFXCheckBox>
</right>
</BorderPane>
</right>
</BorderPane>
<BorderPane>
<left>
<Label BorderPane.alignment="CENTER_LEFT" text="%settings.show_log"/>
</left>
<right>
<JFXToggleButton fx:id="chkShowLogs" size="8" FXUtils.limitHeight="20" />
</right>
</BorderPane>
</ComponentList>
<HBox alignment="CENTER_LEFT" style="-fx-padding: 8 0 0 0;">
<Label text="%settings.advanced" style="-fx-text-fill: #616161;" />
</HBox>
<ComponentList fx:id="advancedSettingsPane" depth="1">
<JFXTextField labelFloat="true" promptText="%settings.advanced.jvm_args" styleClass="fit-width"
fx:id="txtJVMArgs" />
<fx:define>
<Insets fx:id="insets" bottom="8"/>
</fx:define>
<JFXTextField labelFloat="true" promptText="%settings.advanced.minecraft_arguments"
styleClass="fit-width" fx:id="txtGameArgs" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%settings.advanced.java_permanent_generation_space"
styleClass="fit-width" fx:id="txtMetaspace" StackPane.margin="$insets" FXUtils.validateWhileTextChanged="true">
<validators>
<NumberValidator message="%input.number" nullable="true" />
</validators>
</JFXTextField>
<JFXTextField labelFloat="true" promptText="%settings.advanced.wrapper_launcher" styleClass="fit-width"
fx:id="txtWrapper" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%settings.advanced.precall_command" styleClass="fit-width"
fx:id="txtPrecallingCommand" StackPane.margin="$insets"/>
<JFXTextField labelFloat="true" promptText="%settings.advanced.server_ip" styleClass="fit-width"
fx:id="txtServerIP" StackPane.margin="$insets"/>
<MultiFileItem fx:id="nativesDirItem" title="%settings.advanced.natives_directory" chooserTitle="%settings.advanced.natives_directory.choose"
hasSubtitle="true" customText="%settings.custom" directory="true" />
<BorderPane>
<left>
<Label BorderPane.alignment="CENTER_LEFT" text="%settings.advanced.no_jvm_args"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoJVMArgs" size="8" FXUtils.limitHeight="20" />
</right>
</BorderPane>
<BorderPane>
<left>
<Label BorderPane.alignment="CENTER_LEFT" text="%settings.advanced.dont_check_game_completeness"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoGameCheck" size="8" FXUtils.limitHeight="20" />
</right>
</BorderPane>
<BorderPane>
<left>
<Label BorderPane.alignment="CENTER_LEFT" text="%settings.advanced.dont_check_jvm_validity"/>
</left>
<right>
<JFXToggleButton fx:id="chkNoJVMCheck" size="8" FXUtils.limitHeight="20" />
</right>
</BorderPane>
</ComponentList>
</VBox>
</ScrollPane>
</fx:root>