background customizing

This commit is contained in:
huangyuhui
2018-02-13 18:37:33 +08:00
parent 6443770670
commit 69ea41056d
20 changed files with 286 additions and 87 deletions

View File

@@ -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;
}

View File

@@ -0,0 +1,30 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
public enum EnumBackgroundImage {
DEFAULT,
CUSTOM;
public static EnumBackgroundImage indexOf(int index) {
if (index >= values().length || index < 0)
return DEFAULT;
else
return values()[index];
}
}

View File

@@ -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<EnumBackgroundImage> backgroundImageType = new ImmediateObjectProperty<EnumBackgroundImage>(this, "backgroundImageType", EnumBackgroundImage.indexOf(SETTINGS.getBackgroundImageType())) {
@Override
public void invalidated() {
super.invalidated();
SETTINGS.setBackgroundImageType(get().ordinal());
}
};
public EnumBackgroundImage getBackgroundImageType() {
return backgroundImageType.get();
}
public ImmediateObjectProperty<EnumBackgroundImage> backgroundImageTypeProperty() {
return backgroundImageType;
}
public void setBackgroundImageType(EnumBackgroundImage backgroundImageType) {
this.backgroundImageType.set(backgroundImageType);
}
/****************************************
* PROFILES *
****************************************/

View File

@@ -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

View File

@@ -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())

View File

@@ -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() {

View File

@@ -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<Toggle> 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<Toggle> 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<Toggle> 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))

View File

@@ -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<Toggle> 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<Toggle> consumer) {
toggleSelectedListener = consumer;
}
public StringProperty customTextProperty() {

View File

@@ -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 {

View File

@@ -7,6 +7,7 @@
<?import org.jackhuang.hmcl.ui.construct.ComponentList?>
<?import org.jackhuang.hmcl.ui.construct.FileItem?>
<?import org.jackhuang.hmcl.ui.construct.FontComboBox?>
<?import org.jackhuang.hmcl.ui.construct.MultiFileItem?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
type="StackPane">
@@ -32,8 +33,11 @@
</right>
</BorderPane>
<FileItem fx:id="fileCommonLocation" name="%launcher.common_location" title="%launcher.choose_commonpath" tooltip="%settings.launcher.common_path.tooltip" />
<!--FileItem fx:id="fileBackgroundLocation" name="%launcher.background_location" title="%launcher.choose_bgpath" tooltip="%launcher.background_tooltip" /-->
<FileItem fx:id="fileCommonLocation" name="%launcher.common_directory" title="%launcher.common_directory.choose" tooltip="%settings.launcher.common_path.tooltip" />
<MultiFileItem fx:id="backgroundItem" title="%launcher.background" chooserTitle="%launcher.background.choose"
hasSubtitle="true" customText="%settings.custom" />
<BorderPane><left><Label text="%settings.launcher.download_source" BorderPane.alignment="CENTER_LEFT" /></left><right><JFXComboBox fx:id="cboDownloadSource">
<items>
<FXCollections fx:factory="observableArrayList">

View File

@@ -42,7 +42,7 @@
</right>
</BorderPane>
<MultiFileItem fx:id="javaItem" title="%settings.game.java_directory" chooserTitle="%settings.choose_javapath"
<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="%profile.instance_directory" chooserTitle="%settings.choose_gamedir"

View File

@@ -26,7 +26,7 @@
<JFXButton fx:id="btnDelete" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onDelete"
styleClass="toggle-icon3" ripplerFill="white">
<graphic>
<fx:include source="/assets/svg/delete-black.fxml"/>
<fx:include source="/assets/svg/delete-white.fxml"/>
</graphic>
</JFXButton>
<JFXButton fx:id="btnExport" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onExport"
@@ -44,7 +44,7 @@
<JFXButton fx:id="btnManagementMenu" maxHeight="28.0" minHeight="28.0" onMouseClicked="#onManagementMenu"
styleClass="toggle-icon3" ripplerFill="white">
<graphic>
<fx:include source="/assets/svg/wrench-black.fxml"/>
<fx:include source="/assets/svg/wrench-white.fxml"/>
</graphic>
</JFXButton>
</HBox>

View File

@@ -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

View File

@@ -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=游戏图标

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.SVGPath?>
<javafx.scene.shape.SVGPath fill="white" content="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" />

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.SVGPath?>
<javafx.scene.shape.SVGPath fill="black" content="M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z" />
<javafx.scene.shape.SVGPath fill="white" content="M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z" />

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.SVGPath?>
<javafx.scene.shape.SVGPath fill="black" content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" />
<javafx.scene.shape.SVGPath fill="white" content="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" />

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.SVGPath?>
<javafx.scene.shape.SVGPath fill="white" content="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z" />

View File

@@ -55,6 +55,11 @@ public class ImmediateBooleanProperty extends SimpleBooleanProperty {
this.listener = Objects.requireNonNull(listener);
}
public void setChangedListenerAndOperate(Consumer<Boolean> listener) {
this.listener = Objects.requireNonNull(listener);
listener.accept(get());
}
public ImmediateBooleanProperty(Object bean, String name, boolean initialValue) {
super(bean, name, initialValue);
addListener(changeListener);

View File

@@ -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<String> tokenize(String str) {
if (str == null)
return new LinkedList<>();