mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-03-13 17:46:58 +08:00
Add AutomatedToggleGroup & Refactor AccountList
This commit is contained in:
parent
83f7e61d37
commit
7da5b8fbc8
@ -22,6 +22,7 @@ import javafx.beans.property.ListProperty;
|
|||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleListProperty;
|
import javafx.beans.property.SimpleListProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
import javafx.scene.control.Skin;
|
import javafx.scene.control.Skin;
|
||||||
@ -32,16 +33,32 @@ public abstract class ListPage<T extends Node> extends Control {
|
|||||||
|
|
||||||
public abstract void add();
|
public abstract void add();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Skin<?> createDefaultSkin() {
|
||||||
|
return new ListPageSkin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableList<T> getItems() {
|
||||||
|
return items.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(ObservableList<T> items) {
|
||||||
|
this.items.set(items);
|
||||||
|
}
|
||||||
|
|
||||||
public ListProperty<T> itemsProperty() {
|
public ListProperty<T> itemsProperty() {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLoading() {
|
||||||
|
return loading.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoading(boolean loading) {
|
||||||
|
this.loading.set(loading);
|
||||||
|
}
|
||||||
|
|
||||||
public BooleanProperty loadingProperty() {
|
public BooleanProperty loadingProperty() {
|
||||||
return loading;
|
return loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Skin<?> createDefaultSkin() {
|
|
||||||
return new ListPageSkin(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,48 +19,22 @@ package org.jackhuang.hmcl.ui.account;
|
|||||||
|
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.scene.control.ToggleGroup;
|
|
||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.ListPage;
|
import org.jackhuang.hmcl.ui.ListPage;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
||||||
|
|
||||||
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;
|
||||||
|
import static org.jackhuang.hmcl.util.javafx.SelectedItemProperties.createSelectedItemPropertyFor;
|
||||||
|
|
||||||
public class AccountList extends ListPage<AccountListItem> implements DecoratorPage {
|
public class AccountList extends ListPage<AccountListItem> implements DecoratorPage {
|
||||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(i18n("account.manage"));
|
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("account.manage"));
|
||||||
private ObjectProperty<Account> selectedAccount = new SimpleObjectProperty<Account>() {
|
private final ListProperty<Account> accounts = new SimpleListProperty<>(this, "accounts", FXCollections.observableArrayList());
|
||||||
{
|
private final ObjectProperty<Account> selectedAccount;
|
||||||
itemsProperty().addListener(onInvalidating(this::invalidated));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidated() {
|
|
||||||
Account selected = get();
|
|
||||||
itemsProperty().forEach(item -> item.selectedProperty().set(item.getAccount() == selected));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final ListProperty<Account> accounts = new SimpleListProperty<>(FXCollections.observableArrayList());
|
|
||||||
|
|
||||||
private ToggleGroup toggleGroup;
|
|
||||||
private final ObservableList<AccountListItem> accountItems;
|
|
||||||
|
|
||||||
public AccountList() {
|
public AccountList() {
|
||||||
toggleGroup = new ToggleGroup();
|
setItems(MappedObservableList.create(accounts, AccountListItem::new));
|
||||||
|
selectedAccount = createSelectedItemPropertyFor(getItems(), Account.class);
|
||||||
accountItems = MappedObservableList.create(
|
|
||||||
accountsProperty(),
|
|
||||||
account -> new AccountListItem(toggleGroup, account));
|
|
||||||
|
|
||||||
itemsProperty().bindContent(accountItems);
|
|
||||||
|
|
||||||
toggleGroup.selectedToggleProperty().addListener((o, a, toggle) -> {
|
|
||||||
if (toggle == null || toggle.getUserData() == null) return;
|
|
||||||
selectedAccount.set(((AccountListItem) toggle.getUserData()).getAccount());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<Account> selectedAccountProperty() {
|
public ObjectProperty<Account> selectedAccountProperty() {
|
||||||
|
@ -18,9 +18,8 @@
|
|||||||
package org.jackhuang.hmcl.ui.account;
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.scene.control.Control;
|
|
||||||
import javafx.scene.control.Skin;
|
import javafx.scene.control.Skin;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleButton;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||||
@ -33,17 +32,17 @@ import org.jackhuang.hmcl.task.Schedulers;
|
|||||||
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public class AccountListItem extends Control {
|
public class AccountListItem extends ToggleButton {
|
||||||
|
|
||||||
private final Account account;
|
private final Account account;
|
||||||
private final ToggleGroup toggleGroup;
|
|
||||||
private final StringProperty title = new SimpleStringProperty();
|
private final StringProperty title = new SimpleStringProperty();
|
||||||
private final StringProperty subtitle = new SimpleStringProperty();
|
private final StringProperty subtitle = new SimpleStringProperty();
|
||||||
private final BooleanProperty selected = new SimpleBooleanProperty();
|
|
||||||
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
public AccountListItem(ToggleGroup toggleGroup, Account account) {
|
public AccountListItem(Account account) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.toggleGroup = toggleGroup;
|
getStyleClass().clear();
|
||||||
|
setUserData(account);
|
||||||
|
|
||||||
StringBuilder subtitleString = new StringBuilder(Accounts.getAccountTypeName(account));
|
StringBuilder subtitleString = new StringBuilder(Accounts.getAccountTypeName(account));
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
if (account instanceof AuthlibInjectorAccount) {
|
||||||
@ -56,7 +55,6 @@ public class AccountListItem extends Control {
|
|||||||
else
|
else
|
||||||
title.set(account.getUsername() + " - " + account.getCharacter());
|
title.set(account.getUsername() + " - " + account.getCharacter());
|
||||||
subtitle.set(subtitleString.toString());
|
subtitle.set(subtitleString.toString());
|
||||||
selected.set(Accounts.selectedAccountProperty().get() == account);
|
|
||||||
|
|
||||||
final int scaleRatio = 4;
|
final int scaleRatio = 4;
|
||||||
Image image = account instanceof YggdrasilAccount ?
|
Image image = account instanceof YggdrasilAccount ?
|
||||||
@ -70,30 +68,6 @@ public class AccountListItem extends Control {
|
|||||||
return new AccountListItemSkin(this);
|
return new AccountListItemSkin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 void refresh() {
|
public void refresh() {
|
||||||
if (account instanceof YggdrasilAccount) {
|
if (account instanceof YggdrasilAccount) {
|
||||||
// progressBar.setVisible(true);
|
// progressBar.setVisible(true);
|
||||||
@ -113,4 +87,44 @@ public class AccountListItem extends Control {
|
|||||||
public void remove() {
|
public void remove() {
|
||||||
Accounts.getAccounts().remove(account);
|
Accounts.getAccounts().remove(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title.set(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubtitle() {
|
||||||
|
return subtitle.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubtitle(String subtitle) {
|
||||||
|
this.subtitle.set(subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getImage() {
|
||||||
|
return image.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(Image image) {
|
||||||
|
this.image.set(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,7 @@ public class AccountListItemSkin extends SkinBase<AccountListItem> {
|
|||||||
|
|
||||||
JFXRadioButton chkSelected = new JFXRadioButton();
|
JFXRadioButton chkSelected = new JFXRadioButton();
|
||||||
BorderPane.setAlignment(chkSelected, Pos.CENTER);
|
BorderPane.setAlignment(chkSelected, Pos.CENTER);
|
||||||
chkSelected.setUserData(skinnable);
|
|
||||||
chkSelected.selectedProperty().bindBidirectional(skinnable.selectedProperty());
|
chkSelected.selectedProperty().bindBidirectional(skinnable.selectedProperty());
|
||||||
chkSelected.setToggleGroup(skinnable.getToggleGroup());
|
|
||||||
root.setLeft(chkSelected);
|
root.setLeft(chkSelected);
|
||||||
|
|
||||||
HBox center = new HBox();
|
HBox center = new HBox();
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.javafx;
|
||||||
|
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.control.Toggle;
|
||||||
|
import javafx.scene.control.ToggleGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yushijinhun
|
||||||
|
*/
|
||||||
|
public class AutomatedToggleGroup extends ToggleGroup {
|
||||||
|
|
||||||
|
private final ObservableList<? extends Toggle> toggles;
|
||||||
|
private final ListChangeListener<Toggle> listListener;
|
||||||
|
|
||||||
|
public AutomatedToggleGroup(ObservableList<? extends Toggle> toggles) {
|
||||||
|
this.toggles = toggles;
|
||||||
|
|
||||||
|
listListener = change -> {
|
||||||
|
while (change.next()) {
|
||||||
|
change.getRemoved().forEach(it -> it.setToggleGroup(null));
|
||||||
|
change.getAddedSubList().forEach(it -> it.setToggleGroup(this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
toggles.addListener(listListener);
|
||||||
|
|
||||||
|
toggles.forEach(it -> it.setToggleGroup(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
toggles.removeListener(listListener);
|
||||||
|
toggles.forEach(it -> it.setToggleGroup(null));
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,7 @@ import javafx.beans.InvalidationListener;
|
|||||||
import javafx.beans.WeakInvalidationListener;
|
import javafx.beans.WeakInvalidationListener;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.control.ComboBox;
|
import javafx.scene.control.ComboBox;
|
||||||
import javafx.scene.control.SelectionModel;
|
import javafx.scene.control.SelectionModel;
|
||||||
import javafx.scene.control.Toggle;
|
import javafx.scene.control.Toggle;
|
||||||
@ -41,6 +42,7 @@ public final class SelectedItemProperties {
|
|||||||
|
|
||||||
private static final String PROP_PREFIX = SelectedItemProperties.class.getName();
|
private static final String PROP_PREFIX = SelectedItemProperties.class.getName();
|
||||||
|
|
||||||
|
// ==== ComboBox ====
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> ObjectProperty<T> selectedItemPropertyFor(ComboBox<T> comboBox) {
|
public static <T> ObjectProperty<T> selectedItemPropertyFor(ComboBox<T> comboBox) {
|
||||||
return (ObjectProperty<T>) comboBox.getProperties().computeIfAbsent(
|
return (ObjectProperty<T>) comboBox.getProperties().computeIfAbsent(
|
||||||
@ -54,7 +56,9 @@ public final class SelectedItemProperties {
|
|||||||
.flatMap(SelectionModel::selectedItemProperty),
|
.flatMap(SelectionModel::selectedItemProperty),
|
||||||
modelProperty.getValue()::select);
|
modelProperty.getValue()::select);
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
|
||||||
|
// ==== Toggle ====
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static ObjectProperty<Toggle> selectedTogglePropertyFor(ToggleGroup toggleGroup) {
|
public static ObjectProperty<Toggle> selectedTogglePropertyFor(ToggleGroup toggleGroup) {
|
||||||
return (ObjectProperty<Toggle>) toggleGroup.getProperties().computeIfAbsent(
|
return (ObjectProperty<Toggle>) toggleGroup.getProperties().computeIfAbsent(
|
||||||
@ -68,6 +72,10 @@ public final class SelectedItemProperties {
|
|||||||
toggleGroup::selectToggle);
|
toggleGroup::selectToggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> ObjectProperty<T> createSelectedItemPropertyFor(ObservableList<? extends Toggle> items, Class<T> userdataType) {
|
||||||
|
return selectedItemPropertyFor(new AutomatedToggleGroup(items), userdataType);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> ObjectProperty<T> selectedItemPropertyFor(ToggleGroup toggleGroup, Class<T> userdataType) {
|
public static <T> ObjectProperty<T> selectedItemPropertyFor(ToggleGroup toggleGroup, Class<T> userdataType) {
|
||||||
return (ObjectProperty<T>) toggleGroup.getProperties().computeIfAbsent(
|
return (ObjectProperty<T>) toggleGroup.getProperties().computeIfAbsent(
|
||||||
@ -113,6 +121,7 @@ public final class SelectedItemProperties {
|
|||||||
|
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
|
||||||
private SelectedItemProperties() {
|
private SelectedItemProperties() {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user