diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index b6adc4200..e7474ca6b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -31,6 +31,9 @@ public final class Config { @SerializedName("last") private String selectedProfile = ""; + @SerializedName("backgroundType") + private int backgroundImageType = 0; + @SerializedName("bgpath") private String backgroundImage = null; @@ -100,6 +103,15 @@ public final class Config { Settings.INSTANCE.save(); } + public int getBackgroundImageType() { + return backgroundImageType; + } + + public void setBackgroundImageType(int backgroundImageType) { + this.backgroundImageType = backgroundImageType; + Settings.INSTANCE.save(); + } + public String getCommonDirectory() { return commonDirectory; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumBackgroundImage.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumBackgroundImage.java new file mode 100644 index 000000000..d6fe955a3 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumBackgroundImage.java @@ -0,0 +1,30 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * 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.setting; + +public enum EnumBackgroundImage { + DEFAULT, + CUSTOM; + + public static EnumBackgroundImage indexOf(int index) { + if (index >= values().length || index < 0) + return DEFAULT; + else + return values()[index]; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 40dcd6bb0..b0adc1eb6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -19,9 +19,11 @@ package org.jackhuang.hmcl.setting; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; +import javafx.scene.image.Image; import javafx.scene.text.Font; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.auth.Account; @@ -359,6 +361,52 @@ public class Settings { selectedAccount.get(); } + /**************************************** + * BACKGROUND * + ****************************************/ + + private final ImmediateStringProperty backgroundImage = new ImmediateStringProperty(this, "backgroundImage", SETTINGS.getBackgroundImage()) { + @Override + public void invalidated() { + super.invalidated(); + + SETTINGS.setBackgroundImage(get()); + } + }; + + public String getBackgroundImage() { + return backgroundImage.get(); + } + + public ImmediateStringProperty backgroundImageProperty() { + return backgroundImage; + } + + public void setBackgroundImage(String backgroundImage) { + this.backgroundImage.set(backgroundImage); + } + + private final ImmediateObjectProperty backgroundImageType = new ImmediateObjectProperty(this, "backgroundImageType", EnumBackgroundImage.indexOf(SETTINGS.getBackgroundImageType())) { + @Override + public void invalidated() { + super.invalidated(); + + SETTINGS.setBackgroundImageType(get().ordinal()); + } + }; + + public EnumBackgroundImage getBackgroundImageType() { + return backgroundImageType.get(); + } + + public ImmediateObjectProperty backgroundImageTypeProperty() { + return backgroundImageType; + } + + public void setBackgroundImageType(EnumBackgroundImage backgroundImageType) { + this.backgroundImageType.set(backgroundImageType); + } + /**************************************** * PROFILES * ****************************************/ diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 78f32cc12..93710e7bf 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -37,6 +37,7 @@ import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.Tooltip; +import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; import javafx.scene.paint.Color; @@ -44,15 +45,23 @@ import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle; import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.setting.EnumBackgroundImage; +import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.ui.animation.AnimationProducer; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionHandler; import org.jackhuang.hmcl.ui.construct.AdvancedListBox; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogWizardDisplayer; import org.jackhuang.hmcl.ui.wizard.*; +import org.jackhuang.hmcl.util.FileUtils; import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.StringUtils; +import java.io.File; +import java.util.Arrays; +import java.util.List; import java.util.Queue; +import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; public final class Decorator extends StackPane implements TaskExecutorDialogWizardDisplayer { @@ -167,6 +176,76 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza FXUtils.setOverflowHidden((Pane) lookup("#contentPlaceHolderRoot")); FXUtils.setOverflowHidden(drawerWrapper); + + loadBackground(); + } + + private void loadBackground() { + Image background; + + if (Settings.INSTANCE.getBackgroundImageType() == EnumBackgroundImage.DEFAULT) + background = searchBackgroundImage(new Image("/assets/img/background.jpg"), ""); + else + background = searchBackgroundImage(new Image("/assets/img/background.jpg"), Settings.INSTANCE.getBackgroundImage()); + + drawerWrapper.setBackground(new Background(new BackgroundImage(background, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)))); + } + + private static Image searchBackgroundImage(Image def, String customPath) { + Random random = new Random(); + boolean loaded = false; + Image background = def; + + // custom path + if (StringUtils.isNotBlank(customPath)) { + try { + background = new Image("file:" + customPath); + loaded = true; + } catch (IllegalArgumentException ignore) { + } + } + + // bgskin + if (!loaded) { + File backgroundImageFile = new File("bg"); + if (backgroundImageFile.isDirectory()) { + File[] backgroundPath = backgroundImageFile.listFiles(file -> StringUtils.containsOne(FileUtils.getExtension(file), "png", "jpg")); + if (backgroundPath != null && backgroundPath.length > 0) { + int index = random.nextInt(backgroundPath.length); + try { + background = new Image("file:" + backgroundPath[index].getAbsolutePath()); + loaded = true; + } catch (IllegalArgumentException ignore) { + } + } + } + } + + // background.png + if (!loaded) { + File backgroundImageFile = new File("background.png"); + if (backgroundImageFile.exists()) { + try { + background = new Image("file:" + backgroundImageFile.getAbsolutePath()); + loaded = true; + } catch (IllegalArgumentException ignore) { + } + } + } + + // background.jpg + if (!loaded) { + File backgroundImageFile = new File("background.jpg"); + if (backgroundImageFile.exists()) { + try { + background = new Image("file:" + backgroundImageFile.getAbsolutePath()); + loaded = true; + } catch (IllegalArgumentException ignore) { + } + } + } + + return background; } @FXML diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java index fd7eb0494..0e6bc03fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -123,7 +123,7 @@ public final class LeftPaneController { VersionListItem item = new VersionListItem(profile.getName()); RipplerContainer ripplerContainer = new RipplerContainer(item); item.setOnSettingsButtonClicked(() -> Controllers.getDecorator().showPage(new ProfilePage(profile))); - ripplerContainer.setRipplerFill(Paint.valueOf("#89E1F9")); + ripplerContainer.setRipplerFill(Paint.valueOf("#757de8")); ripplerContainer.setOnMouseClicked(e -> { // clean selected property for (Node node : profilePane.getChildren()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java index aa9f4972c..b9f4baf47 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -31,16 +31,17 @@ import javafx.scene.control.Tooltip; import javafx.scene.layout.StackPane; import javafx.scene.text.Font; import org.jackhuang.hmcl.Main; -import org.jackhuang.hmcl.setting.DownloadProviders; -import org.jackhuang.hmcl.setting.Locales; -import org.jackhuang.hmcl.setting.Proxies; -import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.ui.construct.FileItem; import org.jackhuang.hmcl.ui.construct.FontComboBox; +import org.jackhuang.hmcl.ui.construct.MultiFileItem; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Lang; +import java.util.Arrays; +import java.util.Collections; + public final class SettingsPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", Main.i18n("settings.launcher")); @@ -65,8 +66,6 @@ public final class SettingsPage extends StackPane implements DecoratorPage { @FXML private FileItem fileCommonLocation; @FXML - private FileItem fileBackgroundLocation; - @FXML private Label lblDisplay; @FXML private Label lblUpdate; @@ -76,6 +75,8 @@ public final class SettingsPage extends StackPane implements DecoratorPage { private JFXButton btnUpdate; @FXML private ScrollPane scroll; + @FXML + private MultiFileItem backgroundItem; { FXUtils.loadFXML(this, "/assets/fxml/setting.fxml"); @@ -134,6 +135,34 @@ public final class SettingsPage extends StackPane implements DecoratorPage { FXUtils.installTooltip(btnUpdate, 0, 5000, 0, new Tooltip(Main.i18n("update.tooltip"))); checkUpdate(); + + backgroundItem.loadChildren(Collections.singletonList( + backgroundItem.createChildren(Main.i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT) + )); + + FXUtils.bindString(backgroundItem.getTxtCustom(), Settings.INSTANCE.backgroundImageProperty()); + + backgroundItem.setCustomUserData(EnumBackgroundImage.CUSTOM); + backgroundItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Settings.INSTANCE.getBackgroundImageType()).findFirst().ifPresent(it -> it.setSelected(true)); + + Settings.INSTANCE.backgroundImageProperty().setChangedListener(it -> initBackgroundItemSubtitle()); + Settings.INSTANCE.backgroundImageTypeProperty().setChangedListener(it -> initBackgroundItemSubtitle()); + initBackgroundItemSubtitle(); + + backgroundItem.setToggleSelectedListener(newValue -> { + Settings.INSTANCE.setBackgroundImageType((EnumBackgroundImage) newValue.getUserData()); + }); + } + + private void initBackgroundItemSubtitle() { + switch (Settings.INSTANCE.getBackgroundImageType()) { + case DEFAULT: + backgroundItem.setSubtitle(Main.i18n("launcher.background.default")); + break; + case CUSTOM: + backgroundItem.setSubtitle(Settings.INSTANCE.getBackgroundImage()); + break; + } } public String getTitle() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java index 8a14d4e87..8bd1ec0bc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.*; import javafx.application.Platform; -import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.control.Label; @@ -178,34 +177,24 @@ public final class VersionSettingsController { FXUtils.bindBoolean(chkShowLogs, versionSetting.showLogsProperty()); FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty()); - String javaGroupKey = "java_group.listener"; - - Lang.get(javaItem.getGroup().getProperties(), javaGroupKey, ChangeListener.class) - .ifPresent(javaItem.getGroup().selectedToggleProperty()::removeListener); - boolean flag = false; - JFXRadioButton defaultToggle = null; + Toggle defaultToggle = null; for (Toggle toggle : javaItem.getGroup().getToggles()) { - if (toggle instanceof JFXRadioButton) { - if (toggle.getUserData() == Lang.invoke(versionSetting::getJavaVersion)) { - toggle.setSelected(true); - flag = true; - } else if (toggle.getUserData() == JavaVersion.fromCurrentEnvironment()) { - defaultToggle = (JFXRadioButton) toggle; - } + if (toggle.getUserData() == Lang.invoke(versionSetting::getJavaVersion)) { + toggle.setSelected(true); + flag = true; + } else if (toggle.getUserData() == JavaVersion.fromCurrentEnvironment()) { + defaultToggle = toggle; } } - ChangeListener listener = (a, b, newValue) -> { - if (newValue == javaItem.getRadioCustom()) { + javaItem.setToggleSelectedListener(newValue -> { + if (javaItem.isCustomToggle(newValue)) { versionSetting.setJava("Custom"); } else { versionSetting.setJava(((JavaVersion) newValue.getUserData()).getVersion()); } - }; - - javaItem.getGroup().getProperties().put(javaGroupKey, listener); - javaItem.getGroup().selectedToggleProperty().addListener(listener); + }); if (!flag) { Optional.ofNullable(defaultToggle).ifPresent(t -> t.setSelected(true)); @@ -215,49 +204,30 @@ public final class VersionSettingsController { versionSetting.javaProperty().setChangedListener(it -> initJavaSubtitle(versionSetting)); initJavaSubtitle(versionSetting); - - String globalGroupKey = "global_group.listener"; - - Lang.get(globalItem.getGroup().getProperties(), globalGroupKey, ChangeListener.class) - .ifPresent(globalItem.getGroup().selectedToggleProperty()::removeListener); - ChangeListener globalListener = (a, b, newValue) -> { + if (versionSetting.isUsesGlobal()) + globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.TRUE).findFirst().ifPresent(it -> it.setSelected(true)); + else + globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.FALSE).findFirst().ifPresent(it -> it.setSelected(true)); + globalItem.setToggleSelectedListener(newValue -> { if ((Boolean) newValue.getUserData()) profile.globalizeVersionSetting(versionId); else profile.specializeVersionSetting(versionId); Platform.runLater(() -> loadVersionSetting(profile, versionId)); - }; - if (versionSetting.isUsesGlobal()) - globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.TRUE).findFirst().ifPresent(it -> it.setSelected(true)); - else - globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.FALSE).findFirst().ifPresent(it -> it.setSelected(true)); - globalItem.getGroup().getProperties().put(globalGroupKey, globalListener); - globalItem.getGroup().selectedToggleProperty().addListener(globalListener); - versionSetting.usesGlobalProperty().setChangedListener(it -> initUsesGlobalSubtitle(versionSetting)); - initUsesGlobalSubtitle(versionSetting); + }); - String gameDirKey = "game_dir.listener"; - Lang.get(gameDirItem.getGroup().getProperties(), gameDirKey, ChangeListener.class) - .ifPresent(gameDirItem.getGroup().selectedToggleProperty()::removeListener); + versionSetting.usesGlobalProperty().setChangedListenerAndOperate(it -> + globalItem.setSubtitle(Main.i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special"))); - for (Toggle toggle : gameDirItem.getGroup().getToggles()) { - if (toggle instanceof JFXRadioButton) { - if (toggle.getUserData() == versionSetting.getGameDirType()) { - toggle.setSelected(true); - flag = true; - } - } - } + gameDirItem.getGroup().getToggles().stream() + .filter(it -> it.getUserData() == versionSetting.getGameDirType()) + .findFirst().ifPresent(toggle -> toggle.setSelected(true)); gameDirItem.setCustomUserData(EnumGameDirectory.CUSTOM); - - ChangeListener gameDirListener = (a, b, newValue) -> { + gameDirItem.setToggleSelectedListener(newValue -> { versionSetting.setGameDirType((EnumGameDirectory) newValue.getUserData()); - }; - - gameDirItem.getGroup().getProperties().put(gameDirKey, gameDirListener); - gameDirItem.getGroup().selectedToggleProperty().addListener(gameDirListener); + }); versionSetting.gameDirProperty().setChangedListener(it -> initGameDirSubtitle(versionSetting)); versionSetting.gameDirTypeProperty().setChangedListener(it -> initGameDirSubtitle(versionSetting)); @@ -279,10 +249,6 @@ public final class VersionSettingsController { gameDirItem.setSubtitle(profile.getRepository().getRunDirectory(versionId).getAbsolutePath()); } - private void initUsesGlobalSubtitle(VersionSetting versionSetting) { - globalItem.setSubtitle(Main.i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special")); - } - @FXML private void onShowAdvanced() { if (!rootPane.getChildren().contains(advancedSettingsPane)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java index c68166351..c167cc55d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java @@ -30,6 +30,7 @@ import javafx.collections.ObservableList; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; @@ -43,6 +44,7 @@ import org.jackhuang.hmcl.ui.SVG; import java.io.File; import java.util.Collection; +import java.util.function.Consumer; public class MultiFileItem extends ComponentList { private final StringProperty customTitle = new SimpleStringProperty(this, "customTitle", Main.i18n("selector.custom")); @@ -58,6 +60,8 @@ public class MultiFileItem extends ComponentList { private final VBox pane = new VBox(); private final boolean hasCustom; + private Consumer toggleSelectedListener; + public MultiFileItem(@NamedArg(value = "hasCustom", defaultValue = "true") boolean hasCustom) { this.hasCustom = hasCustom; @@ -100,6 +104,11 @@ public class MultiFileItem extends ComponentList { if (hasCustom) pane.getChildren().add(custom); addChildren(pane); + + group.selectedToggleProperty().addListener((a, b, newValue) -> { + if (toggleSelectedListener != null) + toggleSelectedListener.accept(newValue); + }); } public Node createChildren(String title) { @@ -175,8 +184,12 @@ public class MultiFileItem extends ComponentList { radioCustom.setUserData(userData); } - public JFXRadioButton getRadioCustom() { - return radioCustom; + public boolean isCustomToggle(Toggle toggle) { + return radioCustom == toggle; + } + + public void setToggleSelectedListener(Consumer consumer) { + toggleSelectedListener = consumer; } public StringProperty customTextProperty() { diff --git a/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css b/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css index 270ef424a..6d674c73f 100644 --- a/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css +++ b/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css @@ -54,7 +54,7 @@ } .tab-header-background { - -fx-background: gray; + -fx-background-color: #757de8; } /******************************************************************************* @@ -1002,8 +1002,6 @@ } .jfx-decorator-drawer { - -fx-background-image: url("/assets/img/background.jpg"); - -fx-background-size: cover; } .resize-border { diff --git a/HMCL/src/main/resources/assets/fxml/setting.fxml b/HMCL/src/main/resources/assets/fxml/setting.fxml index 8a1cd957f..6a091edc0 100644 --- a/HMCL/src/main/resources/assets/fxml/setting.fxml +++ b/HMCL/src/main/resources/assets/fxml/setting.fxml @@ -7,6 +7,7 @@ + @@ -32,8 +33,11 @@ - - + + + + diff --git a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml index fa394f70e..7a83c4947 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml @@ -42,7 +42,7 @@ - - + - + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index f53f771c0..15aba7afd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -174,11 +174,12 @@ launch.unsupported_launcher_version=Sorry, the launcher cannot launch minecraft, launch.wrong_javadir=Incorrect Java directory, will reset to default Java directory. launcher=Launcher -launcher.background_location=Background Location -launcher.background_tooltip=The laucher uses a default background.\nIf you use custom background.png, link it and it will be used.\nIf there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.\nIf you set the background setting, this app will use it. -launcher.choose_bgpath=Choose background path. -launcher.choose_commonpath=Choose common path. -launcher.common_location=Common Directory +launcher.background=Background Image +launcher.background.choose=Choose background path. +launcher.background.default=Default +launcher.background.tooltip=The laucher uses a default background.\nIf you use custom background.png, link it and it will be used.\nIf there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.\nIf you set the background setting, this app will use it. +launcher.common_directory=Common Directory +launcher.common_directory.choose=Choose common directory. launcher.contact=Contact Us launcher.crash=Hello Minecraft! Launcher has crashed! launcher.crash_out_dated=Hello Minecraft! Launcher has crashed! Your launcher is outdated. Update it! @@ -326,7 +327,6 @@ settings.advanced.wrapper_launcher=Wrapper Launcher(i.e. optirun...) settings.cannot_remove_default_config=Cannot remove the default configution. settings.choose_gamedir=Choose Game Directory -settings.choose_javapath=Choose Java Directory. settings.custom=Custom settings.default=Default settings.failed_load=Failed to load settings file. Remove it? @@ -336,6 +336,7 @@ settings.game.dimension=Game Window Dimension settings.game.exploration=Explore settings.game.fullscreen=Fullscreen settings.game.java_directory=Java Dir +settings.game.java_directory.choose=Choose Java Directory. settings.game.management=Manage settings.icon=Game Icon diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index aa0c3c3e4..7d67b42b0 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -174,11 +174,12 @@ launch.unsupported_launcher_version=对不起,本启动器现在可能不能 launch.wrong_javadir=错误的Java路径,将自动重置为默认Java路径。 launcher=启动器 -launcher.background_location=背景地址 -launcher.background_tooltip=启动器默认使用自带的背景\n如果当前目录有background.png,则会使用该文件作为背景\n如果当前目录有bg子目录,则会随机使用里面的一张图作为背景\n如果该背景地址被修改,则会使用背景地址里的一张图作为背景\n背景地址允许有多个地址,使用半角分号";"(不包含双引号)分隔 -launcher.choose_bgpath=选择背景路径 -launcher.choose_commonpath=选择公共路径 -launcher.common_location=公共文件夹 +launcher.background=背景地址 +launcher.background.choose=选择背景路径 +launcher.background.default=默认 +launcher.background.tooltip=启动器默认使用自带的背景\n如果当前目录有background.png,则会使用该文件作为背景\n如果当前目录有bg子目录,则会随机使用里面的一张图作为背景\n如果该背景地址被修改,则会使用背景地址里的一张图作为背景\n背景地址允许有多个地址,使用半角分号";"(不包含双引号)分隔 +launcher.common_directory=公共文件夹 +launcher.common_directory.choose=选择公共文件夹 launcher.contact=联系我们 launcher.crash=Hello Minecraft!遇到了无法处理的错误,请复制下列内容并通过mcbbs、贴吧、Github或Minecraft Forum反馈bug。 launcher.crash_out_dated=Hello Minecraft! Launcher遇到了无法处理的错误,已检测到您的启动器不是最新版本,请更新后再试! @@ -326,7 +327,6 @@ settings.advanced.wrapper_launcher=前置指令(不必填写,如optirun) settings.cannot_remove_default_config=不能删除默认配置 settings.choose_gamedir=选择游戏路径 -settings.choose_javapath=选择Java路径 settings.custom=自定义 settings.default=默认 settings.failed_load=设置文件加载失败,可能是升级了启动器或被人工修改造成错误,是否清除? @@ -336,6 +336,7 @@ settings.game.dimension=游戏窗口分辨率 settings.game.exploration=浏览 settings.game.fullscreen=全屏 settings.game.java_directory=Java路径 +settings.game.java_directory.choose=选择Java路径 settings.game.management=管理 settings.icon=游戏图标 diff --git a/HMCL/src/main/resources/assets/svg/delete-white.fxml b/HMCL/src/main/resources/assets/svg/delete-white.fxml new file mode 100644 index 000000000..6d7341964 --- /dev/null +++ b/HMCL/src/main/resources/assets/svg/delete-white.fxml @@ -0,0 +1,3 @@ + + + diff --git a/HMCL/src/main/resources/assets/svg/export.fxml b/HMCL/src/main/resources/assets/svg/export.fxml index 217c370d0..d96a43f9e 100644 --- a/HMCL/src/main/resources/assets/svg/export.fxml +++ b/HMCL/src/main/resources/assets/svg/export.fxml @@ -1,3 +1,3 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/svg/folder-open.fxml b/HMCL/src/main/resources/assets/svg/folder-open.fxml index 010b10947..6a734b3d7 100644 --- a/HMCL/src/main/resources/assets/svg/folder-open.fxml +++ b/HMCL/src/main/resources/assets/svg/folder-open.fxml @@ -1,3 +1,3 @@ - + diff --git a/HMCL/src/main/resources/assets/svg/wrench-white.fxml b/HMCL/src/main/resources/assets/svg/wrench-white.fxml new file mode 100644 index 000000000..f3f4f9faf --- /dev/null +++ b/HMCL/src/main/resources/assets/svg/wrench-white.fxml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ImmediateBooleanProperty.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ImmediateBooleanProperty.java index 3d3fcd19d..af637d310 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ImmediateBooleanProperty.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ImmediateBooleanProperty.java @@ -55,6 +55,11 @@ public class ImmediateBooleanProperty extends SimpleBooleanProperty { this.listener = Objects.requireNonNull(listener); } + public void setChangedListenerAndOperate(Consumer listener) { + this.listener = Objects.requireNonNull(listener); + listener.accept(get()); + } + public ImmediateBooleanProperty(Object bean, String name, boolean initialValue) { super(bean, name, initialValue); addListener(changeListener); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java index c4f0c1beb..961705aa9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StringUtils.java @@ -190,6 +190,13 @@ public final class StringUtils { return false; } + public static boolean containsOne(String pattern, String... targets) { + for (String target : targets) + if (pattern.toLowerCase().contains(target.toLowerCase())) + return true; + return false; + } + public static List tokenize(String str) { if (str == null) return new LinkedList<>();