Compare commits

..
Author SHA1 Message Date
yushijinhun 00f1173bac Add translation for CharacterDeletedException 2019-02-05 14:56:11 +08:00
yushijinhun 4721fcea66 allow characterName/authserverName to be changed at runtime 2019-02-05 02:09:39 +08:00
yushijinhun 5ea63273be check validity of YggdrasilSession response 2019-02-05 01:46:48 +08:00
yushijinhun 7cee25aab2 Fix concurrent problems in TexturesLoader.Selector 2019-02-05 00:15:17 +08:00
yushijinhun 9298f5e030 Account Refactor 2019-02-04 23:12:40 +08:00
yushijinhun 93f943d40c Fix crash in version settings
introduced in d75c3bbf96
2019-02-04 17:06:20 +08:00
Feng Chang f20c11a4e2 Ensure sequential execution of configuration writer threads (#516)
* Ensure sequential execution of configuration writer threads

Signed-off-by: Chang Feng <chang_196700@hotmail.com>

* Change method to add synchronized to action

Signed-off-by: Chang Feng <chang_196700@hotmail.com>
2019-02-04 02:18:24 +08:00
yushijinhun 0c25f31493 fix npe 2019-01-26 22:50:51 +08:00
yushijinhun 8d774e267f Show register link in login dialog
https://github.com/yushijinhun/authlib-injector/issues/25
2019-01-26 15:19:17 +08:00
yushijinhun 6c1de5d485 Improve tooltip UX 2019-01-26 13:33:59 +08:00
yushijinhun 77c86ed3bc Add tooltip for authlib-injector accounts 2019-01-26 13:17:45 +08:00
yushijinhun d75c3bbf96 Refactor TwoLineListItem 2019-01-26 13:06:56 +08:00
huanghongxun 8bb6cb714c use result of prev task instead of AutoTypingMap 2019-01-22 17:15:03 +08:00
huanghongxun 28d002f6d3 Do not schedule task if preExecute and postExecute are not overrided. 2019-01-22 16:46:11 +08:00
huanghongxun 78fcc69d29 Fixed not displaying "Home" icon. Mentioned in #513 2019-01-22 16:28:41 +08:00
huanghongxun cdfae54ab9 Fixed costly time consumption reading level.dat. Mentioned in #512 2019-01-22 16:11:31 +08:00
huanghongxun 0813211c20 Use JFXListView in place of custom components to accelerate rendering 2019-01-22 16:01:00 +08:00
huanghongxun 056a4eead2 Add comments to LiteLoaderInstallTask and OptiFineInstallTask 2019-01-22 15:54:59 +08:00
huanghongxun 2635d31425 Fix not correctly adding "--tweakClass" for MultiMC modpack 2019-01-22 15:52:57 +08:00
huanghongxun 76d35af5b9 MultiMC modpack patch json file may have "+libraries" or "libraries" 2019-01-22 15:51:52 +08:00
huanghongxun bcff1695d3 Refactor MaintainTask 2019-01-22 15:50:49 +08:00
huanghongxun 3d04447c2f Load world asynchronously 2019-01-22 14:59:01 +08:00
huanghongxun 2736b88a10 Add some promise-like method to TaskResult 2019-01-22 14:58:00 +08:00
huanghongxun 0804a2fbf8 Merge TaskCallable and TaskCallable2 2019-01-22 14:56:48 +08:00
huanghongxun 7224ed6a7d Fix missorting optifine versions 2019-01-16 12:34:13 +08:00
huanghongxun c41737364c Prevent from potential conflict that a MultiMC modpack has ".minecraft" and "minecraft" at the same time 2019-01-13 17:10:23 +08:00
huanghongxun 320e579844 Remove game deletion and renaming action in game settings page 2019-01-13 16:55:07 +08:00
huanghongxun fc3f2e045b Retry fetching remote text file when downloading had been terminated 2019-01-13 16:50:54 +08:00
huanghongxun 481b47bf10 Fix #508. MultiMC stores files in ".minecraft" instead 2019-01-13 16:50:21 +08:00
huanghongxun 0fb87f0b1d Accept modpack drag 2019-01-13 11:55:55 +08:00
huanghongxun 1252d7700f Update alert prompt of Forge 2760 2019-01-11 21:23:26 +08:00
huanghongxun 30c2d88f62 Use spinnerPane in ModListPage 2019-01-11 21:18:26 +08:00
huanghongxun 718a98d7ec Fix alerting Forge conflicts with LiteLoader but actually not 2019-01-11 21:17:02 +08:00
huanghongxun fb3ba220b6 Fix redownloading disabled mods for curse modpack 2019-01-09 13:18:04 +08:00
yushijinhun d655c9ec6b Use /* instead of /** for license header
see: https://github.com/mycila/license-maven-plugin/issues/118
2019-01-05 19:04:24 +08:00
yushijinhun 8a67f33cf6 Update license year to 2019 2019-01-05 18:50:16 +08:00
yushijinhun 2e53688c52 Add gradle default tasks: clean, build 2019-01-05 18:49:28 +08:00
yushijinhun 11ce04fba4 Add dependency org.jetbrains.annotations 2019-01-05 18:49:02 +08:00
yushijinhun 8b191e4a3b Fix grey auth server list cell 2018-12-31 19:43:36 +08:00
huanghongxun 6405263616 Merge branch 'javafx' of https://github.com/huanghongxun/HMCL into javafx 2018-12-30 19:29:27 +08:00
huanghongxun a2119ab008 Remove "MCBBS" in introduction to the functinoality of modpack install 2018-12-30 19:28:53 +08:00
Haowei Wen b21d8f094a Merge pull request #504 from xfl03/xfl03-jfxpatch-1
Fixed #503
2018-12-23 02:53:10 +08:00
Alexander Xia 90c41a83b1 Fixed #503 2018-12-23 02:49:18 +08:00
huanghongxun a1ec774089 Remind user to move files when switch game working directory 2018-12-22 00:56:05 +08:00
huanghongxun 631056064a Add tooltip about what would be cleaned in game directory 2018-12-22 00:25:19 +08:00
huanghongxun 97e90de71e Add refresh button in mod list page 2018-12-21 01:12:41 +08:00
huanghongxun bbaed35160 Add button to reveal world directory in explorer 2018-12-21 00:40:50 +08:00
huanghongxun 778f26d55f Support manually created world pack 2018-12-21 00:34:46 +08:00
huanghongxun fab5bdc2e1 Auto detect world and datapack's encoding 2018-12-20 20:27:32 +08:00
huanghongxun b7723a88c3 Add dragging world pack to GUI for installation 2018-12-20 20:24:23 +08:00
huanghongxun 1d2b59d5a2 Fix not showing spinner when clicked accept button 2018-12-20 20:07:00 +08:00
huanghongxun 7d42c0f581 Change "redownload asset index" to "Update game asset files" 2018-12-20 19:30:35 +08:00
huanghongxun bfe7398e17 Fixed #501 2018-12-18 13:44:30 +08:00
huanghongxun c4f0a6a197 Suppress IllegalStateException. Closes #500 2018-12-18 13:32:38 +08:00
huanghongxun 1ca9d0fa2c Backup when updating modpack 2018-12-18 13:08:02 +08:00
huanghongxun a015585bd1 Let TaskExecutorDialogPane close itself when finished 2018-12-18 12:35:03 +08:00
huanghongxun bc34427793 Add doDependenciesSucceeded in Task 2018-12-18 00:26:31 +08:00
huanghongxun 0fe867cd93 Fixed #499 2018-12-17 23:31:47 +08:00
yushijinhun 70f0393bde Fix proxy options are passed to game even it's disabled 2018-12-16 16:03:29 +08:00
yushijinhun 9f060be3fd Fix #502
* Check if port is valid before setting it
* Validate user input
* Change proxyPort to int
2018-12-16 15:49:57 +08:00
yushijinhun 176968d883 Fix #498 2018-12-16 00:31:37 +08:00
huanghongxun e6bd55aa69 Merge branch 'javafx' of https://github.com/huanghongxun/HMCL into javafx 2018-12-13 00:43:15 +08:00
huanghongxun f5ffa875b8 Auto detect encoding of compressed packs 2018-12-13 00:42:52 +08:00
huanghongxun 2cb23cbfcb Log messages at finer and finest level 2018-12-11 15:47:12 +08:00
huanghongxun 31dc9b0925 Delete game whose installation fails 2018-12-11 15:44:17 +08:00
huanghongxun af7cd9a821 Merge pull request #496 from yushijinhun/gpl-additional-terms
Add additional terms under GPLv3 section 7
2018-12-09 00:14:58 +08:00
yushijinhun b34a64f425 Add additional terms under GPLv3 section 7 2018-12-08 23:18:31 +08:00
huanghongxun 11820e31a8 Merge pull request #495 from yushijinhun/license
Update license header
2018-12-08 21:27:10 +08:00
yushijinhun 672b6054a6 Format license headers 2018-12-08 21:13:03 +08:00
yushijinhun d2486732d2 Prevent translation contributors being removed by license-gradle-plugin 2018-12-08 21:11:10 +08:00
yushijinhun 924067e4dd Specify GPL version in the readme link
in case FSF updates it
2018-12-08 21:11:10 +08:00
yushijinhun 7820f748a0 Restore original GPLv3 license
From: https://www.gnu.org/licenses/gpl-3.0.txt
2018-12-08 21:11:10 +08:00
yushijinhun e8757deb0d Use license-gradle-plugin 2018-12-08 21:11:08 +08:00
yushijinhun c371924dc0 Remove Fonts class as it has never been used 2018-12-08 19:39:09 +08:00
yushijinhun cf28b27d50 Remove HMCLCore usage instructions 2018-12-08 19:14:56 +08:00
huanghongxun b78f9c8cd5 Merge branch 'javafx' of https://github.com/huanghongxun/HMCL into javafx 2018-12-02 20:03:15 +08:00
huanghongxun 91bd67dc26 Restore default cache directory if needed. Closes #489 2018-12-02 20:02:22 +08:00
huanghongxun 0671b49c98 Fix bubble ui 2018-12-02 18:48:22 +08:00
yushijinhun 900f483a03 Fix #493 2018-12-02 14:57:37 +08:00
yushijinhun 4d7af2e68b Fix #492
Related: 4d73187376
2018-12-02 14:54:58 +08:00
yushijinhun db59dcea65 Log exception when failing to load version list
see https://github.com/huanghongxun/HMCL/issues/489#issuecomment-443427026
2018-12-02 13:55:25 +08:00
420 changed files with 4536 additions and 3140 deletions

No files matched your search

@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl;
@@ -1,188 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 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.game;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
import org.jackhuang.hmcl.auth.yggdrasil.Texture;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Scheduler;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.DialogController;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;
public final class AccountHelper {
private AccountHelper() {}
public static final File SKIN_DIR = Metadata.HMCL_DIRECTORY.resolve("skins").toFile();
public static void loadSkins() {
for (Account account : Accounts.getAccounts()) {
if (account instanceof YggdrasilAccount) {
new SkinLoadTask((YggdrasilAccount) account, false).start();
}
}
}
public static Task loadSkinAsync(YggdrasilAccount account) {
return new SkinLoadTask(account, false);
}
public static Task refreshSkinAsync(YggdrasilAccount account) {
return new SkinLoadTask(account, true);
}
private static File getSkinFile(UUID uuid) {
return new File(SKIN_DIR, uuid + ".png");
}
public static Image getSkin(YggdrasilAccount account) {
return getSkin(account, 1);
}
public static Image getSkin(YggdrasilAccount account, double scaleRatio) {
UUID uuid = account.getUUID();
if (uuid == null)
return getSteveSkin(scaleRatio);
File file = getSkinFile(uuid);
if (file.exists()) {
Image original = new Image("file:" + file.getAbsolutePath());
return new Image("file:" + file.getAbsolutePath(),
original.getWidth() * scaleRatio,
original.getHeight() * scaleRatio,
false, false);
}
return getDefaultSkin(uuid, scaleRatio);
}
public static Image getSkinImmediately(YggdrasilAccount account, GameProfile profile, double scaleRatio) throws Exception {
File file = getSkinFile(profile.getId());
downloadSkin(account, profile, true);
if (!file.exists())
return getDefaultSkin(profile.getId(), scaleRatio);
String url = "file:" + file.getAbsolutePath();
return scale(url, scaleRatio);
}
public static Image getHead(Image skin, int scaleRatio) {
final int size = 8 * scaleRatio;
final int faceOffset = (int) Math.round(scaleRatio * 4d / 9d);
BufferedImage image = SwingFXUtils.fromFXImage(skin, null);
BufferedImage head = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = head.createGraphics();
g2d.drawImage(image, faceOffset, faceOffset, size - faceOffset, size - faceOffset,
size, size, size + size, size + size, null);
if (image.getHeight() > 32) {
g2d.drawImage(image, 0, 0, size, size,
40 * scaleRatio, 8 * scaleRatio, 48 * scaleRatio, 16 * scaleRatio, null);
}
return SwingFXUtils.toFXImage(head, null);
}
private static class SkinLoadTask extends Task {
private final YggdrasilAccount account;
private final boolean refresh;
private final List<Task> dependencies = new LinkedList<>();
public SkinLoadTask(YggdrasilAccount account, boolean refresh) {
this.account = account;
this.refresh = refresh;
}
@Override
public Scheduler getScheduler() {
return Schedulers.io();
}
@Override
public Collection<Task> getDependencies() {
return dependencies;
}
@Override
public void execute() throws Exception {
if (!account.isLoggedIn() && (account.getCharacter() == null || refresh))
DialogController.logIn(account);
downloadSkin(account, refresh);
}
}
private static void downloadSkin(YggdrasilAccount account, GameProfile profile, boolean refresh) throws Exception {
account.clearCache();
File file = getSkinFile(profile.getId());
if (!refresh && file.exists())
return;
Optional<Texture> texture = account.getSkin(profile);
if (!texture.isPresent()) return;
String url = texture.get().getUrl();
new FileDownloadTask(NetworkUtils.toURL(url), file).run();
}
private static void downloadSkin(YggdrasilAccount account, boolean refresh) throws Exception {
account.clearCache();
if (account.getCharacter() == null) return;
File file = getSkinFile(account.getUUID());
if (!refresh && file.exists())
return;
Optional<Texture> texture = account.getSkin();
if (!texture.isPresent()) return;
String url = texture.get().getUrl();
new FileDownloadTask(NetworkUtils.toURL(url), file).run();
}
public static Image scale(String url, double scaleRatio) {
Image origin = new Image(url);
return new Image(url,
origin.getWidth() * scaleRatio,
origin.getHeight() * scaleRatio,
false, false);
}
public static Image getSteveSkin(double scaleRatio) {
return scale("/assets/img/steve.png", scaleRatio);
}
public static Image getAlexSkin(double scaleRatio) {
return scale("/assets/img/alex.png", scaleRatio);
}
public static Image getDefaultSkin(UUID uuid, double scaleRatio) {
int type = uuid.hashCode() & 1;
if (type == 1)
return getAlexSkin(scaleRatio);
else
return getSteveSkin(scaleRatio);
}
}
@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
import javafx.beans.property.SimpleStringProperty;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -73,7 +73,7 @@ public final class HMCLModpackInstallTask extends Task {
}
} catch (JsonParseException | IOException ignore) {
}
dependents.add(new ModpackInstallTask<>(zipFile, run, "/minecraft", it -> !"pack.json".equals(it), config));
dependents.add(new ModpackInstallTask<>(zipFile, run, modpack.getEncoding(), "/minecraft", it -> !"pack.json".equals(it), config));
}
@Override
@@ -91,7 +91,7 @@ public final class HMCLModpackInstallTask extends Task {
String json = CompressingUtils.readTextZipEntry(zipFile, "minecraft/pack.json");
Version version = JsonUtils.GSON.fromJson(json, Version.class).setId(name).setJar(null);
dependencies.add(new VersionJsonSaveTask(repository, version));
dependencies.add(new MinecraftInstanceTask<>(zipFile, "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)));
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/minecraft", modpack, MODPACK_TYPE, repository.getModpackConfiguration(name)));
}
public static final String MODPACK_TYPE = "HMCL";
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -24,8 +24,9 @@ import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.List;
/**
@@ -75,14 +76,15 @@ public final class HMCLModpackManager {
* Read the manifest in a HMCL modpack.
*
* @param file a HMCL modpack file.
* @param encoding encoding of modpack zip file.
* @throws IOException if the file is not a valid zip file.
* @throws JsonParseException if the manifest.json is missing or malformed.
* @return the manifest of HMCL modpack.
*/
public static Modpack readHMCLModpackManifest(File file) throws IOException, JsonParseException {
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json");
Modpack manifest = JsonUtils.fromNonNullJson(manifestJson, Modpack.class);
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json");
public static Modpack readHMCLModpackManifest(Path file, Charset encoding) throws IOException, JsonParseException {
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json", encoding);
Modpack manifest = JsonUtils.fromNonNullJson(manifestJson, Modpack.class).setEncoding(encoding);
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json", encoding);
Version game = JsonUtils.fromNonNullJson(gameJson, Version.class);
if (game.getJar() == null)
if (StringUtils.isBlank(manifest.getVersion()))
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -30,7 +30,6 @@ import org.jackhuang.hmcl.launch.*;
import org.jackhuang.hmcl.mod.CurseCompletionException;
import org.jackhuang.hmcl.mod.CurseCompletionTask;
import org.jackhuang.hmcl.mod.ModpackConfiguration;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.setting.LauncherVisibility;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.VersionSetting;
@@ -197,7 +196,7 @@ public final class LauncherHelper {
}))
.executor();
launchingStepsPane.setExecutor(executor);
launchingStepsPane.setExecutor(executor, false);
executor.addTaskListener(new TaskListener() {
final AtomicInteger finished = new AtomicInteger(0);
@@ -376,7 +375,7 @@ public final class LauncherHelper {
if (!flag) {
boolean hasForge2760 = version.getLibraries().stream().filter(it -> it.is("net.minecraftforge", "forge"))
.anyMatch(it ->
0 <= VersionNumber.VERSION_COMPARATOR.compare("1.12.2-14.23.5.2760", it.getVersion()) &&
VersionNumber.VERSION_COMPARATOR.compare("1.12.2-14.23.5.2760", it.getVersion()) <= 0 &&
VersionNumber.VERSION_COMPARATOR.compare(it.getVersion(), "1.12.2-14.23.5.2773") < 0);
boolean hasLiteLoader = version.getLibraries().stream().anyMatch(it -> it.is("com.mumfrey", "liteloader"));
if (hasForge2760 && hasLiteLoader && gameVersion.compareTo(VersionNumber.asVersion("1.12.2")) == 0) {
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -23,35 +23,39 @@ import org.jackhuang.hmcl.mod.*;
import org.jackhuang.hmcl.setting.EnumGameDirectory;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.VersionSetting;
import org.jackhuang.hmcl.task.FinalizedCallback;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.function.ExceptionalConsumer;
import org.jackhuang.hmcl.util.function.ExceptionalRunnable;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Optional;
public final class ModpackHelper {
private ModpackHelper() {}
public static Modpack readModpackManifest(File file) throws UnsupportedModpackException {
public static Modpack readModpackManifest(Path file, Charset charset) throws UnsupportedModpackException {
try {
return CurseManifest.readCurseForgeModpackManifest(file);
return CurseManifest.readCurseForgeModpackManifest(file, charset);
} catch (Exception e) {
// ignore it, not a valid CurseForge modpack.
}
try {
return HMCLModpackManager.readHMCLModpackManifest(file);
return HMCLModpackManager.readHMCLModpackManifest(file, charset);
} catch (Exception e) {
// ignore it, not a valid HMCL modpack.
}
try {
return MultiMCInstanceConfiguration.readMultiMCModpackManifest(file);
return MultiMCInstanceConfiguration.readMultiMCModpackManifest(file, charset);
} catch (Exception e) {
// ignore it, not a valid MultiMC modpack.
}
@@ -85,49 +89,57 @@ public final class ModpackHelper {
public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) {
profile.getRepository().markVersionAsModpack(name);
FinalizedCallback finalizeTask = (variables, isDependentsSucceeded) -> {
if (isDependentsSucceeded) {
ExceptionalRunnable<?> success = () -> {
HMCLGameRepository repository = profile.getRepository();
repository.refreshVersions();
VersionSetting vs = repository.specializeVersionSetting(name);
repository.undoMark(name);
if (vs != null)
vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER);
};
ExceptionalConsumer<Exception, ?> failure = ex -> {
if (ex instanceof CurseCompletionException && !(ex.getCause() instanceof FileNotFoundException)) {
success.run();
// This is tolerable and we will not delete the game
} else {
HMCLGameRepository repository = profile.getRepository();
repository.refreshVersions();
VersionSetting vs = repository.specializeVersionSetting(name);
repository.undoMark(name);
if (vs != null)
vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER);
repository.removeVersionFromDisk(name);
}
};
if (modpack.getManifest() instanceof CurseManifest)
return new CurseInstallTask(profile.getDependency(), zipFile, ((CurseManifest) modpack.getManifest()), name)
.finalized(finalizeTask);
return new CurseInstallTask(profile.getDependency(), zipFile, modpack, ((CurseManifest) modpack.getManifest()), name)
.finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure);
else if (modpack.getManifest() instanceof HMCLModpackManifest)
return new HMCLModpackInstallTask(profile, zipFile, modpack, name)
.finalized(finalizeTask);
.finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure);
else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration)
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
.finalized(finalizeTask)
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
.finalized(Schedulers.defaultScheduler(), ExceptionalConsumer.fromRunnable(success), failure)
.then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
}
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException {
Modpack modpack = ModpackHelper.readModpackManifest(zipFile);
public static Task getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException {
Modpack modpack = ModpackHelper.readModpackManifest(zipFile.toPath(), charset);
switch (configuration.getType()) {
case CurseInstallTask.MODPACK_TYPE:
if (!(modpack.getManifest() instanceof CurseManifest))
throw new MismatchedModpackTypeException(CurseInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
return new CurseInstallTask(profile.getDependency(), zipFile, (CurseManifest) modpack.getManifest(), name);
return new ModpackUpdateTask(profile.getRepository(), name, new CurseInstallTask(profile.getDependency(), zipFile, modpack, (CurseManifest) modpack.getManifest(), name));
case MultiMCModpackInstallTask.MODPACK_TYPE:
if (!(modpack.getManifest() instanceof MultiMCInstanceConfiguration))
throw new MismatchedModpackTypeException(MultiMCModpackInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, (MultiMCInstanceConfiguration) modpack.getManifest(), name);
return new ModpackUpdateTask(profile.getRepository(), name, new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, (MultiMCInstanceConfiguration) modpack.getManifest(), name));
case HMCLModpackInstallTask.MODPACK_TYPE:
if (!(modpack.getManifest() instanceof HMCLModpackManifest))
throw new MismatchedModpackTypeException(HMCLModpackInstallTask.MODPACK_TYPE, getManifestType(modpack.getManifest()));
return new HMCLModpackInstallTask(profile, zipFile, modpack, name);
return new ModpackUpdateTask(profile.getRepository(), name, new HMCLModpackInstallTask(profile, zipFile, modpack, name));
default:
throw new UnsupportedModpackException();
}
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
@@ -0,0 +1,209 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
import static java.util.Collections.singletonMap;
import static org.jackhuang.hmcl.util.Lang.threadPool;
import static org.jackhuang.hmcl.util.Logging.LOG;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.ServerResponseMalformedException;
import org.jackhuang.hmcl.auth.yggdrasil.Texture;
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
import org.jackhuang.hmcl.auth.yggdrasil.TextureType;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.util.javafx.MultiStepBinding;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
/**
* @author yushijinhun
*/
public final class TexturesLoader {
private TexturesLoader() {
}
// ==== Texture Loading ====
public static class LoadedTexture {
private final BufferedImage image;
private final Map<String, String> metadata;
public LoadedTexture(BufferedImage image, Map<String, String> metadata) {
this.image = image;
this.metadata = metadata;
}
public BufferedImage getImage() {
return image;
}
public Map<String, String> getMetadata() {
return metadata;
}
}
private static final ThreadPoolExecutor POOL = threadPool("TexturesDownload", true, 2, 10, TimeUnit.SECONDS);
private static final Path TEXTURES_DIR = Metadata.MINECRAFT_DIRECTORY.resolve("assets").resolve("skins");
private static Path getTexturePath(Texture texture) {
String url = texture.getUrl();
int slash = url.lastIndexOf('/');
int dot = url.lastIndexOf('.');
if (dot < slash) {
dot = url.length();
}
String hash = url.substring(slash + 1, dot);
String prefix = hash.length() > 2 ? hash.substring(0, 2) : "xx";
return TEXTURES_DIR.resolve(prefix).resolve(hash);
}
public static LoadedTexture loadTexture(Texture texture) throws IOException {
Path file = getTexturePath(texture);
if (!Files.isRegularFile(file)) {
// download it
try {
new FileDownloadTask(new URL(texture.getUrl()), file.toFile()).run();
LOG.info("Texture downloaded: " + texture.getUrl());
} catch (Exception e) {
if (Files.isRegularFile(file)) {
// concurrency conflict?
LOG.log(Level.WARNING, "Failed to download texture " + texture.getUrl() + ", but the file is available", e);
} else {
throw new IOException("Failed to download texture " + texture.getUrl());
}
}
}
BufferedImage img;
try (InputStream in = Files.newInputStream(file)) {
img = ImageIO.read(in);
}
return new LoadedTexture(img, texture.getMetadata());
}
// ====
// ==== Skins ====
private final static Map<TextureModel, LoadedTexture> DEFAULT_SKINS = new EnumMap<>(TextureModel.class);
static {
loadDefaultSkin("/assets/img/steve.png", TextureModel.STEVE);
loadDefaultSkin("/assets/img/alex.png", TextureModel.ALEX);
}
private static void loadDefaultSkin(String path, TextureModel model) {
try (InputStream in = TexturesLoader.class.getResourceAsStream(path)) {
DEFAULT_SKINS.put(model, new LoadedTexture(ImageIO.read(in), singletonMap("model", model.modelName)));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public static LoadedTexture getDefaultSkin(TextureModel model) {
return DEFAULT_SKINS.get(model);
}
public static ObjectBinding<LoadedTexture> skinBinding(YggdrasilService service, UUID uuid) {
LoadedTexture uuidFallback = getDefaultSkin(TextureModel.detectUUID(uuid));
return MultiStepBinding.of(service.getProfileRepository().binding(uuid))
.map(profile -> profile
.flatMap(it -> {
try {
return YggdrasilService.getTextures(it);
} catch (ServerResponseMalformedException e) {
LOG.log(Level.WARNING, "Failed to parse texture payload", e);
return Optional.empty();
}
})
.flatMap(it -> Optional.ofNullable(it.get(TextureType.SKIN))))
.asyncMap(it -> {
if (it.isPresent()) {
Texture texture = it.get();
try {
return loadTexture(texture);
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to load texture " + texture.getUrl() + ", using fallback texture", e);
return getDefaultSkin(TextureModel.detectModelName(texture.getMetadata()));
}
} else {
return uuidFallback;
}
}, uuidFallback, POOL);
}
// ====
// ==== Avatar ====
public static BufferedImage toAvatar(BufferedImage skin, int size) {
BufferedImage avatar = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = avatar.createGraphics();
int scale = skin.getWidth() / 64;
int faceOffset = (int) Math.round(size / 18.0);
g.drawImage(skin,
faceOffset, faceOffset, size - faceOffset, size - faceOffset,
8 * scale, 8 * scale, 16 * scale, 16 * scale,
null);
if (skin.getWidth() == skin.getHeight()) {
g.drawImage(skin,
0, 0, size, size,
40 * scale, 8 * scale, 48 * scale, 16 * scale, null);
}
g.dispose();
return avatar;
}
public static ObjectBinding<Image> fxAvatarBinding(YggdrasilService service, UUID uuid, int size) {
return MultiStepBinding.of(skinBinding(service, uuid))
.map(it -> toAvatar(it.image, size))
.map(img -> SwingFXUtils.toFXImage(img, null));
}
public static ObjectBinding<Image> fxAvatarBinding(Account account, int size) {
if (account instanceof YggdrasilAccount) {
return fxAvatarBinding(((YggdrasilAccount) account).getYggdrasilService(), account.getUUID(), size);
} else {
return Bindings.createObjectBinding(
() -> SwingFXUtils.toFXImage(toAvatar(getDefaultSkin(TextureModel.detectUUID(account.getUUID())).image, size), null));
}
}
// ====
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -35,7 +35,6 @@ import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.authlibinjector.SimpleAuthlibInjectorArtifactProvider;
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory;
import org.jackhuang.hmcl.auth.yggdrasil.MojangYggdrasilProvider;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory;
import org.jackhuang.hmcl.task.Schedulers;
@@ -63,7 +62,7 @@ public final class Accounts {
private Accounts() {}
public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE;
public static final YggdrasilAccountFactory FACTORY_YGGDRASIL = new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE);
public static final YggdrasilAccountFactory FACTORY_MOJANG = YggdrasilAccountFactory.MOJANG;
public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(createAuthlibInjectorArtifactProvider(), Accounts::getOrCreateAuthlibInjectorServer);
// ==== login type / account factory mapping ====
@@ -71,7 +70,7 @@ public final class Accounts {
private static final Map<AccountFactory<?>, String> factory2type = new HashMap<>();
static {
type2factory.put("offline", FACTORY_OFFLINE);
type2factory.put("yggdrasil", FACTORY_YGGDRASIL);
type2factory.put("yggdrasil", FACTORY_MOJANG);
type2factory.put("authlibInjector", FACTORY_AUTHLIB_INJECTOR);
type2factory.forEach((type, factory) -> factory2type.put(factory, type));
@@ -94,7 +93,7 @@ public final class Accounts {
else if (account instanceof AuthlibInjectorAccount)
return FACTORY_AUTHLIB_INJECTOR;
else if (account instanceof YggdrasilAccount)
return FACTORY_YGGDRASIL;
return FACTORY_MOJANG;
else
throw new IllegalArgumentException("Failed to determine account type: " + account);
}
@@ -279,7 +278,7 @@ public final class Accounts {
// ==== Login type name i18n ===
private static Map<AccountFactory<?>, String> unlocalizedLoginTypeNames = mapOf(
pair(Accounts.FACTORY_OFFLINE, "account.methods.offline"),
pair(Accounts.FACTORY_YGGDRASIL, "account.methods.yggdrasil"),
pair(Accounts.FACTORY_MOJANG, "account.methods.yggdrasil"),
pair(Accounts.FACTORY_AUTHLIB_INJECTOR, "account.methods.authlib_injector"));
public static String getLocalizedLoginTypeName(AccountFactory<?> factory) {
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -41,6 +41,7 @@ import org.jackhuang.hmcl.util.i18n.Locales;
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
import org.jackhuang.hmcl.util.javafx.ObservableHelper;
import org.jackhuang.hmcl.util.javafx.PropertyUtils;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.net.Proxy;
@@ -62,8 +63,12 @@ public final class Config implements Cloneable, Observable {
.setPrettyPrinting()
.create();
@Nullable
public static Config fromJson(String json) throws JsonParseException {
Config loaded = CONFIG_GSON.fromJson(json, Config.class);
if (loaded == null) {
return null;
}
Config instance = new Config();
PropertyUtils.copyProperties(loaded, instance);
return instance;
@@ -97,7 +102,7 @@ public final class Config implements Cloneable, Observable {
private StringProperty proxyHost = new SimpleStringProperty();
@SerializedName("proxyPort")
private StringProperty proxyPort = new SimpleStringProperty();
private IntegerProperty proxyPort = new SimpleIntegerProperty();
@SerializedName("proxyUserName")
private StringProperty proxyUser = new SimpleStringProperty();
@@ -288,15 +293,15 @@ public final class Config implements Cloneable, Observable {
return proxyHost;
}
public String getProxyPort() {
public int getProxyPort() {
return proxyPort.get();
}
public void setProxyPort(String proxyPort) {
public void setProxyPort(int proxyPort) {
this.proxyPort.set(proxyPort);
}
public StringProperty proxyPortProperty() {
public IntegerProperty proxyPortProperty() {
return proxyPort;
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -31,7 +31,6 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.game.HMCLCacheRepository;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.mod.ModManager;
import org.jackhuang.hmcl.ui.WeakListenerHolder;
import org.jackhuang.hmcl.util.*;
import org.jackhuang.hmcl.util.javafx.ImmediateObjectProperty;
@@ -52,7 +51,6 @@ import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
public final class Profile implements Observable {
private final WeakListenerHolder listenerHolder = new WeakListenerHolder();
private final HMCLGameRepository repository;
private final ModManager modManager;
private final StringProperty selectedVersion = new SimpleStringProperty();
@@ -136,7 +134,6 @@ public final class Profile implements Observable {
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);
this.selectedVersion.set(selectedVersion);
this.useRelativePath.set(useRelativePath);
@@ -166,10 +163,6 @@ public final class Profile implements Observable {
return repository;
}
public ModManager getModManager() {
return modManager;
}
public DefaultDependencyManager getDependency() {
return new DefaultDependencyManager(repository, DownloadProviders.getDownloadProvider(), HMCLCacheRepository.REPOSITORY);
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,14 +13,13 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.value.ObservableObjectValue;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.StringUtils;
import java.net.Authenticator;
@@ -30,6 +29,7 @@ import java.net.Proxy;
import java.net.Proxy.Type;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.Logging.LOG;
public final class ProxyManager {
private ProxyManager() {
@@ -49,10 +49,14 @@ public final class ProxyManager {
proxyProperty = Bindings.createObjectBinding(
() -> {
String host = config().getProxyHost();
Integer port = Lang.toIntOrNull(config().getProxyPort());
if (!config().hasProxy() || StringUtils.isBlank(host) || port == null || config().getProxyType() == Proxy.Type.DIRECT) {
int port = config().getProxyPort();
if (!config().hasProxy() || StringUtils.isBlank(host) || config().getProxyType() == Proxy.Type.DIRECT) {
return Proxy.NO_PROXY;
} else {
if (port < 0 || port > 0xFFFF) {
LOG.warning("Illegal proxy port: " + port);
return Proxy.NO_PROXY;
}
return new Proxy(config().getProxyType(), new InetSocketAddress(host, port));
}
},
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -21,9 +21,7 @@ import javafx.beans.binding.Bindings;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.game.HMCLCacheRepository;
import org.jackhuang.hmcl.util.CacheRepository;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import org.jackhuang.hmcl.util.io.FileUtils;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
@@ -53,11 +51,9 @@ public class Settings {
CacheRepository.setInstance(HMCLCacheRepository.REPOSITORY);
HMCLCacheRepository.REPOSITORY.directoryProperty().bind(Bindings.createStringBinding(() -> {
String str = getCommonDirectory();
try {
Paths.get(str);
return str;
} catch (InvalidPathException e) {
if (FileUtils.canCreateDirectory(getCommonDirectory())) {
return getCommonDirectory();
} else {
return getDefaultCommonDirectory();
}
}, config().commonDirectoryProperty(), config().commonDirTypeProperty()));
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.setting;
@@ -528,7 +528,7 @@ public final class VersionSetting {
public LaunchOptions toLaunchOptions(File gameDir) throws InterruptedException {
JavaVersion javaVersion = Optional.ofNullable(getJavaVersion()).orElse(JavaVersion.fromCurrentEnvironment());
return new LaunchOptions.Builder()
LaunchOptions.Builder builder = new LaunchOptions.Builder()
.setGameDir(gameDir)
.setJava(javaVersion)
.setVersionName(Metadata.TITLE)
@@ -543,13 +543,17 @@ public final class VersionSetting {
.setFullscreen(isFullscreen())
.setServerIp(getServerIp())
.setWrapper(getWrapper())
.setProxyHost(config().getProxyHost())
.setProxyPort(config().getProxyPort())
.setProxyUser(config().getProxyUser())
.setProxyPass(config().getProxyPass())
.setPrecalledCommand(getPreLaunchCommand())
.setNoGeneratedJVMArgs(isNoJVMArgs())
.create();
.setNoGeneratedJVMArgs(isNoJVMArgs());
if (config().hasProxy()) {
builder.setProxyHost(config().getProxyHost());
builder.setProxyPort(config().getProxyPort());
if (config().hasProxyAuth()) {
builder.setProxyUser(config().getProxyUser());
builder.setProxyPass(config().getProxyPass());
}
}
return builder.create();
}
public static class Serializer implements JsonSerializer<VersionSetting>, JsonDeserializer<VersionSetting> {
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -21,7 +21,6 @@ import com.jfoenix.concurrency.JFXUtilities;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import org.jackhuang.hmcl.Launcher;
@@ -29,6 +28,7 @@ import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.setting.EnumCommonDirectory;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor;
@@ -90,8 +90,13 @@ public final class Controllers {
// FXThread
public static GameList getGameListPage() {
if (gameListPage == null)
if (gameListPage == null) {
gameListPage = new GameList();
FXUtils.applyDragListener(gameListPage, it -> "zip".equals(FileUtils.getExtension(it)), modpacks -> {
File modpack = modpacks.get(0);
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(Profiles.getSelectedProfile(), modpack), i18n("install.modpack"));
});
}
return gameListPage;
}
@@ -139,27 +144,9 @@ public final class Controllers {
public static MainPage getMainPage() {
if (mainPage == null) {
MainPage mainPage = new MainPage();
mainPage.setOnDragOver(event -> {
if (event.getGestureSource() != mainPage && event.getDragboard().hasFiles()) {
if (event.getDragboard().getFiles().stream().anyMatch(it -> "zip".equals(FileUtils.getExtension(it))))
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
});
mainPage.setOnDragDropped(event -> {
List<File> files = event.getDragboard().getFiles();
if (files != null) {
List<File> modpacks = files.stream()
.filter(it -> "zip".equals(FileUtils.getExtension(it)))
.collect(Collectors.toList());
if (!modpacks.isEmpty()) {
File modpack = modpacks.get(0);
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(Profiles.getSelectedProfile(), modpack), i18n("install.modpack"));
event.setDropCompleted(true);
}
}
event.consume();
FXUtils.applyDragListener(mainPage, it -> "zip".equals(FileUtils.getExtension(it)), modpacks -> {
File modpack = modpacks.get(0);
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(Profiles.getSelectedProfile(), modpack), i18n("install.modpack"));
});
FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), version -> {
@@ -211,6 +198,12 @@ public final class Controllers {
leftPaneController = new LeftPaneController();
decorator.getDecorator().drawerProperty().setAll(leftPaneController);
if (config().getCommonDirType() == EnumCommonDirectory.CUSTOM &&
!FileUtils.canCreateDirectory(config().getCommonDirectory())) {
config().setCommonDirType(EnumCommonDirectory.DEFAULT);
dialog(i18n("launcher.cache_directory.invalid"));
}
Task.of(JavaVersion::initialize).start();
scene = new Scene(decorator.getDecorator(), 800, 519);
@@ -251,6 +244,10 @@ public final class Controllers {
return pane;
}
public static Region taskDialog(TaskExecutor executor, String title) {
return taskDialog(executor, title, "");
}
public static Region taskDialog(TaskExecutor executor, String title, String subtitle) {
return taskDialog(executor, title, subtitle, null);
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -37,6 +37,7 @@ import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
@@ -50,11 +51,13 @@ import org.jackhuang.hmcl.util.javafx.ExtendedProperties;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BooleanSupplier;
@@ -62,6 +65,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import static org.jackhuang.hmcl.util.Lang.thread;
import static org.jackhuang.hmcl.util.Lang.tryCast;
@@ -230,8 +234,20 @@ public final class FXUtils {
}
}
public static void installTooltip(Node node, String tooltip) {
installTooltip(node, 0, 5000, 0, new Tooltip(tooltip));
public static void installFastTooltip(Node node, Tooltip tooltip) {
installTooltip(node, 50, 5000, 0, tooltip);
}
public static void installFastTooltip(Node node, String tooltip) {
installFastTooltip(node, new Tooltip(tooltip));
}
public static void installSlowTooltip(Node node, Tooltip tooltip) {
installTooltip(node, 500, 5000, 0, tooltip);
}
public static void installSlowTooltip(Node node, String tooltip) {
installSlowTooltip(node, new Tooltip(tooltip));
}
public static void installTooltip(Node node, double openDelay, double visibleDelay, double closeDelay, Tooltip tooltip) {
@@ -445,6 +461,34 @@ public final class FXUtils {
}
}
public static void applyDragListener(Node node, FileFilter filter, Consumer<List<File>> callback) {
applyDragListener(node, filter, callback, null);
}
public static void applyDragListener(Node node, FileFilter filter, Consumer<List<File>> callback, Runnable dragDropped) {
node.setOnDragOver(event -> {
if (event.getGestureSource() != node && event.getDragboard().hasFiles()) {
if (event.getDragboard().getFiles().stream().anyMatch(filter::accept))
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
});
node.setOnDragDropped(event -> {
List<File> files = event.getDragboard().getFiles();
if (files != null) {
List<File> acceptFiles = files.stream().filter(filter::accept).collect(Collectors.toList());
if (!acceptFiles.isEmpty()) {
callback.accept(acceptFiles);
event.setDropCompleted(true);
}
}
if (dragDropped != null)
dragDropped.run();
event.consume();
});
}
public static <T> StringConverter<T> stringConverter(Function<T, String> func) {
return new StringConverter<T>() {
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -26,7 +26,6 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.game.ModpackHelper;
import org.jackhuang.hmcl.mod.Modpack;
import org.jackhuang.hmcl.mod.UnsupportedModpackException;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
@@ -37,10 +36,10 @@ import org.jackhuang.hmcl.ui.account.AccountAdvancedListItem;
import org.jackhuang.hmcl.ui.account.AddAccountPane;
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
import org.jackhuang.hmcl.ui.profile.ProfileAdvancedListItem;
import org.jackhuang.hmcl.ui.versions.GameAdvancedListItem;
import org.jackhuang.hmcl.ui.versions.Versions;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
@@ -111,7 +110,6 @@ public final class LeftPaneController extends AdvancedListBox {
// ====
private boolean checkedModpack = false;
private static boolean showNewAccount = true;
private void onRefreshedVersions(HMCLGameRepository repository) {
JFXUtilities.runInFX(() -> {
@@ -121,27 +119,21 @@ public final class LeftPaneController extends AdvancedListBox {
if (repository.getVersionCount() == 0) {
File modpackFile = new File("modpack.zip").getAbsoluteFile();
if (modpackFile.exists()) {
try {
AtomicReference<Region> region = new AtomicReference<>();
Modpack modpack = ModpackHelper.readModpackManifest(modpackFile);
TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
.with(Task.of(Schedulers.javafx(), () -> {
region.get().fireEvent(new DialogCloseEvent());
checkAccount();
})).executor();
region.set(Controllers.taskDialog(executor, i18n("modpack.installing"), ""));
executor.start();
showNewAccount = false;
} catch (UnsupportedModpackException ignore) {
}
Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath()))
.thenResult(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
.thenResult(modpack -> {
AtomicReference<Region> region = new AtomicReference<>();
TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
.with(Task.of(Schedulers.javafx(), this::checkAccount)).executor();
region.set(Controllers.taskDialog(executor, i18n("modpack.installing")));
executor.start();
return null;
}).start();
}
}
}
if (showNewAccount) {
showNewAccount = false;
checkAccount();
}
checkAccount();
});
}
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -30,9 +30,13 @@ import javafx.scene.control.Skin;
public abstract class ListPage<T extends Node> extends Control {
private final ListProperty<T> items = new SimpleListProperty<>(this, "items", FXCollections.observableArrayList());
private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading", false);
private final BooleanProperty refreshable = new SimpleBooleanProperty(this, "refreshable", false);
public abstract void add();
public void refresh() {
}
@Override
protected Skin<?> createDefaultSkin() {
return new ListPageSkin(this);
@@ -61,4 +65,16 @@ public abstract class ListPage<T extends Node> extends Control {
public BooleanProperty loadingProperty() {
return loading;
}
public boolean isRefreshable() {
return refreshable.get();
}
public BooleanProperty refreshableProperty() {
return refreshable;
}
public void setRefreshable(boolean refreshable) {
this.refreshable.set(refreshable);
}
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,13 +13,13 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXScrollPane;
import com.jfoenix.controls.JFXSpinner;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@@ -28,17 +28,14 @@ import javafx.scene.control.SkinBase;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.construct.SpinnerPane;
public class ListPageSkin extends SkinBase<ListPage> {
public class ListPageSkin extends SkinBase<ListPage<?>> {
public ListPageSkin(ListPage<?> skinnable) {
super(skinnable);
StackPane rootPane = new StackPane();
JFXSpinner spinner = new JFXSpinner();
spinner.setRadius(16);
spinner.getStyleClass().setAll("materialDesign-purple", "first-spinner");
SpinnerPane spinnerPane = new SpinnerPane();
StackPane contentPane = new StackPane();
{
@@ -56,7 +53,7 @@ public class ListPageSkin extends SkinBase<ListPage> {
scrollPane.setContent(list);
JFXScrollPane.smoothScrolling(scrollPane);
}
VBox vBox = new VBox();
{
vBox.setAlignment(Pos.BOTTOM_RIGHT);
@@ -72,19 +69,29 @@ public class ListPageSkin extends SkinBase<ListPage> {
btnAdd.setGraphic(SVG.plus(Theme.whiteFillBinding(), -1, -1));
btnAdd.setOnMouseClicked(e -> skinnable.add());
JFXButton btnRefresh = new JFXButton();
FXUtils.setLimitWidth(btnRefresh, 40);
FXUtils.setLimitHeight(btnRefresh, 40);
btnRefresh.getStyleClass().setAll("jfx-button-raised-round");
btnRefresh.setButtonType(JFXButton.ButtonType.RAISED);
btnRefresh.setGraphic(SVG.refresh(Theme.whiteFillBinding(), -1, -1));
btnRefresh.setOnMouseClicked(e -> skinnable.refresh());
vBox.getChildren().setAll(btnAdd);
FXUtils.onChangeAndOperate(skinnable.refreshableProperty(),
refreshable -> {
if (refreshable) vBox.getChildren().setAll(btnRefresh, btnAdd);
else vBox.getChildren().setAll(btnAdd);
});
}
contentPane.getChildren().setAll(scrollPane, vBox);
}
rootPane.getChildren().setAll(contentPane);
spinnerPane.loadingProperty().bind(skinnable.loadingProperty());
spinnerPane.setContent(contentPane);
skinnable.loadingProperty().addListener((a, b, newValue) -> {
if (newValue) rootPane.getChildren().setAll(spinner);
else rootPane.getChildren().setAll(contentPane);
});
getChildren().setAll(rootPane);
getChildren().setAll(spinnerPane);
}
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -87,11 +87,8 @@ public final class MainPage extends StackPane implements DecoratorPage {
lblIcon.setGraphic(SVG.update(Theme.whiteFillBinding(), 20, 20));
TwoLineListItem prompt = new TwoLineListItem();
prompt.setTitleFill(Color.WHITE);
prompt.setSubtitleFill(Color.WHITE);
prompt.setSubtitle(i18n("update.bubble.subtitle"));
prompt.setPickOnBounds(false);
prompt.setStyle("-jfx-title-font-weight: BOLD;");
prompt.titleProperty().bind(latestVersionProperty());
hBox.getChildren().setAll(lblIcon, prompt);
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -24,7 +24,8 @@ import javafx.beans.InvalidationListener;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.When;
import javafx.beans.property.*;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.control.ToggleGroup;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
@@ -41,7 +42,7 @@ import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.i18n.Locales;
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
import java.awt.Desktop;
import java.awt.*;
import java.io.IOException;
import java.net.Proxy;
import java.nio.file.Files;
@@ -95,7 +96,11 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
// ==== Proxy ====
txtProxyHost.textProperty().bindBidirectional(config().proxyHostProperty());
txtProxyPort.textProperty().bindBidirectional(config().proxyPortProperty());
txtProxyPort.textProperty().bindBidirectional(config().proxyPortProperty(),
SafeStringConverter.fromInteger()
.restrict(it -> it >= 0 && it <= 0xFFFF)
.fallbackTo(0)
.asPredicate(Validator.addTo(txtProxyPort)));
txtProxyUsername.textProperty().bindBidirectional(config().proxyUserProperty());
txtProxyPassword.textProperty().bindBidirectional(config().proxyPassProperty());
@@ -114,17 +119,17 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
// ====
fileCommonLocation.loadChildren(Arrays.asList(
fileCommonLocation.createChildren(i18n("launcher.common_directory.default"), EnumCommonDirectory.DEFAULT)
fileCommonLocation.createChildren(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT)
), EnumCommonDirectory.CUSTOM);
fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty());
fileCommonLocation.customTextProperty().bindBidirectional(config().commonDirectoryProperty());
fileCommonLocation.subtitleProperty().bind(
Bindings.createObjectBinding(() -> Optional.ofNullable(Settings.instance().getCommonDirectory())
.orElse(i18n("launcher.common_directory.disabled")),
.orElse(i18n("launcher.cache_directory.disabled")),
config().commonDirectoryProperty(), config().commonDirTypeProperty()));
// ==== Update ====
FXUtils.installTooltip(btnUpdate, i18n("update.tooltip"));
FXUtils.installFastTooltip(btnUpdate, i18n("update.tooltip"));
updateListener = any -> {
btnUpdate.setVisible(UpdateChecker.isOutdated());
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -26,17 +26,16 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
import org.jackhuang.hmcl.setting.EnumCommonDirectory;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public abstract class SettingsView extends StackPane {
protected final JFXTextField txtProxyHost;
protected final JFXTextField txtProxyPort;
@@ -144,9 +143,9 @@ public abstract class SettingsView extends StackPane {
{
fileCommonLocation = new MultiFileItem<>(true);
fileCommonLocation.setTitle(i18n("launcher.common_directory"));
fileCommonLocation.setTitle(i18n("launcher.cache_directory"));
fileCommonLocation.setDirectory(true);
fileCommonLocation.setChooserTitle(i18n("launcher.common_directory.choose"));
fileCommonLocation.setChooserTitle(i18n("launcher.cache_directory.choose"));
fileCommonLocation.setHasSubtitle(true);
fileCommonLocation.setCustomText("settings.custom");
@@ -360,7 +359,7 @@ public abstract class SettingsView extends StackPane {
HBox hBox = new HBox();
hBox.setSpacing(3);
cboFont = new FontComboBox(12, false);
cboFont = new FontComboBox(12);
txtFontSize = new JFXTextField();
FXUtils.setLimitWidth(txtFontSize, 50);
hBox.getChildren().setAll(cboFont, txtFontSize);
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,19 +13,19 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.image.Image;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.game.AccountHelper;
import org.jackhuang.hmcl.game.TexturesLoader;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
@@ -38,23 +38,15 @@ public class AccountAdvancedListItem extends AdvancedListItem {
protected void invalidated() {
Account account = get();
if (account == null) {
titleProperty().unbind();
setTitle(i18n("account.missing"));
setSubtitle(i18n("account.missing.add"));
imageProperty().unbind();
setImage(new Image("/assets/img/craft_table.png"));
} else {
setTitle(account.getCharacter());
titleProperty().bind(Bindings.createStringBinding(account::getCharacter, account));
setSubtitle(accountSubtitle(account));
final int scaleRatio = 4;
Image defaultSkin = AccountHelper.getDefaultSkin(account.getUUID(), scaleRatio);
setImage(AccountHelper.getHead(defaultSkin, scaleRatio));
if (account instanceof YggdrasilAccount) {
AccountHelper.loadSkinAsync((YggdrasilAccount) account).subscribe(Schedulers.javafx(), () -> {
Image image = AccountHelper.getSkin((YggdrasilAccount) account, scaleRatio);
setImage(AccountHelper.getHead(image, scaleRatio));
});
}
imageProperty().bind(TexturesLoader.fxAvatarBinding(account, 32));
}
}
};
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,25 +13,32 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.*;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Skin;
import javafx.scene.image.Image;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AuthenticationException;
import org.jackhuang.hmcl.auth.CredentialExpiredException;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.game.AccountHelper;
import org.jackhuang.hmcl.game.TexturesLoader;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.ui.DialogController;
import static org.jackhuang.hmcl.util.Lang.thread;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import java.util.logging.Level;
public class AccountListItem extends RadioButton {
private final Account account;
@@ -44,23 +51,24 @@ public class AccountListItem extends RadioButton {
getStyleClass().clear();
setUserData(account);
StringBuilder subtitleString = new StringBuilder(Accounts.getLocalizedLoginTypeName(Accounts.getAccountFactory(account)));
String loginTypeName = Accounts.getLocalizedLoginTypeName(Accounts.getAccountFactory(account));
if (account instanceof AuthlibInjectorAccount) {
AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer();
subtitleString.append(", ").append(i18n("account.injector.server")).append(": ").append(server.getName());
subtitle.bind(Bindings.concat(
loginTypeName, ", ", i18n("account.injector.server"), ": ",
Bindings.createStringBinding(server::getName, server)));
} else {
subtitle.set(loginTypeName);
}
if (account instanceof OfflineAccount)
title.set(account.getCharacter());
else
title.set(account.getUsername() + " - " + account.getCharacter());
subtitle.set(subtitleString.toString());
StringBinding characterName = Bindings.createStringBinding(account::getCharacter, account);
if (account instanceof OfflineAccount) {
title.bind(characterName);
} else {
title.bind(Bindings.concat(account.getUsername(), " - ", characterName));
}
final int scaleRatio = 4;
Image image = account instanceof YggdrasilAccount ?
AccountHelper.getSkin((YggdrasilAccount) account, scaleRatio) :
AccountHelper.getDefaultSkin(account.getUUID(), scaleRatio);
this.image.set(AccountHelper.getHead(image, scaleRatio));
image.bind(TexturesLoader.fxAvatarBinding(account, 32));
}
@Override
@@ -69,19 +77,20 @@ public class AccountListItem extends RadioButton {
}
public void refresh() {
if (account instanceof YggdrasilAccount) {
// progressBar.setVisible(true);
AccountHelper.refreshSkinAsync((YggdrasilAccount) account)
.finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> {
// progressBar.setVisible(false);
if (isDependentsSucceeded) {
final int scaleRatio = 4;
Image image = AccountHelper.getSkin((YggdrasilAccount) account, scaleRatio);
this.image.set(AccountHelper.getHead(image, scaleRatio));
}
}).start();
}
account.clearCache();
thread(() -> {
try {
account.logIn();
} catch (CredentialExpiredException e) {
try {
DialogController.logIn(account);
} catch (Exception e1) {
LOG.log(Level.WARNING, "Failed to refresh " + account + " with password", e1);
}
} catch (AuthenticationException e) {
LOG.log(Level.WARNING, "Failed to refresh " + account + " with token", e);
}
});
}
public void remove() {
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
@@ -21,18 +21,26 @@ import com.jfoenix.concurrency.JFXUtilities;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXRadioButton;
import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.SkinBase;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
public class AccountListItemSkin extends SkinBase<AccountListItem> {
public AccountListItemSkin(AccountListItem skinnable) {
@@ -58,8 +66,22 @@ public class AccountListItemSkin extends SkinBase<AccountListItem> {
FXUtils.limitSize(imageView, 32, 32);
imageView.imageProperty().bind(skinnable.imageProperty());
TwoLineListItem item = new TwoLineListItem();
Label title = new Label();
title.getStyleClass().add("title");
title.textProperty().bind(skinnable.titleProperty());
Label subtitle = new Label();
subtitle.getStyleClass().add("subtitle");
subtitle.textProperty().bind(skinnable.subtitleProperty());
if (skinnable.getAccount() instanceof AuthlibInjectorAccount) {
Tooltip tooltip = new Tooltip();
AuthlibInjectorServer server = ((AuthlibInjectorAccount) skinnable.getAccount()).getServer();
tooltip.textProperty().bind(Bindings.createStringBinding(server::toString, server));
FXUtils.installSlowTooltip(subtitle, tooltip);
}
VBox item = new VBox(title, subtitle);
item.getStyleClass().add("two-line-list-item");
BorderPane.setAlignment(item, Pos.CENTER);
center.getChildren().setAll(imageView, item);
root.setCenter(center);
@@ -69,7 +91,7 @@ public class AccountListItemSkin extends SkinBase<AccountListItem> {
btnRefresh.setOnMouseClicked(e -> skinnable.refresh());
btnRefresh.getStyleClass().add("toggle-icon4");
btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), -1, -1));
JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRefresh, i18n("button.refresh")));
JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh")));
right.getChildren().add(btnRefresh);
JFXButton btnRemove = new JFXButton();
@@ -77,14 +99,12 @@ public class AccountListItemSkin extends SkinBase<AccountListItem> {
btnRemove.getStyleClass().add("toggle-icon4");
BorderPane.setAlignment(btnRemove, Pos.CENTER);
btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), -1, -1));
JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRemove, i18n("button.delete")));
JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRemove, i18n("button.delete")));
right.getChildren().add(btnRemove);
root.setRight(right);
root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;");
JFXDepthManager.setDepth(root, 1);
item.titleProperty().bind(skinnable.titleProperty());
item.subtitleProperty().bind(skinnable.subtitleProperty());
getChildren().setAll(root);
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
@@ -37,8 +37,7 @@ public class AccountLoginPane extends StackPane {
private final Consumer<AuthInfo> success;
private final Runnable failed;
@FXML
private Label lblUsername;
@FXML private Label lblUsername;
@FXML private JFXPasswordField txtPassword;
@FXML private Label lblCreationWarning;
@FXML private JFXProgressBar progressBar;
@@ -59,25 +58,19 @@ public class AccountLoginPane extends StackPane {
String password = txtPassword.getText();
progressBar.setVisible(true);
lblCreationWarning.setText("");
Task.ofResult("login", () -> {
try {
return oldAccount.logInWithPassword(password);
} catch (Exception e) {
return e;
}
}).subscribe(Schedulers.javafx(), variable -> {
Object account = variable.get("login");
if (account instanceof AuthInfo) {
success.accept(((AuthInfo) account));
fireEvent(new DialogCloseEvent());
} else if (account instanceof NoSelectedCharacterException) {
fireEvent(new DialogCloseEvent());
} else if (account instanceof Exception) {
lblCreationWarning.setText(AddAccountPane.accountException((Exception) account));
}
progressBar.setVisible(false);
});
Task.ofResult(() -> oldAccount.logInWithPassword(password))
.finalizedResult(Schedulers.javafx(), authInfo -> {
success.accept(authInfo);
fireEvent(new DialogCloseEvent());
progressBar.setVisible(false);
}, e -> {
if (e instanceof NoSelectedCharacterException) {
fireEvent(new DialogCloseEvent());
} else {
lblCreationWarning.setText(AddAccountPane.accountException(e));
}
progressBar.setVisible(false);
}).start();
}
@FXML
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,19 +13,23 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
import com.jfoenix.concurrency.JFXUtilities;
import com.jfoenix.controls.*;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ListProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
@@ -35,20 +39,22 @@ import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDownloadException;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.game.AccountHelper;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
import org.jackhuang.hmcl.game.TexturesLoader;
import org.jackhuang.hmcl.setting.Accounts;
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.*;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.javafx.MultiStepBinding;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.*;
@@ -63,12 +69,13 @@ public class AddAccountPane extends StackPane {
@FXML private JFXComboBox<AccountFactory<?>> cboType;
@FXML private JFXComboBox<AuthlibInjectorServer> cboServers;
@FXML private Label lblInjectorServer;
@FXML private Hyperlink linkManageInjectorServers;
@FXML private JFXDialogLayout layout;
@FXML private JFXButton btnAccept;
@FXML private JFXButton btnAddServer;
@FXML private JFXButton btnManageServer;
@FXML private SpinnerPane acceptPane;
@FXML private HBox linksContainer;
private ListProperty<Hyperlink> links = new SimpleListProperty<>();;
public AddAccountPane() {
FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml");
@@ -79,7 +86,7 @@ public class AddAccountPane extends StackPane {
cboServers.getItems().addListener(onInvalidating(this::selectDefaultServer));
selectDefaultServer();
cboType.getItems().setAll(Accounts.FACTORY_OFFLINE, Accounts.FACTORY_YGGDRASIL, Accounts.FACTORY_AUTHLIB_INJECTOR);
cboType.getItems().setAll(Accounts.FACTORY_OFFLINE, Accounts.FACTORY_MOJANG, Accounts.FACTORY_AUTHLIB_INJECTOR);
cboType.setConverter(stringConverter(Accounts::getLocalizedLoginTypeName));
// try selecting the preferred login type
cboType.getSelectionModel().select(
@@ -117,6 +124,34 @@ public class AddAccountPane extends StackPane {
txtUsername.textProperty(),
txtPassword.textProperty(), txtPassword.visibleProperty(),
cboServers.getSelectionModel().selectedItemProperty(), cboServers.visibleProperty()));
// authlib-injector links
links.bind(MultiStepBinding.of(cboServers.getSelectionModel().selectedItemProperty())
.map(AddAccountPane::createHyperlinks)
.map(FXCollections::observableList));
Bindings.bindContent(linksContainer.getChildren(), links);
linksContainer.visibleProperty().bind(cboServers.visibleProperty());
}
private static final String[] ALLOWED_LINKS = { "register" };
public static List<Hyperlink> createHyperlinks(AuthlibInjectorServer server) {
if (server == null) {
return emptyList();
}
Map<String, String> links = server.getLinks();
List<Hyperlink> result = new ArrayList<>();
for (String key : ALLOWED_LINKS) {
String value = links.get(key);
if (value != null) {
Hyperlink link = new Hyperlink(i18n("account.injector.link." + key));
FXUtils.installSlowTooltip(link, value);
link.setOnAction(e -> FXUtils.openLink(value));
result.add(link);
}
}
return unmodifiableList(result);
}
/**
@@ -160,10 +195,8 @@ public class AddAccountPane extends StackPane {
AccountFactory<?> factory = cboType.getSelectionModel().getSelectedItem();
Object additionalData = getAuthAdditionalData();
Task.ofResult("create_account", () -> factory.create(new Selector(), username, password, additionalData))
.finalized(Schedulers.javafx(), variables -> {
Account account = variables.get("create_account");
Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData))
.finalizedResult(Schedulers.javafx(), account -> {
int oldIndex = Accounts.getAccounts().indexOf(account);
if (oldIndex == -1) {
Accounts.getAccounts().add(account);
@@ -214,7 +247,7 @@ public class AddAccountPane extends StackPane {
private final CountDownLatch latch = new CountDownLatch(1);
private GameProfile selectedProfile = null;
{
public Selector() {
setStyle("-fx-padding: 8px;");
cancel.setText(i18n("button.cancel"));
@@ -232,45 +265,33 @@ public class AddAccountPane extends StackPane {
}
@Override
public GameProfile select(Account account, List<GameProfile> names) throws NoSelectedCharacterException {
if (!(account instanceof YggdrasilAccount))
return CharacterSelector.DEFAULT.select(account, names);
YggdrasilAccount yggdrasilAccount = (YggdrasilAccount) account;
public GameProfile select(YggdrasilService service, List<GameProfile> profiles) throws NoSelectedCharacterException {
Platform.runLater(() -> {
for (GameProfile profile : profiles) {
ImageView portraitView = new ImageView();
portraitView.setSmooth(false);
portraitView.imageProperty().bind(TexturesLoader.fxAvatarBinding(service, profile.getId(), 32));
FXUtils.limitSize(portraitView, 32, 32);
for (GameProfile profile : names) {
Image image;
final int scaleRatio = 4;
try {
image = AccountHelper.getSkinImmediately(yggdrasilAccount, profile, scaleRatio);
} catch (Exception e) {
Logging.LOG.log(Level.WARNING, "Failed to get skin for " + profile.getName(), e);
image = AccountHelper.getDefaultSkin(profile.getId(), scaleRatio);
IconedItem accountItem = new IconedItem(portraitView, profile.getName());
accountItem.setOnMouseClicked(e -> {
selectedProfile = profile;
latch.countDown();
});
listBox.add(accountItem);
}
ImageView portraitView = new ImageView();
portraitView.setSmooth(false);
portraitView.setImage(AccountHelper.getHead(image, scaleRatio));
FXUtils.limitSize(portraitView, 32, 32);
IconedItem accountItem = new IconedItem(portraitView, profile.getName());
accountItem.setOnMouseClicked(e -> {
selectedProfile = profile;
latch.countDown();
});
listBox.add(accountItem);
}
JFXUtilities.runInFX(() -> Controllers.dialog(this));
Controllers.dialog(this);
});
try {
latch.await();
if (selectedProfile == null)
throw new NoSelectedCharacterException(account);
throw new NoSelectedCharacterException();
return selectedProfile;
} catch (InterruptedException ignore) {
throw new NoSelectedCharacterException(account);
throw new NoSelectedCharacterException();
} finally {
JFXUtilities.runInFX(() -> Selector.this.fireEvent(new DialogCloseEvent()));
}
@@ -298,6 +319,8 @@ public class AddAccountPane extends StackPane {
return exception.getMessage();
} else if (exception instanceof AuthlibInjectorDownloadException) {
return i18n("account.failed.injector_download_failure");
} else if (exception instanceof CharacterDeletedException) {
return i18n("account.failed.character_deleted");
} else if (exception.getClass() == AuthenticationException.class) {
return exception.getLocalizedMessage();
} else {
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,12 +13,14 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
@@ -33,17 +35,17 @@ public final class AuthlibInjectorServerItem extends BorderPane {
private final AuthlibInjectorServer server;
private final Label lblServerName = new Label();
private final Label lblServerIp = new Label();
private final Label lblServerUrl = new Label();
public AuthlibInjectorServerItem(AuthlibInjectorServer server, Consumer<AuthlibInjectorServerItem> deleteCallback) {
this.server = server;
lblServerName.setStyle("-fx-font-size: 15;");
lblServerIp.setStyle("-fx-font-size: 10;");
lblServerUrl.setStyle("-fx-font-size: 10;");
VBox center = new VBox();
BorderPane.setAlignment(center, Pos.CENTER);
center.getChildren().addAll(lblServerName, lblServerIp);
center.getChildren().addAll(lblServerName, lblServerUrl);
setCenter(center);
JFXButton right = new JFXButton();
@@ -55,8 +57,8 @@ public final class AuthlibInjectorServerItem extends BorderPane {
setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;");
JFXDepthManager.setDepth(this, 1);
lblServerName.setText(server.getName());
lblServerIp.setText(server.getUrl());
lblServerName.textProperty().bind(Bindings.createStringBinding(server::getName, server));
lblServerUrl.setText(server.getUrl());
}
public AuthlibInjectorServer getServer() {
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.account;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.animation;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.animation;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright c 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.animation;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.animation;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import javafx.beans.DefaultProperty;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -61,7 +61,7 @@ public class FileItem extends BorderPane {
right.setGraphic(SVG.pencil(Theme.blackFillBinding(), 15, 15));
right.getStyleClass().add("toggle-icon4");
right.setOnMouseClicked(e -> onExplore());
FXUtils.installTooltip(right, i18n("button.edit"));
FXUtils.installFastTooltip(right, i18n("button.edit"));
setRight(right);
Tooltip tip = new Tooltip();
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -24,27 +24,27 @@ import static javafx.collections.FXCollections.singletonObservableList;
import org.jackhuang.hmcl.util.javafx.MultiStepBinding;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXListCell;
import javafx.beans.NamedArg;
import javafx.beans.binding.Bindings;
import javafx.scene.control.ListCell;
import javafx.scene.text.Font;
public class FontComboBox extends JFXComboBox<String> {
private boolean loaded = false;
public FontComboBox(@NamedArg(value = "fontSize", defaultValue = "12.0") double fontSize,
@NamedArg(value = "enableStyle", defaultValue = "false") boolean enableStyle) {
public FontComboBox(@NamedArg(value = "fontSize", defaultValue = "12.0") double fontSize) {
styleProperty().bind(Bindings.concat("-fx-font-family: \"", valueProperty(), "\""));
setCellFactory(listView -> new ListCell<String>() {
setCellFactory(listView -> new JFXListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
if (!empty) {
setText(item);
setFont(new Font(item, fontSize));
setGraphic(null);
setStyle("-fx-font-family: \"" + item + "\"");
}
}
});
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,11 +13,12 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import javafx.scene.Node;
import org.jackhuang.hmcl.ui.FXUtils;
public class IconedMenuItem extends IconedItem {
@@ -27,4 +28,9 @@ public class IconedMenuItem extends IconedItem {
getStyleClass().setAll("iconed-menu-item");
setOnMouseClicked(e -> action.run());
}
public IconedMenuItem addTooltip(String tooltip) {
FXUtils.installFastTooltip(this, tooltip);
return this;
}
}
@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.controls.JFXButton;
@@ -46,7 +63,7 @@ public final class ImagePickerItem extends BorderPane {
deleteButton.onMouseClickedProperty().bind(onDeleteButtonClicked);
deleteButton.getStyleClass().add("toggle-icon4");
FXUtils.installTooltip(selectButton, i18n("button.edit"));
FXUtils.installFastTooltip(selectButton, i18n("button.edit"));
HBox hBox = new HBox();
hBox.getChildren().setAll(imageView, selectButton, deleteButton);
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -38,15 +38,20 @@ public class InputDialogPane extends StackPane {
private Label content;
@FXML
private Label lblCreationWarning;
@FXML
private SpinnerPane acceptPane;
public InputDialogPane(String text, FutureCallback<String> onResult) {
FXUtils.loadFXML(this, "/assets/fxml/input-dialog.fxml");
content.setText(text);
cancelButton.setOnMouseClicked(e -> fireEvent(new DialogCloseEvent()));
acceptButton.setOnMouseClicked(e -> {
acceptPane.showSpinner();
onResult.call(textField.getText(), () -> {
acceptPane.hideSpinner();
fireEvent(new DialogCloseEvent());
}, msg -> {
acceptPane.hideSpinner();
lblCreationWarning.setText(msg);
});
});
@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import javafx.geometry.Insets;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun4008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,3 +1,20 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.controls.JFXColorPicker;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -32,6 +32,7 @@ import org.jackhuang.hmcl.util.Logging;
import java.util.Optional;
import java.util.Stack;
import java.util.logging.Level;
public class Navigator extends StackPane {
private static final String PROPERTY_DIALOG_CLOSE_HANDLER = Navigator.class.getName() + ".closeListener";
@@ -94,10 +95,14 @@ public class Navigator extends StackPane {
if (!initialized)
throw new IllegalStateException("Navigator must have a root page");
if (stack.peek() != from) {
// Allow page to be closed multiple times.
Logging.LOG.log(Level.INFO, "Closing already closed page: " + from, new Throwable());
return;
}
Logging.LOG.info("Closed page " + from);
if (stack.peek() != from)
throw new IllegalStateException();
stack.pop();
Node node = stack.peek();
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,13 +13,15 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.controls.JFXSpinner;
import javafx.beans.DefaultProperty;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
@@ -32,19 +34,29 @@ public class SpinnerPane extends StackPane {
private final JFXSpinner spinner = new JFXSpinner();
private final StackPane contentPane = new StackPane();
private final ObjectProperty<Node> content = new SimpleObjectProperty<>(this, "content");
private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading") {
protected void invalidated() {
if (get())
transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer());
else
transitionHandler.setContent(contentPane, ContainerAnimations.FADE.getAnimationProducer());
}
};
public SpinnerPane() {
getStyleClass().add("spinner-pane");
getChildren().setAll(contentPane);
content.addListener((a, b, newValue) -> contentPane.getChildren().setAll(newValue));
}
public void showSpinner() {
transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer());
setLoading(true);
}
public void hideSpinner() {
transitionHandler.setContent(contentPane, ContainerAnimations.FADE.getAnimationProducer());
setLoading(false);
}
public Node getContent() {
@@ -58,4 +70,16 @@ public class SpinnerPane extends StackPane {
public void setContent(Node content) {
this.content.set(content);
}
public boolean isLoading() {
return loading.get();
}
public BooleanProperty loadingProperty() {
return loading;
}
public void setLoading(boolean loading) {
this.loading.set(loading);
}
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,13 +13,14 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.concurrency.JFXUtilities;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXProgressBar;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
@@ -27,6 +28,7 @@ import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.task.TaskListener;
import org.jackhuang.hmcl.ui.FXUtils;
import java.util.Optional;
@@ -66,10 +68,23 @@ public class TaskExecutorDialogPane extends StackPane {
}
public void setExecutor(TaskExecutor executor) {
setExecutor(executor, true);
}
public void setExecutor(TaskExecutor executor, boolean autoClose) {
this.executor = executor;
if (executor != null)
if (executor != null) {
taskListPane.setExecutor(executor);
if (autoClose)
executor.addTaskListener(new TaskListener() {
@Override
public void onStop(boolean success, TaskExecutor executor) {
Platform.runLater(() -> fireEvent(new DialogCloseEvent()));
}
});
}
}
public StringProperty titleProperty() {
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,18 +13,21 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXProgressBar;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.download.forge.ForgeInstallTask;
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask;
@@ -42,15 +45,16 @@ import java.util.Map;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class TaskListPane extends StackPane {
private final AdvancedListBox listBox = new AdvancedListBox();
private final JFXListView<Task> listBox = new JFXListView<>();
private final Map<Task, ProgressListNode> nodes = new HashMap<>();
private final ReadOnlyIntegerWrapper finishedTasks = new ReadOnlyIntegerWrapper();
private final ReadOnlyIntegerWrapper totTasks = new ReadOnlyIntegerWrapper();
public TaskListPane() {
listBox.setSpacing(0);
getChildren().setAll(listBox);
listBox.setPadding(Insets.EMPTY);
listBox.setCellFactory(listView -> new ProgressListNode());
}
public ReadOnlyIntegerProperty finishedTasksProperty() {
@@ -66,7 +70,7 @@ public final class TaskListPane extends StackPane {
@Override
public void onStart() {
Platform.runLater(() -> {
listBox.clear();
listBox.getItems().clear();
finishedTasks.set(0);
totTasks.set(0);
});
@@ -94,6 +98,8 @@ public final class TaskListPane extends StackPane {
task.setName(i18n("modpack.type.curse.completion"));
} else if (task instanceof ModpackInstallTask) {
task.setName(i18n("modpack.installing"));
} else if (task instanceof ModpackUpdateTask) {
task.setName(i18n("modpack.update"));
} else if (task instanceof CurseInstallTask) {
task.setName(i18n("modpack.install", i18n("modpack.type.curse")));
} else if (task instanceof MultiMCModpackInstallTask) {
@@ -106,66 +112,66 @@ public final class TaskListPane extends StackPane {
task.setName(i18n("modpack.scan"));
}
ProgressListNode node = new ProgressListNode(task);
nodes.put(task, node);
Platform.runLater(() -> listBox.add(node));
Platform.runLater(() -> listBox.getItems().add(task));
}
@Override
public void onFinished(Task task) {
ProgressListNode node = nodes.remove(task);
if (node == null)
return;
node.unbind();
Platform.runLater(() -> {
listBox.remove(node);
finishedTasks.set(finishedTasks.getValue() + 1);
});
}
@Override
public void onFailed(Task task, Throwable throwable) {
ProgressListNode node = nodes.remove(task);
if (node == null)
return;
Platform.runLater(() -> {
node.setThrowable(throwable);
finishedTasks.set(finishedTasks.getValue() + 1);
if (listBox.getItems().remove(task))
finishedTasks.set(finishedTasks.getValue() + 1);
});
}
});
}
private static class ProgressListNode extends VBox {
private static class ProgressListNode extends ListCell<Task> {
private final BorderPane borderPane = new BorderPane();
private final JFXProgressBar bar = new JFXProgressBar();
private final Label title = new Label();
private final Label state = new Label();
public ProgressListNode(Task task) {
bar.progressProperty().bind(task.progressProperty());
title.setText(task.getName());
state.textProperty().bind(task.messageProperty());
BorderPane borderPane = new BorderPane();
{
borderPane.setLeft(title);
borderPane.setRight(state);
getChildren().addAll(borderPane, bar);
borderPane.setBottom(bar);
borderPane.setMinWidth(0);
borderPane.setPrefWidth(1);
setPadding(Insets.EMPTY);
bar.minWidthProperty().bind(widthProperty());
bar.prefWidthProperty().bind(widthProperty());
bar.maxWidthProperty().bind(widthProperty());
}
public void unbind() {
bar.progressProperty().unbind();
state.textProperty().unbind();
}
@Override
protected void updateItem(Task item, boolean empty) {
boolean wasEmpty = isEmpty();
Task oldTask = getItem();
public void setThrowable(Throwable throwable) {
unbind();
state.setText(throwable.getLocalizedMessage());
bar.setProgress(0);
if (!wasEmpty && oldTask != null) {
bar.progressProperty().unbind();
state.textProperty().unbind();
}
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
setGraphic(borderPane);
bar.visibleProperty().bind(Bindings.createBooleanBinding(() -> item.progressProperty().get() != -1, item.progressProperty()));
bar.progressProperty().bind(item.progressProperty());
state.textProperty().bind(Bindings.createObjectBinding(() -> {
if (item.getState() == Task.TaskState.FAILED) {
return item.getLastException().getLocalizedMessage();
} else {
return item.messageProperty().get();
}
}, item.messageProperty(), item.stateProperty()));
title.setText(item.getName());
}
}
}
}
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,38 +13,21 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.css.CssMetaData;
import javafx.css.SimpleStyleableObjectProperty;
import javafx.css.Styleable;
import javafx.css.StyleableObjectProperty;
import javafx.css.StyleablePropertyFactory;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import java.util.List;
public class TwoLineListItem extends StackPane {
public class TwoLineListItem extends VBox {
private static final String DEFAULT_STYLE_CLASS = "two-line-list-item";
private final StringProperty title = new SimpleStringProperty(this, "title");
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
private final StyleableObjectProperty<Font> titleFont = new SimpleStyleableObjectProperty<>(StyleableProperties.TITLE_FONT, this, "title-font", Font.font(15));
private final StyleableObjectProperty<Font> subtitleFont = new SimpleStyleableObjectProperty<>(StyleableProperties.SUBTITLE_FONT, this, "subtitle-font", Font.getDefault());
private final StyleableObjectProperty<Paint> titleFill = new SimpleStyleableObjectProperty<>(StyleableProperties.TITLE_FILL, this, "title-fill", Color.BLACK);
private final StyleableObjectProperty<Paint> subtitleFill = new SimpleStyleableObjectProperty<>(StyleableProperties.SUBTITLE_FILL, this, "subtitle-fill", Color.GRAY);
public TwoLineListItem(String titleString, String subtitleString) {
this();
@@ -53,20 +36,16 @@ public class TwoLineListItem extends StackPane {
}
public TwoLineListItem() {
setMouseTransparent(true);
Label lblTitle = new Label();
lblTitle.textFillProperty().bind(titleFill);
lblTitle.fontProperty().bind(titleFont);
lblTitle.getStyleClass().add("title");
lblTitle.textProperty().bind(title);
Label lblSubtitle = new Label();
lblSubtitle.textFillProperty().bind(subtitleFill);
lblSubtitle.fontProperty().bind(subtitleFont);
lblSubtitle.getStyleClass().add("subtitle");
lblSubtitle.textProperty().bind(subtitle);
VBox vbox = new VBox();
vbox.getChildren().setAll(lblTitle, lblSubtitle);
getChildren().setAll(vbox);
getChildren().setAll(lblTitle, lblSubtitle);
getStyleClass().add(DEFAULT_STYLE_CLASS);
}
@@ -94,74 +73,8 @@ public class TwoLineListItem extends StackPane {
this.subtitle.set(subtitle);
}
public Font getTitleFont() {
return titleFont.get();
}
public StyleableObjectProperty<Font> titleFontProperty() {
return titleFont;
}
public void setTitleFont(Font titleFont) {
this.titleFont.set(titleFont);
}
public Font getSubtitleFont() {
return subtitleFont.get();
}
public StyleableObjectProperty<Font> subtitleFontProperty() {
return subtitleFont;
}
public void setSubtitleFont(Font subtitleFont) {
this.subtitleFont.set(subtitleFont);
}
public Paint getTitleFill() {
return titleFill.get();
}
public StyleableObjectProperty<Paint> titleFillProperty() {
return titleFill;
}
public void setTitleFill(Paint titleFill) {
this.titleFill.set(titleFill);
}
public Paint getSubtitleFill() {
return subtitleFill.get();
}
public StyleableObjectProperty<Paint> subtitleFillProperty() {
return subtitleFill;
}
public void setSubtitleFill(Paint subtitleFill) {
this.subtitleFill.set(subtitleFill);
}
@Override
public String toString() {
return getTitle();
}
@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return getClassCssMetaData();
}
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return StyleableProperties.FACTORY.getCssMetaData();
}
private static class StyleableProperties {
private static final StyleablePropertyFactory<TwoLineListItem> FACTORY = new StyleablePropertyFactory<>(StackPane.getClassCssMetaData());
private static final CssMetaData<TwoLineListItem, Font> TITLE_FONT = FACTORY.createFontCssMetaData("-jfx-title-font", s -> s.titleFont, Font.font(15));
private static final CssMetaData<TwoLineListItem, Font> SUBTITLE_FONT = FACTORY.createFontCssMetaData("-jfx-subtitle-font", s -> s.subtitleFont);
private static final CssMetaData<TwoLineListItem, Paint> TITLE_FILL = FACTORY.createPaintCssMetaData("-jfx-title-fill", s -> s.titleFill);
private static final CssMetaData<TwoLineListItem, Paint> SUBTITLE_FILL = FACTORY.createPaintCssMetaData("-jfx-subtitle-fill", s -> s.subtitleFill, Color.GREY);
}
}
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.construct;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.decorator;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.decorator;
@@ -42,14 +42,12 @@ import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
import org.jackhuang.hmcl.setting.Config;
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.wizard.Refreshable;
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
import org.jackhuang.hmcl.util.FutureCallback;
import java.io.IOException;
import java.nio.file.Files;
@@ -59,7 +57,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Random;
import java.util.function.Consumer;
import java.util.logging.Level;
import static java.util.stream.Collectors.toList;
@@ -359,45 +356,6 @@ public class DecoratorController {
}
}
public void showDialog(String text) {
showDialog(text, null);
}
public void showDialog(String text, String title) {
showDialog(text, title, MessageBox.INFORMATION_MESSAGE);
}
public void showDialog(String text, String title, int type) {
showDialog(text, title, type, null);
}
public void showDialog(String text, String title, int type, Runnable onAccept) {
showDialog(new MessageDialogPane(text, title, type, onAccept));
}
public void showConfirmDialog(String text, String title, Runnable onAccept, Runnable onCancel) {
showDialog(new MessageDialogPane(text, title, onAccept, onCancel));
}
public InputDialogPane showInputDialog(String text, FutureCallback<String> onResult) {
InputDialogPane pane = new InputDialogPane(text, onResult);
showDialog(pane);
return pane;
}
public Region showTaskDialog(TaskExecutor executor, String title, String subtitle) {
return showTaskDialog(executor, title, subtitle, null);
}
public Region showTaskDialog(TaskExecutor executor, String title, String subtitle, Consumer<Region> onCancel) {
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel);
pane.setTitle(title);
pane.setSubtitle(subtitle);
pane.setExecutor(executor);
showDialog(pane);
return pane;
}
// ==== Wizard ====
public void startWizard(WizardProvider wizardProvider) {
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.decorator;
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.decorator;
@@ -32,6 +32,7 @@ import javafx.scene.control.SkinBase;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
@@ -73,8 +74,12 @@ public class DecoratorSkin extends SkinBase<Decorator> {
BorderPane root = new BorderPane();
root.getStyleClass().setAll("jfx-decorator", "resize-border");
root.setMaxHeight(519);
root.setMaxWidth(800);
root.setPrefHeight(519);
root.setPrefWidth(800);
root.setMaxHeight(Region.USE_PREF_SIZE);
root.setMinHeight(Region.USE_PREF_SIZE);
root.setMaxWidth(Region.USE_PREF_SIZE);
root.setMinWidth(Region.USE_PREF_SIZE);
StackPane drawerWrapper = new StackPane();
skinnable.setDrawerWrapper(drawerWrapper);
@@ -202,7 +207,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
else navLeft.getChildren().setAll(backNavButton);
});
skinnable.showCloseAsHomeProperty().addListener((a, b, newValue) -> {
FXUtils.onChangeAndOperate(skinnable.showCloseAsHomeProperty(), (newValue) -> {
if (newValue)
closeNavButton.setGraphic(SVG.home(Theme.foregroundFillBinding(), -1, -1));
else
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.decorator;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.download;
@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
*
* Hello Minecraft! Launcher
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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
@@ -13,7 +13,7 @@
* 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/}.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.ui.download;
Loaded 100 of 420 files, more files were not shown because too many files have changed in this diff. Show more