Change the way to determine whether use global settings or the specific one

This commit is contained in:
huangyuhui 2018-09-02 23:24:32 +08:00
parent 222e39dc48
commit bbc2b251dd
12 changed files with 126 additions and 64 deletions

View File

@ -75,22 +75,16 @@ public final class Profile implements Observable {
this.gameDir.set(gameDir);
}
private final ObjectProperty<VersionSetting> global = new ImmediateObjectProperty<>(this, "global", new VersionSetting());
private final ReadOnlyObjectWrapper<VersionSetting> global = new ReadOnlyObjectWrapper<>(this, "global");
public ObjectProperty<VersionSetting> globalProperty() {
return global;
public ReadOnlyObjectProperty<VersionSetting> globalProperty() {
return global.getReadOnlyProperty();
}
public VersionSetting getGlobal() {
return global.get();
}
private void setGlobal(VersionSetting global) {
if (global == null)
global = new VersionSetting();
this.global.set(global);
}
private final ImmediateStringProperty name;
public ImmediateStringProperty nameProperty() {
@ -124,10 +118,15 @@ public final class Profile implements Observable {
}
public Profile(String name, File initialGameDir) {
this(name, initialGameDir, new VersionSetting());
}
public Profile(String name, File initialGameDir, VersionSetting global) {
this.name = new ImmediateStringProperty(this, "name", name);
gameDir = new ImmediateObjectProperty<>(this, "gameDir", initialGameDir);
repository = new HMCLGameRepository(this, initialGameDir);
modManager = new ModManager(repository);
this.global.set(global == null ? new VersionSetting() : global);
gameDir.addListener((a, b, newValue) -> repository.changeDirectory(newValue));
selectedVersion.addListener(o -> checkSelectedVersion());
@ -227,7 +226,7 @@ public final class Profile implements Observable {
}
protected void invalidate() {
JFXUtilities.runInFX(observableHelper::invalidate);
observableHelper.invalidate();
}
public static final class Serializer implements JsonSerializer<Profile>, JsonDeserializer<Profile> {
@ -256,8 +255,7 @@ public final class Profile implements Observable {
JsonObject obj = (JsonObject) json;
String gameDir = Optional.ofNullable(obj.get("gameDir")).map(JsonElement::getAsString).orElse("");
Profile profile = new Profile("Default", new File(gameDir));
profile.setGlobal(context.deserialize(obj.get("global"), VersionSetting.class));
Profile profile = new Profile("Default", new File(gameDir), context.deserialize(obj.get("global"), VersionSetting.class));
profile.setSelectedVersion(Optional.ofNullable(obj.get("selectedMinecraftVersion")).map(JsonElement::getAsString).orElse(""));
profile.setUseRelativePath(Optional.ofNullable(obj.get("useRelativePath")).map(JsonElement::getAsBoolean).orElse(false));
return profile;

View File

@ -40,7 +40,7 @@ public final class VersionPage extends StackPane implements DecoratorPage {
private final StringProperty title = new SimpleStringProperty(this, "title", null);
@FXML
private VersionSettingsController versionSettingsController;
private VersionSettingsPage versionSettings;
@FXML
private Tab modTab;
@FXML
@ -92,7 +92,7 @@ public final class VersionPage extends StackPane implements DecoratorPage {
title.set(i18n("settings.game") + " - " + id);
versionSettingsController.loadVersionSetting(profile, id);
versionSettings.loadVersionSetting(profile, id);
modController.setParentTab(tabPane);
modTab.setUserData(modController);
modController.loadMods(profile.getModManager(), id);

View File

@ -17,16 +17,18 @@
*/
package org.jackhuang.hmcl.ui;
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.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
@ -38,6 +40,8 @@ import org.jackhuang.hmcl.task.Task;
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.decorator.DecoratorPage;
import org.jackhuang.hmcl.ui.versions.Versions;
import org.jackhuang.hmcl.util.*;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -49,11 +53,14 @@ import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
public final class VersionSettingsController {
public final class VersionSettingsPage extends StackPane implements DecoratorPage {
private final StringProperty title = new SimpleStringProperty();
private VersionSetting lastVersionSetting = null;
private Profile profile;
private String versionId;
private boolean javaItemsLoaded;
private InvalidationListener specificSettingsListener;
@FXML private VBox rootPane;
@FXML private ScrollPane scroll;
@ -67,16 +74,22 @@ public final class VersionSettingsController {
@FXML private JFXTextField txtPrecallingCommand;
@FXML private JFXTextField txtServerIP;
@FXML private ComponentList advancedSettingsPane;
@FXML private ComponentList componentList;
@FXML private JFXComboBox<?> cboLauncherVisibility;
@FXML private JFXCheckBox chkFullscreen;
@FXML private Label lblPhysicalMemory;
@FXML private JFXToggleButton chkNoJVMArgs;
@FXML private JFXToggleButton chkNoGameCheck;
@FXML private MultiFileItem<Boolean> globalItem;
@FXML private MultiFileItem<JavaVersion> javaItem;
@FXML private MultiFileItem<EnumGameDirectory> gameDirItem;
@FXML private JFXToggleButton chkShowLogs;
@FXML private ImagePickerItem iconPickerItem;
@FXML private JFXCheckBox chkEnableSpecificSettings;
@FXML private BorderPane settingsTypePane;
public VersionSettingsPage() {
FXUtils.loadFXML(this, "/assets/fxml/version/version-settings.fxml");
}
@FXML
private void initialize() {
@ -105,20 +118,42 @@ public final class VersionSettingsController {
gameDirItem.createChildren(i18n("settings.advanced.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER)
));
globalItem.loadChildren(Arrays.asList(
globalItem.createChildren(i18n("settings.type.global"), true),
globalItem.createChildren(i18n("settings.type.special"), false)
));
chkEnableSpecificSettings.selectedProperty().addListener((a, b, newValue) -> {
if (versionId == null) return;
// do not call versionSettings.setUsesGlobal(true/false)
// because versionSettings can be the global one.
// global versionSettings.usesGlobal is always true.
if (newValue)
profile.specializeVersionSetting(versionId);
else
profile.globalizeVersionSetting(versionId);
Platform.runLater(() -> loadVersionSetting(profile, versionId));
});
specificSettingsListener = o -> {
chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal());
};
componentList.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
advancedSettingsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
}
public void loadVersionSetting(Profile profile, String versionId) {
this.profile = profile;
this.versionId = versionId;
if (versionId == null) {
componentList.removeChild(iconPickerItem);
rootPane.getChildren().remove(settingsTypePane);
chkEnableSpecificSettings.setSelected(true);
}
VersionSetting versionSetting = profile.getVersionSetting(versionId);
gameDirItem.setDisable(profile.getRepository().isModpack(versionId));
globalItem.setDisable(profile.getRepository().isModpack(versionId));
gameDirItem.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
settingsTypePane.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
// unbind data fields
if (lastVersionSetting != null) {
@ -139,14 +174,13 @@ public final class VersionSettingsController {
FXUtils.unbindBoolean(chkShowLogs, lastVersionSetting.showLogsProperty());
FXUtils.unbindEnum(cboLauncherVisibility);
globalItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.usesGlobalProperty());
lastVersionSetting.usesGlobalProperty().removeListener(specificSettingsListener);
gameDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.gameDirTypeProperty());
gameDirItem.subtitleProperty().unbind();
}
// unbind data fields
globalItem.setToggleSelectedListener(null);
javaItem.setToggleSelectedListener(null);
// bind new data fields
@ -167,6 +201,10 @@ public final class VersionSettingsController {
FXUtils.bindBoolean(chkShowLogs, versionSetting.showLogsProperty());
FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty());
versionSetting.usesGlobalProperty().addListener(specificSettingsListener);
if (versionId != null)
chkEnableSpecificSettings.setSelected(!versionSetting.isUsesGlobal());
javaItem.setToggleSelectedListener(newValue -> {
if (javaItem.isCustomToggle(newValue)) {
versionSetting.setUsesCustomJavaDir();
@ -179,21 +217,6 @@ public final class VersionSettingsController {
versionSetting.javaProperty().setChangedListener(it -> initJavaSubtitle(versionSetting));
initJavaSubtitle(versionSetting);
globalItem.selectedDataProperty().bindBidirectional(versionSetting.usesGlobalProperty());
globalItem.subtitleProperty().bind(Bindings.createStringBinding(() -> i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special"),
versionSetting.usesGlobalProperty()));
globalItem.setToggleSelectedListener(newValue -> {
// do not call versionSettings.setUsesGlobal(true/false)
// because versionSettings can be the global one.
// global versionSettings.usesGlobal is always true.
if ((Boolean) newValue.getUserData())
profile.globalizeVersionSetting(versionId);
else
profile.specializeVersionSetting(versionId);
Platform.runLater(() -> loadVersionSetting(profile, versionId));
});
gameDirItem.selectedDataProperty().bindBidirectional(versionSetting.gameDirTypeProperty());
gameDirItem.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath()).normalize().toString(),
versionSetting.gameDirProperty(), versionSetting.gameDirTypeProperty()));
@ -229,8 +252,16 @@ public final class VersionSettingsController {
.map(JavaVersion::getBinary).map(File::getAbsolutePath).orElse("Invalid Java Directory"))));
}
@FXML
private void editGlobalSettings() {
Versions.modifyGlobalSettings(profile);
}
@FXML
private void onExploreIcon() {
if (versionId == null)
return;
FileChooser chooser = new FileChooser();
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("extension.png"), "*.png"));
File selectedFile = chooser.showOpenDialog(Controllers.getStage());
@ -246,6 +277,11 @@ public final class VersionSettingsController {
}
private void loadIcon() {
if (versionId == null) {
iconPickerItem.setImage(new Image("/assets/img/grass.png"));
return;
}
File iconFile = profile.getRepository().getVersionIcon(versionId);
if (iconFile.exists())
iconPickerItem.setImage(new Image("file:" + iconFile.getAbsolutePath()));
@ -253,4 +289,9 @@ public final class VersionSettingsController {
iconPickerItem.setImage(new Image("/assets/img/grass.png"));
FXUtils.limitSize(iconPickerItem.getImageView(), 32, 32);
}
@Override
public StringProperty titleProperty() {
return title;
}
}

View File

@ -60,7 +60,7 @@ public class ComponentList extends StackPane {
vbox.getChildren().add(child);
}
public void removeChildren(Node node) {
public void removeChild(Node node) {
vbox.getChildren().removeIf(node1 -> node1.getProperties().get("node") == node);
}

View File

@ -30,6 +30,7 @@ import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.VersionSettingsPage;
import org.jackhuang.hmcl.ui.download.DownloadWizardProvider;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.VersionNumber;
@ -111,7 +112,7 @@ public class GameList extends Control implements DecoratorPage {
}
public void modifyGlobalGameSettings() {
// Controllers.navigate();
Versions.modifyGlobalSettings(profile);
}
@Override

View File

@ -79,13 +79,13 @@ public class GameListSkin extends SkinBase<GameList> {
btnRefresh.setOnMouseClicked(e -> skinnable.refresh());
toolbar.getChildren().add(btnRefresh);
// JFXButton btnModify = new JFXButton();
// btnModify.getStyleClass().add("jfx-tool-bar-button");
// btnModify.textFillProperty().bind(Theme.foregroundFillBinding());
// btnModify.setGraphic(wrap(SVG.gear(Theme.foregroundFillBinding(), -1, -1)));
// btnModify.setText(I18n.i18n("settings.type.global.manage"));
// btnModify.setOnMouseClicked(e -> skinnable.modifyGlobalGameSettings());
// toolbar.getChildren().add(btnModify);
JFXButton btnModify = new JFXButton();
btnModify.getStyleClass().add("jfx-tool-bar-button");
btnModify.textFillProperty().bind(Theme.foregroundFillBinding());
btnModify.setGraphic(wrap(SVG.gear(Theme.foregroundFillBinding(), -1, -1)));
btnModify.setText(I18n.i18n("settings.type.global.manage"));
btnModify.setOnMouseClicked(e -> skinnable.modifyGlobalGameSettings());
toolbar.getChildren().add(btnModify);
root.setTop(toolbar);
}

View File

@ -27,11 +27,13 @@ import org.jackhuang.hmcl.mod.UnsupportedModpackException;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.setting.EnumGameDirectory;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.VersionSettingsPage;
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
import org.jackhuang.hmcl.ui.construct.MessageBox;
import org.jackhuang.hmcl.ui.export.ExportWizardProvider;
@ -130,4 +132,11 @@ public class Versions {
else
LauncherHelper.INSTANCE.launch(profile, Accounts.getSelectedAccount(), id, null);
}
public static void modifyGlobalSettings(Profile profile) {
VersionSettingsPage page = new VersionSettingsPage();
page.loadVersionSetting(profile, null);
page.titleProperty().set(Profiles.getProfileDisplayName(profile) + " - " + i18n("settings.type.global.manage"));
Controllers.navigate(page);
}
}

View File

@ -8,15 +8,24 @@
<?import javafx.scene.layout.*?>
<?import org.jackhuang.hmcl.ui.construct.*?>
<?import org.jackhuang.hmcl.ui.*?>
<StackPane xmlns="http://javafx.com/javafx"
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.jackhuang.hmcl.ui.VersionSettingsController">
type="StackPane">
<ScrollPane fx:id="scroll" fitToHeight="true" fitToWidth="true" vbarPolicy="ALWAYS">
<VBox fx:id="rootPane" style="-fx-padding: 20;">
<VBox fx:id="rootPane" style="-fx-padding: 20;" spacing="8">
<ComponentList depth="1">
<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>
<MultiFileItem fx:id="globalItem" title="%settings.type" hasSubtitle="true" hasCustom="false" />
<ComponentList fx:id="componentList" depth="1">
<ImagePickerItem fx:id="iconPickerItem" title="%settings.icon" onSelectButtonClicked="#onExploreIcon">
<Image url="/assets/img/icon.png"/>
@ -104,7 +113,7 @@
</right>
</BorderPane>
</ComponentList>
<HBox alignment="CENTER_LEFT" style="-fx-padding: 20 0 12 0;">
<HBox alignment="CENTER_LEFT" style="-fx-padding: 12 0 4 0;">
<Label text="%settings.advanced" style="-fx-text-fill: #616161;" />
</HBox>
<ComponentList fx:id="advancedSettingsPane" depth="1">
@ -150,4 +159,4 @@
</ComponentList>
</VBox>
</ScrollPane>
</StackPane>
</fx:root>

View File

@ -4,6 +4,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import org.jackhuang.hmcl.ui.VersionSettingsPage?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:id="rootPane"
@ -12,7 +13,7 @@
<StackPane fx:id="contentPane">
<JFXTabPane fx:id="tabPane">
<Tab text="%settings">
<fx:include source="version-settings.fxml" fx:id="versionSettings"/>
<VersionSettingsPage fx:id="versionSettings" />
</Tab>
<Tab fx:id="modTab" text="%mods">
<fx:include source="mod.fxml" fx:id="mod"/>

View File

@ -313,7 +313,8 @@ settings.tabs.installers=Installers
settings.type=Version setting type
settings.type.global=Global global settings(all shared)
settings.type.global.manage=Global Game Settings
settings.type.special=Specialized version settings(will not affect other versions)
settings.type.global.edit=Configure global game settings
settings.type.special.enable=Enable specialized settings for this game
update=Update
update.channel.dev=Update to development version

View File

@ -313,7 +313,8 @@ settings.tabs.installers=自動安裝
settings.type=版本設定類型
settings.type.global=全域版本設定(使用該設定的版本共用一套設定)
settings.type.global.manage=全域遊戲設定
settings.type.special=單獨版本設定(不會影響到其他版本的設定)
settings.type.global.edit=編輯全域遊戲設定
settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本)
update=啟動器更新
update.channel.dev=更新到開發版

View File

@ -313,7 +313,8 @@ settings.tabs.installers=自动安装
settings.type=版本设置类型
settings.type.global=全局版本设置(使用该设置的版本共用一套设定)
settings.type.global.manage=全局游戏设置
settings.type.special=版本特定设置(不会影响到其他版本的设定)
settings.type.global.edit=编辑全局版本设置
settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本)
update=启动器更新
update.channel.dev=更新到开发版