Add account list view
This commit is contained in:
@@ -29,6 +29,8 @@ import javafx.scene.layout.VBox;
|
|||||||
import javafx.scene.text.TextAlignment;
|
import javafx.scene.text.TextAlignment;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class AdvancedListItem2 extends StackPane {
|
public class AdvancedListItem2 extends StackPane {
|
||||||
|
|
||||||
public AdvancedListItem2(AdvancedListItemViewModel viewModel) {
|
public AdvancedListItem2(AdvancedListItemViewModel viewModel) {
|
||||||
@@ -47,6 +49,8 @@ public class AdvancedListItem2 extends StackPane {
|
|||||||
FXUtils.limitSize(imageView, 32, 32);
|
FXUtils.limitSize(imageView, 32, 32);
|
||||||
imageView.setPreserveRatio(true);
|
imageView.setPreserveRatio(true);
|
||||||
imageView.imageProperty().bind(viewModel.imageProperty());
|
imageView.imageProperty().bind(viewModel.imageProperty());
|
||||||
|
Optional.ofNullable(viewModel.viewportProperty())
|
||||||
|
.ifPresent(imageView.viewportProperty()::bind);
|
||||||
imageViewContainer.getChildren().setAll(imageView);
|
imageViewContainer.getChildren().setAll(imageView);
|
||||||
|
|
||||||
VBox vbox = new VBox();
|
VBox vbox = new VBox();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui;
|
|||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.geometry.Rectangle2D;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
|
|
||||||
public abstract class AdvancedListItemViewModel {
|
public abstract class AdvancedListItemViewModel {
|
||||||
@@ -27,6 +28,10 @@ public abstract class AdvancedListItemViewModel {
|
|||||||
|
|
||||||
public abstract ObjectProperty<Image> imageProperty();
|
public abstract ObjectProperty<Image> imageProperty();
|
||||||
|
|
||||||
|
public ObjectProperty<Rectangle2D> viewportProperty() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract StringProperty titleProperty();
|
public abstract StringProperty titleProperty();
|
||||||
|
|
||||||
public abstract StringProperty subtitleProperty();
|
public abstract StringProperty subtitleProperty();
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import org.jackhuang.hmcl.Metadata;
|
|||||||
import org.jackhuang.hmcl.setting.Settings;
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
|
import org.jackhuang.hmcl.ui.account.AccountListView;
|
||||||
|
import org.jackhuang.hmcl.ui.account.AccountListViewModel;
|
||||||
import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage;
|
import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage;
|
||||||
import org.jackhuang.hmcl.ui.construct.InputDialogPane;
|
import org.jackhuang.hmcl.ui.construct.InputDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||||
@@ -49,6 +51,7 @@ public final class Controllers {
|
|||||||
private static SettingsPage settingsPage = null;
|
private static SettingsPage settingsPage = null;
|
||||||
private static VersionPage versionPage = null;
|
private static VersionPage versionPage = null;
|
||||||
private static GameListView gameListView = null;
|
private static GameListView gameListView = null;
|
||||||
|
private static AccountListView accountListView = null;
|
||||||
private static AuthlibInjectorServersPage serversPage = null;
|
private static AuthlibInjectorServersPage serversPage = null;
|
||||||
private static LeftPaneController leftPaneController;
|
private static LeftPaneController leftPaneController;
|
||||||
private static Decorator decorator;
|
private static Decorator decorator;
|
||||||
@@ -75,6 +78,13 @@ public final class Controllers {
|
|||||||
return gameListView;
|
return gameListView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FXThread
|
||||||
|
public static AccountListView getAccountListView() {
|
||||||
|
if (accountListView == null)
|
||||||
|
accountListView = new AccountListView(new AccountListViewModel());
|
||||||
|
return accountListView;
|
||||||
|
}
|
||||||
|
|
||||||
// FXThread
|
// FXThread
|
||||||
public static VersionPage getVersionPage() {
|
public static VersionPage getVersionPage() {
|
||||||
if (versionPage == null)
|
if (versionPage == null)
|
||||||
@@ -192,5 +202,7 @@ public final class Controllers {
|
|||||||
decorator = null;
|
decorator = null;
|
||||||
stage = null;
|
stage = null;
|
||||||
scene = null;
|
scene = null;
|
||||||
|
gameListView = null;
|
||||||
|
accountListView = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,28 +19,15 @@ package org.jackhuang.hmcl.ui;
|
|||||||
|
|
||||||
import com.jfoenix.concurrency.JFXUtilities;
|
import com.jfoenix.concurrency.JFXUtilities;
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXPopup;
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
|
||||||
import javafx.beans.binding.When;
|
import javafx.beans.binding.When;
|
||||||
import javafx.beans.property.ListProperty;
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleListProperty;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Tooltip;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.input.MouseButton;
|
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
|
||||||
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
|
||||||
import org.jackhuang.hmcl.event.*;
|
import org.jackhuang.hmcl.event.*;
|
||||||
import org.jackhuang.hmcl.game.AccountHelper;
|
|
||||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||||
import org.jackhuang.hmcl.game.ModpackHelper;
|
import org.jackhuang.hmcl.game.ModpackHelper;
|
||||||
import org.jackhuang.hmcl.mod.Modpack;
|
import org.jackhuang.hmcl.mod.Modpack;
|
||||||
@@ -49,12 +36,12 @@ import org.jackhuang.hmcl.setting.*;
|
|||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
import org.jackhuang.hmcl.ui.account.AccountPage;
|
import org.jackhuang.hmcl.ui.account.AccountAdvancedListItemViewModel;
|
||||||
import org.jackhuang.hmcl.ui.account.AddAccountPane;
|
import org.jackhuang.hmcl.ui.account.AddAccountPane;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
|
import org.jackhuang.hmcl.ui.versions.GameAdvancedListItemViewModel;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import org.jackhuang.hmcl.util.MappedObservableList;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -62,37 +49,20 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static javafx.collections.FXCollections.singletonObservableList;
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public final class LeftPaneController {
|
public final class LeftPaneController {
|
||||||
private final AdvancedListBox leftPane;
|
private final AdvancedListBox leftPane;
|
||||||
private final VBox profilePane = new VBox();
|
private final VBox profilePane = new VBox();
|
||||||
private final VBox accountPane = new VBox();
|
private final VBox accountPane = new VBox();
|
||||||
private final IconedItem launcherSettingsItem;
|
|
||||||
private final AdvancedListItem2 gameListItem;
|
|
||||||
|
|
||||||
private ListProperty<RipplerContainer> accountItems = new SimpleListProperty<>();
|
|
||||||
private ObjectProperty<Account> selectedAccount = new SimpleObjectProperty<Account>() {
|
|
||||||
{
|
|
||||||
accountItems.addListener(onInvalidating(this::invalidated));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidated() {
|
|
||||||
Account selected = get();
|
|
||||||
accountItems.forEach(item -> item.setSelected(
|
|
||||||
getAccountFromItem(item)
|
|
||||||
.map(it -> it == selected)
|
|
||||||
.orElse(false)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public LeftPaneController(AdvancedListBox leftPane) {
|
public LeftPaneController(AdvancedListBox leftPane) {
|
||||||
this.leftPane = leftPane;
|
this.leftPane = leftPane;
|
||||||
|
|
||||||
launcherSettingsItem = new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20));
|
AdvancedListItem2 accountListItem = new AdvancedListItem2(new AccountAdvancedListItemViewModel());
|
||||||
|
AdvancedListItem2 gameListItem = new AdvancedListItem2(new GameAdvancedListItemViewModel());
|
||||||
|
|
||||||
|
IconedItem launcherSettingsItem = new IconedItem(SVG.gear(Theme.blackFillBinding(), 20, 20));
|
||||||
|
|
||||||
launcherSettingsItem.getLabel().textProperty().bind(
|
launcherSettingsItem.getLabel().textProperty().bind(
|
||||||
new When(UpdateChecker.outdatedProperty())
|
new When(UpdateChecker.outdatedProperty())
|
||||||
@@ -107,17 +77,12 @@ public final class LeftPaneController {
|
|||||||
launcherSettingsItem.maxWidthProperty().bind(leftPane.widthProperty());
|
launcherSettingsItem.maxWidthProperty().bind(leftPane.widthProperty());
|
||||||
launcherSettingsItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage()));
|
launcherSettingsItem.setOnMouseClicked(e -> Controllers.navigate(Controllers.getSettingsPage()));
|
||||||
|
|
||||||
gameListItem = new AdvancedListItem2(new GameAdvancedListItemViewModel());
|
|
||||||
|
|
||||||
leftPane
|
leftPane
|
||||||
.add(new ClassTitle(i18n("account").toUpperCase(), Lang.apply(new JFXButton(), button -> {
|
.startCategory(i18n("account").toUpperCase())
|
||||||
button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10));
|
.add(accountListItem)
|
||||||
button.getStyleClass().add("toggle-icon-tiny");
|
.startCategory(i18n("version").toUpperCase())
|
||||||
button.setOnMouseClicked(e -> addNewAccount());
|
|
||||||
})))
|
|
||||||
.add(accountPane)
|
|
||||||
.startCategory(i18n("launcher").toUpperCase())
|
|
||||||
.add(gameListItem)
|
.add(gameListItem)
|
||||||
|
.startCategory(i18n("launcher").toUpperCase())
|
||||||
.add(launcherSettingsItem)
|
.add(launcherSettingsItem)
|
||||||
.add(new ClassTitle(i18n("profile.title").toUpperCase(), Lang.apply(new JFXButton(), button -> {
|
.add(new ClassTitle(i18n("profile.title").toUpperCase(), Lang.apply(new JFXButton(), button -> {
|
||||||
button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10));
|
button.setGraphic(SVG.plus(Theme.blackFillBinding(), 10, 10));
|
||||||
@@ -127,22 +92,6 @@ public final class LeftPaneController {
|
|||||||
})))
|
})))
|
||||||
.add(profilePane);
|
.add(profilePane);
|
||||||
|
|
||||||
// ==== Accounts ====
|
|
||||||
// Missing account item
|
|
||||||
AdvancedListItem missingAccountItem = new AdvancedListItem(i18n("account.missing"), i18n("message.unknown"));
|
|
||||||
RipplerContainer missingAccountRippler = new RipplerContainer(missingAccountItem);
|
|
||||||
missingAccountItem.setOnSettingsButtonClicked(e -> addNewAccount());
|
|
||||||
missingAccountRippler.setOnMouseClicked(e -> addNewAccount());
|
|
||||||
|
|
||||||
accountItems.bind(
|
|
||||||
new When(Accounts.accountsProperty().emptyProperty())
|
|
||||||
.then(singletonObservableList(missingAccountRippler))
|
|
||||||
.otherwise(MappedObservableList.create(Accounts.getAccounts(), this::createAccountItem)));
|
|
||||||
Bindings.bindContent(accountPane.getChildren(), accountItems);
|
|
||||||
|
|
||||||
selectedAccount.bindBidirectional(Accounts.selectedAccountProperty());
|
|
||||||
// ====
|
|
||||||
|
|
||||||
EventBus.EVENT_BUS.channel(ProfileLoadingEvent.class).register(this::onProfilesLoading);
|
EventBus.EVENT_BUS.channel(ProfileLoadingEvent.class).register(this::onProfilesLoading);
|
||||||
EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(this::onProfileChanged);
|
EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(this::onProfileChanged);
|
||||||
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(this::onRefreshedVersions);
|
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(this::onRefreshedVersions);
|
||||||
@@ -154,55 +103,6 @@ public final class LeftPaneController {
|
|||||||
.map(Account.class::cast);
|
.map(Account.class::cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String accountSubtitle(Account account) {
|
|
||||||
if (account instanceof OfflineAccount)
|
|
||||||
return i18n("account.methods.offline");
|
|
||||||
else if (account instanceof YggdrasilAccount)
|
|
||||||
return account.getUsername();
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private RipplerContainer createAccountItem(Account account) {
|
|
||||||
AdvancedListItem item = new AdvancedListItem(account.getCharacter(), accountSubtitle(account));
|
|
||||||
RipplerContainer rippler = new RipplerContainer(item);
|
|
||||||
item.setOnSettingsButtonClicked(e -> {
|
|
||||||
AccountPage accountPage = new AccountPage(account, item);
|
|
||||||
JFXPopup popup = new JFXPopup(accountPage);
|
|
||||||
accountPage.setOnDelete(popup::hide);
|
|
||||||
popup.show((Node) e.getSource(), JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, e.getX(), e.getY());
|
|
||||||
});
|
|
||||||
rippler.setOnMouseClicked(e -> {
|
|
||||||
if (e.getButton() == MouseButton.PRIMARY) {
|
|
||||||
selectedAccount.set(account);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
rippler.getProperties().put("account", account);
|
|
||||||
rippler.maxWidthProperty().bind(leftPane.widthProperty());
|
|
||||||
|
|
||||||
if (account instanceof YggdrasilAccount) {
|
|
||||||
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
|
||||||
item.setImage(image, AccountHelper.getViewport(4));
|
|
||||||
} else {
|
|
||||||
item.setImage(AccountHelper.getDefaultSkin(account.getUUID(), 4), AccountHelper.getViewport(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
|
||||||
FXUtils.installTooltip(rippler, 500, 5000, 0, new Tooltip(((AuthlibInjectorAccount) account).getServer().getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// update skin
|
|
||||||
if (account instanceof YggdrasilAccount) {
|
|
||||||
AccountHelper.refreshSkinAsync((YggdrasilAccount) account)
|
|
||||||
.subscribe(Schedulers.javafx(), () -> {
|
|
||||||
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
|
||||||
item.setImage(image, AccountHelper.getViewport(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return rippler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAccount() {
|
public void checkAccount() {
|
||||||
if (Accounts.getAccounts().isEmpty())
|
if (Accounts.getAccounts().isEmpty())
|
||||||
addNewAccount();
|
addNewAccount();
|
||||||
|
|||||||
@@ -18,8 +18,10 @@
|
|||||||
package org.jackhuang.hmcl.ui;
|
package org.jackhuang.hmcl.ui;
|
||||||
|
|
||||||
import javafx.beans.binding.ObjectBinding;
|
import javafx.beans.binding.ObjectBinding;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
import javafx.scene.shape.SVGPath;
|
import javafx.scene.shape.SVGPath;
|
||||||
|
|
||||||
@@ -33,8 +35,11 @@ public final class SVG {
|
|||||||
path.setContent(d);
|
path.setContent(d);
|
||||||
path.fillProperty().bind(fill);
|
path.fillProperty().bind(fill);
|
||||||
|
|
||||||
if (width < 0 || height < 0)
|
if (width < 0 || height < 0) {
|
||||||
return path;
|
StackPane pane = new StackPane(path);
|
||||||
|
pane.setAlignment(Pos.CENTER);
|
||||||
|
return pane;
|
||||||
|
}
|
||||||
|
|
||||||
Group svg = new Group(path);
|
Group svg = new Group(path);
|
||||||
double scale = Math.min(width / svg.getBoundsInParent().getWidth(), height / svg.getBoundsInParent().getHeight());
|
double scale = Math.min(width / svg.getBoundsInParent().getWidth(), height / svg.getBoundsInParent().getHeight());
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.geometry.Rectangle2D;
|
||||||
|
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.setting.Accounts;
|
||||||
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
|
import org.jackhuang.hmcl.ui.AdvancedListItemViewModel;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class AccountAdvancedListItemViewModel extends AdvancedListItemViewModel {
|
||||||
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
||||||
|
private final ObjectProperty<Rectangle2D> viewport = new SimpleObjectProperty<>(AccountHelper.getViewport(4));
|
||||||
|
private final StringProperty title = new SimpleStringProperty();
|
||||||
|
private final StringProperty subtitle = new SimpleStringProperty();
|
||||||
|
|
||||||
|
public AccountAdvancedListItemViewModel() {
|
||||||
|
|
||||||
|
FXUtils.onChangeAndOperate(Accounts.selectedAccountProperty(), account -> {
|
||||||
|
if (account == null) {
|
||||||
|
title.set(i18n("account.missing"));
|
||||||
|
subtitle.set(i18n("account.missing.add"));
|
||||||
|
image.set(new Image("/assets/img/craft_table.png"));
|
||||||
|
} else {
|
||||||
|
title.set(account.getCharacter());
|
||||||
|
subtitle.set(accountSubtitle(account));
|
||||||
|
|
||||||
|
this.image.set(AccountHelper.getDefaultSkin(account.getUUID(), 4));
|
||||||
|
|
||||||
|
if (account instanceof YggdrasilAccount) {
|
||||||
|
AccountHelper.loadSkinAsync((YggdrasilAccount) account).subscribe(Schedulers.javafx(), () -> {
|
||||||
|
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
||||||
|
this.image.set(image);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void action() {
|
||||||
|
Controllers.navigate(Controllers.getAccountListView());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectProperty<Rectangle2D> viewportProperty() {
|
||||||
|
return viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String accountSubtitle(Account account) {
|
||||||
|
if (account instanceof OfflineAccount)
|
||||||
|
return i18n("account.methods.offline");
|
||||||
|
else if (account instanceof YggdrasilAccount)
|
||||||
|
return account.getUsername();
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
|
import com.jfoenix.concurrency.JFXUtilities;
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXRadioButton;
|
||||||
|
import com.jfoenix.effects.JFXDepthManager;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
import org.jackhuang.hmcl.ui.TwoLineListItem;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class AccountListItemView extends BorderPane {
|
||||||
|
|
||||||
|
public AccountListItemView(AccountListItemViewModel viewModel) {
|
||||||
|
JFXRadioButton chkSelected = new JFXRadioButton();
|
||||||
|
BorderPane.setAlignment(chkSelected, Pos.CENTER);
|
||||||
|
chkSelected.setUserData(viewModel);
|
||||||
|
chkSelected.selectedProperty().bindBidirectional(viewModel.selectedProperty());
|
||||||
|
chkSelected.setToggleGroup(viewModel.getToggleGroup());
|
||||||
|
setLeft(chkSelected);
|
||||||
|
|
||||||
|
HBox center = new HBox();
|
||||||
|
center.setSpacing(8);
|
||||||
|
center.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
StackPane imageViewContainer = new StackPane();
|
||||||
|
FXUtils.setLimitWidth(imageViewContainer, 32);
|
||||||
|
FXUtils.setLimitHeight(imageViewContainer, 32);
|
||||||
|
|
||||||
|
ImageView imageView = new ImageView();
|
||||||
|
FXUtils.limitSize(imageView, 32, 32);
|
||||||
|
imageView.imageProperty().bind(viewModel.imageProperty());
|
||||||
|
imageView.viewportProperty().bind(viewModel.viewportProperty());
|
||||||
|
imageViewContainer.getChildren().setAll(imageView);
|
||||||
|
|
||||||
|
TwoLineListItem item = new TwoLineListItem();
|
||||||
|
BorderPane.setAlignment(item, Pos.CENTER);
|
||||||
|
center.getChildren().setAll(imageView, item);
|
||||||
|
setCenter(center);
|
||||||
|
|
||||||
|
HBox right = new HBox();
|
||||||
|
right.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
JFXButton btnRefresh = new JFXButton();
|
||||||
|
btnRefresh.setOnMouseClicked(e -> viewModel.refresh());
|
||||||
|
btnRefresh.getStyleClass().add("toggle-icon4");
|
||||||
|
btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), -1, -1));
|
||||||
|
JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRefresh, i18n("button.refresh")));
|
||||||
|
right.getChildren().add(btnRefresh);
|
||||||
|
|
||||||
|
JFXButton btnRemove = new JFXButton();
|
||||||
|
btnRemove.setOnMouseClicked(e -> viewModel.remove());
|
||||||
|
btnRemove.getStyleClass().add("toggle-icon4");
|
||||||
|
BorderPane.setAlignment(btnRemove, Pos.CENTER);
|
||||||
|
btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), -1, -1));
|
||||||
|
JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRefresh, i18n("button.delete")));
|
||||||
|
right.getChildren().add(btnRemove);
|
||||||
|
setRight(right);
|
||||||
|
|
||||||
|
setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;");
|
||||||
|
JFXDepthManager.setDepth(this, 1);
|
||||||
|
item.titleProperty().bind(viewModel.titleProperty());
|
||||||
|
item.subtitleProperty().bind(viewModel.subtitleProperty());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
|
import javafx.beans.property.*;
|
||||||
|
import javafx.geometry.Rectangle2D;
|
||||||
|
import javafx.scene.control.ToggleGroup;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
|
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.setting.Accounts;
|
||||||
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class AccountListItemViewModel {
|
||||||
|
private final Account account;
|
||||||
|
private final ToggleGroup toggleGroup;
|
||||||
|
private final StringProperty title = new SimpleStringProperty();
|
||||||
|
private final StringProperty subtitle = new SimpleStringProperty();
|
||||||
|
private final BooleanProperty selected = new SimpleBooleanProperty();
|
||||||
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
||||||
|
private final ObjectProperty<Rectangle2D> viewport = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
|
public AccountListItemViewModel(ToggleGroup toggleGroup, Account account) {
|
||||||
|
this.account = account;
|
||||||
|
this.toggleGroup = toggleGroup;
|
||||||
|
|
||||||
|
StringBuilder subtitleString = new StringBuilder(Accounts.getAccountTypeName(account));
|
||||||
|
if (account instanceof AuthlibInjectorAccount) {
|
||||||
|
AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer();
|
||||||
|
subtitleString.append(", ").append(i18n("account.injector.server")).append(": ").append(server.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account instanceof OfflineAccount)
|
||||||
|
title.set(account.getCharacter());
|
||||||
|
else
|
||||||
|
title.set(account.getUsername() + " - " + account.getCharacter());
|
||||||
|
subtitle.set(subtitleString.toString());
|
||||||
|
selected.set(Accounts.selectedAccountProperty().get() == account);
|
||||||
|
|
||||||
|
viewport.set(AccountHelper.getViewport(4));
|
||||||
|
if (account instanceof YggdrasilAccount) {
|
||||||
|
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
||||||
|
this.image.set(image);
|
||||||
|
} else {
|
||||||
|
this.image.set(AccountHelper.getDefaultSkin(account.getUUID(), 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToggleGroup getToggleGroup() {
|
||||||
|
return toggleGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanProperty selectedProperty() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Rectangle2D> viewportProperty() {
|
||||||
|
return viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
if (account instanceof YggdrasilAccount) {
|
||||||
|
// progressBar.setVisible(true);
|
||||||
|
AccountHelper.refreshSkinAsync((YggdrasilAccount) account)
|
||||||
|
.finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> {
|
||||||
|
// progressBar.setVisible(false);
|
||||||
|
|
||||||
|
if (isDependentsSucceeded) {
|
||||||
|
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
||||||
|
this.image.set(image);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
Accounts.getAccounts().remove(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
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.wizard.DecoratorPage;
|
||||||
|
import org.jackhuang.hmcl.util.MappedObservableList;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class AccountListView extends StackPane implements DecoratorPage {
|
||||||
|
private final StringProperty title = new SimpleStringProperty(i18n("account.manage"));
|
||||||
|
|
||||||
|
public AccountListView(AccountListViewModel viewModel) {
|
||||||
|
ScrollPane scrollPane = new ScrollPane();
|
||||||
|
{
|
||||||
|
scrollPane.setFitToWidth(true);
|
||||||
|
|
||||||
|
VBox accountList = new VBox();
|
||||||
|
accountList.maxWidthProperty().bind(scrollPane.widthProperty());
|
||||||
|
accountList.setSpacing(10);
|
||||||
|
accountList.setStyle("-fx-padding: 10 10 10 10;");
|
||||||
|
|
||||||
|
Bindings.bindContent(accountList.getChildren(),
|
||||||
|
MappedObservableList.create(viewModel.itemsProperty(), AccountListItemView::new));
|
||||||
|
|
||||||
|
scrollPane.setContent(accountList);
|
||||||
|
}
|
||||||
|
|
||||||
|
VBox vBox = new VBox();
|
||||||
|
{
|
||||||
|
vBox.setAlignment(Pos.BOTTOM_RIGHT);
|
||||||
|
vBox.setPickOnBounds(false);
|
||||||
|
vBox.setPadding(new Insets(15));
|
||||||
|
vBox.setSpacing(15);
|
||||||
|
|
||||||
|
JFXButton btnAdd = new JFXButton();
|
||||||
|
FXUtils.setLimitWidth(btnAdd, 40);
|
||||||
|
FXUtils.setLimitHeight(btnAdd, 40);
|
||||||
|
btnAdd.getStyleClass().setAll("jfx-button-raised-round");
|
||||||
|
btnAdd.setButtonType(JFXButton.ButtonType.RAISED);
|
||||||
|
btnAdd.setGraphic(SVG.plus(Theme.whiteFillBinding(), -1, -1));
|
||||||
|
btnAdd.setOnMouseClicked(e -> viewModel.addNewAccount());
|
||||||
|
|
||||||
|
vBox.getChildren().setAll(btnAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChildren().setAll(scrollPane, vBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
|
import javafx.beans.property.ListProperty;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleListProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.scene.control.ToggleGroup;
|
||||||
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
|
import org.jackhuang.hmcl.setting.Accounts;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.util.MappedObservableList;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
||||||
|
|
||||||
|
public class AccountListViewModel {
|
||||||
|
private final ListProperty<AccountListItemViewModel> items = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||||
|
private ObjectProperty<Account> selectedAccount = new SimpleObjectProperty<Account>() {
|
||||||
|
{
|
||||||
|
items.addListener(onInvalidating(this::invalidated));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void invalidated() {
|
||||||
|
Account selected = get();
|
||||||
|
items.forEach(item -> item.selectedProperty().set(item.getAccount() == selected));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private ToggleGroup toggleGroup;
|
||||||
|
|
||||||
|
public AccountListViewModel() {
|
||||||
|
toggleGroup = new ToggleGroup();
|
||||||
|
|
||||||
|
items.bindContent(MappedObservableList.create(
|
||||||
|
Accounts.accountsProperty(),
|
||||||
|
account -> new AccountListItemViewModel(toggleGroup, account)));
|
||||||
|
|
||||||
|
selectedAccount.bindBidirectional(Accounts.selectedAccountProperty());
|
||||||
|
toggleGroup.selectedToggleProperty().addListener((o, a, toggle) -> {
|
||||||
|
if (toggle == null || toggle.getUserData() == null) return;
|
||||||
|
selectedAccount.set(((AccountListItemViewModel) toggle.getUserData()).getAccount());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNewAccount() {
|
||||||
|
Controllers.dialog(new AddAccountPane());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListProperty<AccountListItemViewModel> itemsProperty() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher.
|
|
||||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.ui.account;
|
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
|
||||||
import com.jfoenix.controls.JFXProgressBar;
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.BorderPane;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.auth.Account;
|
|
||||||
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.setting.Accounts;
|
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
|
||||||
import org.jackhuang.hmcl.ui.SVG;
|
|
||||||
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
|
|
||||||
import org.jackhuang.hmcl.ui.construct.ComponentList;
|
|
||||||
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.installTooltip;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class AccountPage extends StackPane implements DecoratorPage {
|
|
||||||
private final StringProperty title;
|
|
||||||
private final ObjectProperty<Runnable> onDelete = new SimpleObjectProperty<>(this, "onDelete");
|
|
||||||
private final AdvancedListItem item;
|
|
||||||
private final Account account;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Label lblType;
|
|
||||||
@FXML
|
|
||||||
private Label lblServer;
|
|
||||||
@FXML
|
|
||||||
private Label lblCharacter;
|
|
||||||
@FXML
|
|
||||||
private Label lblEmail;
|
|
||||||
@FXML
|
|
||||||
private BorderPane paneServer;
|
|
||||||
@FXML
|
|
||||||
private BorderPane paneEmail;
|
|
||||||
@FXML
|
|
||||||
private ComponentList componentList;
|
|
||||||
@FXML
|
|
||||||
private JFXButton btnDelete;
|
|
||||||
@FXML
|
|
||||||
private JFXButton btnRefresh;
|
|
||||||
@FXML
|
|
||||||
private JFXProgressBar progressBar;
|
|
||||||
|
|
||||||
public AccountPage(Account account, AdvancedListItem item) {
|
|
||||||
this.account = account;
|
|
||||||
this.item = item;
|
|
||||||
|
|
||||||
title = new SimpleStringProperty(this, "title", i18n("account") + " - " + account.getCharacter());
|
|
||||||
|
|
||||||
FXUtils.loadFXML(this, "/assets/fxml/account.fxml");
|
|
||||||
|
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
|
||||||
AuthlibInjectorServer server = ((AuthlibInjectorAccount) account).getServer();
|
|
||||||
lblServer.setText(server.getName());
|
|
||||||
installTooltip(lblServer, server.getUrl());
|
|
||||||
} else {
|
|
||||||
componentList.removeChildren(paneServer);
|
|
||||||
|
|
||||||
if (account instanceof OfflineAccount) {
|
|
||||||
componentList.removeChildren(paneEmail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
btnDelete.setGraphic(SVG.delete(Theme.blackFillBinding(), 15, 15));
|
|
||||||
btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), 15, 15));
|
|
||||||
|
|
||||||
lblCharacter.setText(account.getCharacter());
|
|
||||||
lblType.setText(Accounts.getAccountTypeName(account));
|
|
||||||
lblEmail.setText(account.getUsername());
|
|
||||||
|
|
||||||
btnRefresh.setVisible(account instanceof YggdrasilAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private void onDelete() {
|
|
||||||
Accounts.getAccounts().remove(account);
|
|
||||||
Optional.ofNullable(onDelete.get()).ifPresent(Runnable::run);
|
|
||||||
}
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private void onRefresh() {
|
|
||||||
if (account instanceof YggdrasilAccount) {
|
|
||||||
progressBar.setVisible(true);
|
|
||||||
AccountHelper.refreshSkinAsync((YggdrasilAccount) account)
|
|
||||||
.finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> {
|
|
||||||
progressBar.setVisible(false);
|
|
||||||
|
|
||||||
if (isDependentsSucceeded) {
|
|
||||||
Image image = AccountHelper.getSkin((YggdrasilAccount) account, 4);
|
|
||||||
item.setImage(image, AccountHelper.getViewport(4));
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StringProperty titleProperty() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title.set(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Runnable getOnDelete() {
|
|
||||||
return onDelete.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectProperty<Runnable> onDeleteProperty() {
|
|
||||||
return onDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnDelete(Runnable onDelete) {
|
|
||||||
this.onDelete.set(onDelete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* 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 {http://www.gnu.org/licenses/}.
|
||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui;
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
import com.jfoenix.concurrency.JFXUtilities;
|
import com.jfoenix.concurrency.JFXUtilities;
|
||||||
import javafx.beans.InvalidationListener;
|
import javafx.beans.InvalidationListener;
|
||||||
@@ -23,14 +23,15 @@ import javafx.beans.property.ObjectProperty;
|
|||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import org.jackhuang.hmcl.event.EventBus;
|
import org.jackhuang.hmcl.event.EventBus;
|
||||||
import org.jackhuang.hmcl.event.ProfileChangedEvent;
|
import org.jackhuang.hmcl.event.ProfileChangedEvent;
|
||||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||||
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
|
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.setting.Settings;
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
|
import org.jackhuang.hmcl.ui.AdvancedListItemViewModel;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
import org.jackhuang.hmcl.ui.WeakListenerHelper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.advanced-list-box-item {
|
.advanced-list-box-item {
|
||||||
-fx-padding: 10 16 10 16;
|
-fx-padding: 0 16 0 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
.advanced-list-box-content {
|
.advanced-list-box-content {
|
||||||
|
|||||||
BIN
HMCL/src/main/resources/assets/img/craft_table.png
Normal file
BIN
HMCL/src/main/resources/assets/img/craft_table.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -48,11 +48,13 @@ account.injector.http=Warning: This server is using HTTP, which will cause your
|
|||||||
account.injector.server=Auth Server
|
account.injector.server=Auth Server
|
||||||
account.injector.server_url=Server URL
|
account.injector.server_url=Server URL
|
||||||
account.injector.server_name=Server Name
|
account.injector.server_name=Server Name
|
||||||
|
account.manage=Account List
|
||||||
account.methods=Login Type
|
account.methods=Login Type
|
||||||
account.methods.authlib_injector=authlib-injector
|
account.methods.authlib_injector=authlib-injector
|
||||||
account.methods.offline=Offline
|
account.methods.offline=Offline
|
||||||
account.methods.yggdrasil=Mojang
|
account.methods.yggdrasil=Mojang
|
||||||
account.missing=None
|
account.missing=No Account
|
||||||
|
account.missing.add=Click the button on the right to add
|
||||||
account.password=Password
|
account.password=Password
|
||||||
account.username=Name
|
account.username=Name
|
||||||
|
|
||||||
@@ -325,6 +327,7 @@ update.latest=This is latest Version.
|
|||||||
update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update.
|
update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update.
|
||||||
update.tooltip=Update
|
update.tooltip=Update
|
||||||
|
|
||||||
|
version=Games
|
||||||
version.cannot_read=Unable to gather the game version. Cannot continue auto-installing.
|
version.cannot_read=Unable to gather the game version. Cannot continue auto-installing.
|
||||||
version.forbidden_name=Forbidden name, do not use this.
|
version.forbidden_name=Forbidden name, do not use this.
|
||||||
version.game.old=Old
|
version.game.old=Old
|
||||||
|
|||||||
@@ -48,11 +48,13 @@ account.injector.http=警告:此伺服器使用不安全的 HTTP 協議,您
|
|||||||
account.injector.server=認證伺服器
|
account.injector.server=認證伺服器
|
||||||
account.injector.server_url=伺服器位址
|
account.injector.server_url=伺服器位址
|
||||||
account.injector.server_name=伺服器名稱
|
account.injector.server_name=伺服器名稱
|
||||||
|
account.manage=帳戶列表
|
||||||
account.methods=登入方式
|
account.methods=登入方式
|
||||||
account.methods.authlib_injector=authlib-injector 登入
|
account.methods.authlib_injector=authlib-injector 登入
|
||||||
account.methods.offline=離線模式
|
account.methods.offline=離線模式
|
||||||
account.methods.yggdrasil=正版登入
|
account.methods.yggdrasil=正版登入
|
||||||
account.missing=沒有帳戶
|
account.missing=沒有遊戲帳戶
|
||||||
|
account.missing.add=點擊右邊按鈕添加
|
||||||
account.password=密碼
|
account.password=密碼
|
||||||
account.username=使用者名稱
|
account.username=使用者名稱
|
||||||
|
|
||||||
@@ -325,6 +327,7 @@ update.latest=目前版本為最新版本
|
|||||||
update.no_browser=無法打開瀏覽器,網址已經複製到剪貼簿了,您可以手動複製網址打開頁面
|
update.no_browser=無法打開瀏覽器,網址已經複製到剪貼簿了,您可以手動複製網址打開頁面
|
||||||
update.tooltip=更新
|
update.tooltip=更新
|
||||||
|
|
||||||
|
version=遊戲
|
||||||
version.cannot_read=讀取遊戲版本失敗,無法進行自動安裝
|
version.cannot_read=讀取遊戲版本失敗,無法進行自動安裝
|
||||||
version.forbidden_name=此版本名稱不受支援,請換一個名字
|
version.forbidden_name=此版本名稱不受支援,請換一個名字
|
||||||
version.game.old=老舊版本
|
version.game.old=老舊版本
|
||||||
|
|||||||
@@ -48,11 +48,13 @@ account.injector.http=警告:此服务器使用不安全的 HTTP 协议,您
|
|||||||
account.injector.server=认证服务器
|
account.injector.server=认证服务器
|
||||||
account.injector.server_url=服务器地址
|
account.injector.server_url=服务器地址
|
||||||
account.injector.server_name=服务器名称
|
account.injector.server_name=服务器名称
|
||||||
|
account.manage=账户列表
|
||||||
account.methods=登录方式
|
account.methods=登录方式
|
||||||
account.methods.authlib_injector=authlib-injector 登录
|
account.methods.authlib_injector=authlib-injector 登录
|
||||||
account.methods.offline=离线模式
|
account.methods.offline=离线模式
|
||||||
account.methods.yggdrasil=正版登录
|
account.methods.yggdrasil=正版登录
|
||||||
account.missing=没有账户
|
account.missing=没有游戏账户
|
||||||
|
account.missing.add=点击右边按钮添加
|
||||||
account.password=密码
|
account.password=密码
|
||||||
account.username=用户名
|
account.username=用户名
|
||||||
|
|
||||||
@@ -325,6 +327,7 @@ update.latest=当前版本为最新版本
|
|||||||
update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面
|
update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面
|
||||||
update.tooltip=更新
|
update.tooltip=更新
|
||||||
|
|
||||||
|
version=游戏
|
||||||
version.cannot_read=读取游戏版本失败,无法进行自动安装
|
version.cannot_read=读取游戏版本失败,无法进行自动安装
|
||||||
version.forbidden_name=此版本名称不受支持,请换一个名字
|
version.forbidden_name=此版本名称不受支持,请换一个名字
|
||||||
version.game.old=远古版
|
version.game.old=远古版
|
||||||
|
|||||||
Reference in New Issue
Block a user