优化 AdvancedListItem (#5460)
This commit is contained in:
@@ -312,14 +312,6 @@ public final class FXUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Node wrap(Node node) {
|
|
||||||
return limitingSize(node, 30, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Node wrap(SVG svg) {
|
|
||||||
return wrap(svg.createIcon(20));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ListenerPair<T> {
|
private static class ListenerPair<T> {
|
||||||
private final ObservableValue<T> value;
|
private final ObservableValue<T> value;
|
||||||
private final ChangeListener<? super T> listener;
|
private final ChangeListener<? super T> listener;
|
||||||
|
|||||||
@@ -130,20 +130,23 @@ public enum SVG {
|
|||||||
|
|
||||||
public static final double DEFAULT_SIZE = 24;
|
public static final double DEFAULT_SIZE = 24;
|
||||||
|
|
||||||
private final String path;
|
private final String rawPath;
|
||||||
|
private String path;
|
||||||
|
|
||||||
SVG(String path) {
|
SVG(String rawPath) {
|
||||||
// We move the current point so that SVGPath will treat 0 0 24 24 as the layout bounds
|
this.rawPath = rawPath;
|
||||||
this.path = "M24 24ZM0 0Z" + path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
|
if (path == null)
|
||||||
|
// We move the current point so that SVGPath will treat 0 0 24 24 as the layout bounds
|
||||||
|
path = "M24 24ZM0 0Z" + rawPath;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SVGPath createSVGPath() {
|
public SVGPath createSVGPath() {
|
||||||
var p = new SVGPath();
|
var p = new SVGPath();
|
||||||
p.setContent(path);
|
p.setContent(getPath());
|
||||||
p.getStyleClass().add("svg");
|
p.getStyleClass().add("svg");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import javafx.beans.binding.Bindings;
|
|||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
@@ -76,9 +77,10 @@ public class AccountAdvancedListItem extends AdvancedListItem {
|
|||||||
FXUtils.installFastTooltip(this, tooltip);
|
FXUtils.installFastTooltip(this, tooltip);
|
||||||
|
|
||||||
canvas = new Canvas(32, 32);
|
canvas = new Canvas(32, 32);
|
||||||
setLeftGraphic(canvas);
|
canvas.setMouseTransparent(true);
|
||||||
|
AdvancedListItem.setAlignment(canvas, Pos.CENTER);
|
||||||
|
|
||||||
setActionButtonVisible(false);
|
setLeftGraphic(canvas);
|
||||||
|
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
this.accountProperty().set(account);
|
this.accountProperty().set(account);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.account;
|
package org.jackhuang.hmcl.ui.account;
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.ListProperty;
|
import javafx.beans.property.ListProperty;
|
||||||
@@ -54,7 +53,6 @@ import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.setting.ConfigHolder.globalConfig;
|
import static org.jackhuang.hmcl.setting.ConfigHolder.globalConfig;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.wrap;
|
|
||||||
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.ExtendedProperties.createSelectedItemPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.createSelectedItemPropertyFor;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
@@ -130,35 +128,25 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
|||||||
|
|
||||||
AdvancedListItem microsoftItem = new AdvancedListItem();
|
AdvancedListItem microsoftItem = new AdvancedListItem();
|
||||||
microsoftItem.getStyleClass().add("navigation-drawer-item");
|
microsoftItem.getStyleClass().add("navigation-drawer-item");
|
||||||
microsoftItem.setActionButtonVisible(false);
|
|
||||||
microsoftItem.setTitle(i18n("account.methods.microsoft"));
|
microsoftItem.setTitle(i18n("account.methods.microsoft"));
|
||||||
microsoftItem.setLeftGraphic(wrap(SVG.MICROSOFT));
|
microsoftItem.setLeftIcon(SVG.MICROSOFT);
|
||||||
microsoftItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MICROSOFT)));
|
microsoftItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MICROSOFT)));
|
||||||
|
|
||||||
AdvancedListItem offlineItem = new AdvancedListItem();
|
AdvancedListItem offlineItem = new AdvancedListItem();
|
||||||
offlineItem.getStyleClass().add("navigation-drawer-item");
|
offlineItem.getStyleClass().add("navigation-drawer-item");
|
||||||
offlineItem.setActionButtonVisible(false);
|
|
||||||
offlineItem.setTitle(i18n("account.methods.offline"));
|
offlineItem.setTitle(i18n("account.methods.offline"));
|
||||||
offlineItem.setLeftGraphic(wrap(SVG.PERSON));
|
offlineItem.setLeftIcon(SVG.PERSON);
|
||||||
offlineItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_OFFLINE)));
|
offlineItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_OFFLINE)));
|
||||||
|
|
||||||
VBox boxAuthServers = new VBox();
|
VBox boxAuthServers = new VBox();
|
||||||
authServerItems = MappedObservableList.create(skinnable.authServersProperty(), server -> {
|
authServerItems = MappedObservableList.create(skinnable.authServersProperty(), server -> {
|
||||||
AdvancedListItem item = new AdvancedListItem();
|
AdvancedListItem item = new AdvancedListItem();
|
||||||
item.getStyleClass().add("navigation-drawer-item");
|
item.getStyleClass().add("navigation-drawer-item");
|
||||||
item.setLeftGraphic(wrap(SVG.DRESSER));
|
item.setLeftIcon(SVG.DRESSER);
|
||||||
item.setOnAction(e -> Controllers.dialog(new CreateAccountPane(server)));
|
item.setOnAction(e -> Controllers.dialog(new CreateAccountPane(server)));
|
||||||
|
item.setRightAction(SVG.CLOSE, () -> Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), () -> {
|
||||||
JFXButton btnRemove = new JFXButton();
|
|
||||||
btnRemove.setOnAction(e -> {
|
|
||||||
Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), () -> {
|
|
||||||
skinnable.authServersProperty().remove(server);
|
skinnable.authServersProperty().remove(server);
|
||||||
}, null);
|
}, null));
|
||||||
e.consume();
|
|
||||||
});
|
|
||||||
btnRemove.getStyleClass().add("toggle-icon4");
|
|
||||||
btnRemove.setGraphic(SVG.CLOSE.createIcon(14));
|
|
||||||
item.setRightGraphic(btnRemove);
|
|
||||||
|
|
||||||
ObservableValue<String> title = BindingMapping.of(server, AuthlibInjectorServer::getName);
|
ObservableValue<String> title = BindingMapping.of(server, AuthlibInjectorServer::getName);
|
||||||
item.titleProperty().bind(title);
|
item.titleProperty().bind(title);
|
||||||
@@ -206,8 +194,7 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
|||||||
addAuthServerItem.getStyleClass().add("navigation-drawer-item");
|
addAuthServerItem.getStyleClass().add("navigation-drawer-item");
|
||||||
addAuthServerItem.setTitle(i18n("account.injector.add"));
|
addAuthServerItem.setTitle(i18n("account.injector.add"));
|
||||||
addAuthServerItem.setSubtitle(i18n("account.methods.authlib_injector"));
|
addAuthServerItem.setSubtitle(i18n("account.methods.authlib_injector"));
|
||||||
addAuthServerItem.setActionButtonVisible(false);
|
addAuthServerItem.setLeftIcon(SVG.ADD_CIRCLE);
|
||||||
addAuthServerItem.setLeftGraphic(wrap(SVG.ADD_CIRCLE));
|
|
||||||
addAuthServerItem.setOnAction(e -> Controllers.dialog(new AddAuthlibInjectorServerPane()));
|
addAuthServerItem.setOnAction(e -> Controllers.dialog(new AddAuthlibInjectorServerPane()));
|
||||||
VBox.setMargin(addAuthServerItem, new Insets(0, 0, 12, 0));
|
VBox.setMargin(addAuthServerItem, new Insets(0, 0, 12, 0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,10 +71,9 @@ public class AdvancedListBox extends ScrollPane {
|
|||||||
private AdvancedListItem createNavigationDrawerItem(String title, SVG leftGraphic) {
|
private AdvancedListItem createNavigationDrawerItem(String title, SVG leftGraphic) {
|
||||||
AdvancedListItem item = new AdvancedListItem();
|
AdvancedListItem item = new AdvancedListItem();
|
||||||
item.getStyleClass().add("navigation-drawer-item");
|
item.getStyleClass().add("navigation-drawer-item");
|
||||||
item.setActionButtonVisible(false);
|
|
||||||
item.setTitle(title);
|
item.setTitle(title);
|
||||||
if (leftGraphic != null) {
|
if (leftGraphic != null) {
|
||||||
item.setLeftGraphic(FXUtils.wrap(leftGraphic));
|
item.setLeftIcon(leftGraphic);
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@@ -101,19 +100,22 @@ public class AdvancedListBox extends ScrollPane {
|
|||||||
return add(item);
|
return add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousNameCombination")
|
||||||
public AdvancedListBox addNavigationDrawerTab(TabHeader tabHeader, TabControl.Tab<?> tab, String title,
|
public AdvancedListBox addNavigationDrawerTab(TabHeader tabHeader, TabControl.Tab<?> tab, String title,
|
||||||
SVG unselectedGraphic, SVG selectedGraphic) {
|
SVG unselectedGraphic, SVG selectedGraphic) {
|
||||||
AdvancedListItem item = createNavigationDrawerItem(title, null);
|
AdvancedListItem item = createNavigationDrawerItem(title, null);
|
||||||
item.activeProperty().bind(tabHeader.getSelectionModel().selectedItemProperty().isEqualTo(tab));
|
item.activeProperty().bind(tabHeader.getSelectionModel().selectedItemProperty().isEqualTo(tab));
|
||||||
item.setOnAction(e -> tabHeader.select(tab));
|
item.setOnAction(e -> tabHeader.select(tab));
|
||||||
|
|
||||||
Node unselectedIcon = unselectedGraphic.createIcon(20);
|
Node unselectedIcon = unselectedGraphic.createIcon(AdvancedListItem.LEFT_ICON_SIZE);
|
||||||
Node selectedIcon = selectedGraphic.createIcon(20);
|
Node selectedIcon = selectedGraphic.createIcon(AdvancedListItem.LEFT_ICON_SIZE);
|
||||||
|
|
||||||
TransitionPane leftGraphic = new TransitionPane();
|
TransitionPane leftGraphic = new TransitionPane();
|
||||||
|
AdvancedListItem.setAlignment(leftGraphic, Pos.CENTER);
|
||||||
|
leftGraphic.setMouseTransparent(true);
|
||||||
leftGraphic.setAlignment(Pos.CENTER);
|
leftGraphic.setAlignment(Pos.CENTER);
|
||||||
FXUtils.setLimitWidth(leftGraphic, 30);
|
FXUtils.setLimitWidth(leftGraphic, AdvancedListItem.LEFT_GRAPHIC_SIZE);
|
||||||
FXUtils.setLimitHeight(leftGraphic, 20);
|
FXUtils.setLimitHeight(leftGraphic, AdvancedListItem.LEFT_ICON_SIZE);
|
||||||
leftGraphic.setPadding(Insets.EMPTY);
|
leftGraphic.setPadding(Insets.EMPTY);
|
||||||
leftGraphic.setContent(item.isActive() ? selectedIcon : unselectedIcon, ContainerAnimations.NONE);
|
leftGraphic.setContent(item.isActive() ? selectedIcon : unselectedIcon, ContainerAnimations.NONE);
|
||||||
FXUtils.onChange(item.activeProperty(), active ->
|
FXUtils.onChange(item.activeProperty(), active ->
|
||||||
|
|||||||
@@ -17,105 +17,134 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.construct;
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
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;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.image.ImageView;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
|
||||||
|
|
||||||
public class AdvancedListItem extends Control {
|
public class AdvancedListItem extends Control {
|
||||||
private final ObjectProperty<Node> leftGraphic = new SimpleObjectProperty<>(this, "leftGraphic");
|
public static final double LEFT_GRAPHIC_SIZE = 32;
|
||||||
private final ObjectProperty<Node> rightGraphic = new SimpleObjectProperty<>(this, "rightGraphic");
|
public static final double LEFT_ICON_SIZE = 20;
|
||||||
private final StringProperty title = new SimpleStringProperty(this, "title");
|
public static final Insets LEFT_ICON_MARGIN = new Insets(0, 6, 0, 6);
|
||||||
private final BooleanProperty active = new SimpleBooleanProperty(this, "active");
|
|
||||||
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
|
public static void setMargin(Node graphic, Insets margin) {
|
||||||
private final BooleanProperty actionButtonVisible = new SimpleBooleanProperty(this, "actionButtonVisible", true);
|
BorderPane.setMargin(graphic, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAlignment(Node graphic, Pos alignment) {
|
||||||
|
BorderPane.setAlignment(graphic, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
public AdvancedListItem() {
|
public AdvancedListItem() {
|
||||||
getStyleClass().add("advanced-list-item");
|
getStyleClass().add("advanced-list-item");
|
||||||
FXUtils.onClicked(this, () -> fireEvent(new ActionEvent()));
|
FXUtils.onClicked(this, () -> fireEvent(new ActionEvent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node getLeftGraphic() {
|
private final ObjectProperty<Node> leftGraphic = new SimpleObjectProperty<>(this, "leftGraphic");
|
||||||
return leftGraphic.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectProperty<Node> leftGraphicProperty() {
|
public ObjectProperty<Node> leftGraphicProperty() {
|
||||||
return leftGraphic;
|
return leftGraphic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node getLeftGraphic() {
|
||||||
|
return leftGraphic.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void setLeftGraphic(Node leftGraphic) {
|
public void setLeftGraphic(Node leftGraphic) {
|
||||||
this.leftGraphic.set(leftGraphic);
|
this.leftGraphic.set(leftGraphic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node getRightGraphic() {
|
public void setLeftIcon(SVG svg) {
|
||||||
return rightGraphic.get();
|
Node icon = svg.createIcon(LEFT_ICON_SIZE);
|
||||||
|
icon.setMouseTransparent(true);
|
||||||
|
BorderPane.setMargin(icon, LEFT_ICON_MARGIN);
|
||||||
|
BorderPane.setAlignment(icon, Pos.CENTER);
|
||||||
|
leftGraphicProperty().set(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ObjectProperty<Node> rightGraphic = new SimpleObjectProperty<>(this, "rightGraphic");
|
||||||
|
|
||||||
public ObjectProperty<Node> rightGraphicProperty() {
|
public ObjectProperty<Node> rightGraphicProperty() {
|
||||||
return rightGraphic;
|
return rightGraphic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node getRightGraphic() {
|
||||||
|
return rightGraphic.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void setRightGraphic(Node rightGraphic) {
|
public void setRightGraphic(Node rightGraphic) {
|
||||||
this.rightGraphic.set(rightGraphic);
|
this.rightGraphic.set(rightGraphic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public void setRightAction(SVG icon, Runnable action) {
|
||||||
return title.get();
|
var button = new JFXButton();
|
||||||
|
button.setOnAction(e -> {
|
||||||
|
action.run();
|
||||||
|
e.consume();
|
||||||
|
});
|
||||||
|
button.getStyleClass().add("toggle-icon4");
|
||||||
|
button.setGraphic(icon.createIcon(14));
|
||||||
|
setAlignment(button, Pos.CENTER);
|
||||||
|
setRightGraphic(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final StringProperty title = new SimpleStringProperty(this, "title");
|
||||||
|
|
||||||
public StringProperty titleProperty() {
|
public StringProperty titleProperty() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
this.title.set(title);
|
this.title.set(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
|
||||||
return active.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BooleanProperty activeProperty() {
|
public StringProperty subtitleProperty() {
|
||||||
return active;
|
return subtitle;
|
||||||
}
|
|
||||||
|
|
||||||
public void setActive(boolean active) {
|
|
||||||
this.active.set(active);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSubtitle() {
|
public String getSubtitle() {
|
||||||
return subtitle.get();
|
return subtitle.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty subtitleProperty() {
|
|
||||||
return subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubtitle(String subtitle) {
|
public void setSubtitle(String subtitle) {
|
||||||
this.subtitle.set(subtitle);
|
this.subtitle.set(subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActionButtonVisible() {
|
private final BooleanProperty active = new SimpleBooleanProperty(this, "active");
|
||||||
return actionButtonVisible.get();
|
|
||||||
|
public BooleanProperty activeProperty() {
|
||||||
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanProperty actionButtonVisibleProperty() {
|
public boolean isActive() {
|
||||||
return actionButtonVisible;
|
return active.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActionButtonVisible(boolean actionButtonVisible) {
|
public void setActive(boolean active) {
|
||||||
this.actionButtonVisible.set(actionButtonVisible);
|
this.active.set(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ObjectProperty<EventHandler<ActionEvent>> onAction = new SimpleObjectProperty<>(this, "onAction") {
|
||||||
|
@Override
|
||||||
|
protected void invalidated() {
|
||||||
|
setEventHandler(ActionEvent.ACTION, get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {
|
public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {
|
||||||
return onAction;
|
return onAction;
|
||||||
}
|
}
|
||||||
@@ -128,32 +157,9 @@ public class AdvancedListItem extends Control {
|
|||||||
return onActionProperty().get();
|
return onActionProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectProperty<EventHandler<ActionEvent>> onAction = new SimpleObjectProperty<EventHandler<ActionEvent>>(this, "onAction") {
|
|
||||||
@Override
|
|
||||||
protected void invalidated() {
|
|
||||||
setEventHandler(ActionEvent.ACTION, get());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Skin<?> createDefaultSkin() {
|
protected Skin<?> createDefaultSkin() {
|
||||||
return new AdvancedListItemSkin(this);
|
return new AdvancedListItemSkin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Node, ImageView> createImageView(Image image) {
|
|
||||||
return createImageView(image, 32, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Pair<Node, ImageView> createImageView(Image image, double width, double height) {
|
|
||||||
StackPane imageViewContainer = new StackPane();
|
|
||||||
FXUtils.setLimitWidth(imageViewContainer, width);
|
|
||||||
FXUtils.setLimitHeight(imageViewContainer, height);
|
|
||||||
|
|
||||||
ImageView imageView = new ImageView();
|
|
||||||
FXUtils.limitSize(imageView, width, height);
|
|
||||||
imageView.setPreserveRatio(true);
|
|
||||||
imageView.setImage(image);
|
|
||||||
imageViewContainer.getChildren().setAll(imageView);
|
|
||||||
return pair(imageViewContainer, imageView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,8 @@
|
|||||||
package org.jackhuang.hmcl.ui.construct;
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.HBox;
|
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
|
||||||
public class AdvancedListItemSkin extends SkinBase<AdvancedListItem> {
|
public class AdvancedListItemSkin extends SkinBase<AdvancedListItem> {
|
||||||
@@ -40,41 +38,14 @@ public class AdvancedListItemSkin extends SkinBase<AdvancedListItem> {
|
|||||||
|
|
||||||
RipplerContainer container = new RipplerContainer(root);
|
RipplerContainer container = new RipplerContainer(root);
|
||||||
|
|
||||||
HBox left = new HBox();
|
|
||||||
left.setAlignment(Pos.CENTER_LEFT);
|
|
||||||
left.setMouseTransparent(true);
|
|
||||||
|
|
||||||
TwoLineListItem item = new TwoLineListItem();
|
TwoLineListItem item = new TwoLineListItem();
|
||||||
root.setCenter(item);
|
root.setCenter(item);
|
||||||
item.setMouseTransparent(true);
|
item.setMouseTransparent(true);
|
||||||
item.titleProperty().bind(skinnable.titleProperty());
|
item.titleProperty().bind(skinnable.titleProperty());
|
||||||
item.subtitleProperty().bind(skinnable.subtitleProperty());
|
item.subtitleProperty().bind(skinnable.subtitleProperty());
|
||||||
|
|
||||||
FXUtils.onChangeAndOperate(skinnable.leftGraphicProperty(),
|
root.leftProperty().bind(skinnable.leftGraphicProperty());
|
||||||
newGraphic -> {
|
root.rightProperty().bind(skinnable.rightGraphicProperty());
|
||||||
if (newGraphic == null) {
|
|
||||||
left.getChildren().clear();
|
|
||||||
} else {
|
|
||||||
left.getChildren().setAll(newGraphic);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
root.setLeft(left);
|
|
||||||
|
|
||||||
HBox right = new HBox();
|
|
||||||
right.setAlignment(Pos.CENTER);
|
|
||||||
right.getStyleClass().add("toggle-icon4");
|
|
||||||
FXUtils.setLimitWidth(right, 40);
|
|
||||||
FXUtils.onChangeAndOperate(skinnable.rightGraphicProperty(),
|
|
||||||
newGraphic -> {
|
|
||||||
if (newGraphic == null) {
|
|
||||||
right.getChildren().clear();
|
|
||||||
} else {
|
|
||||||
right.getChildren().setAll(newGraphic);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
FXUtils.onChangeAndOperate(skinnable.actionButtonVisibleProperty(),
|
|
||||||
visible -> root.setRight(visible ? right : null));
|
|
||||||
|
|
||||||
getChildren().setAll(container);
|
getChildren().setAll(container);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.main;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXPopup;
|
import com.jfoenix.controls.JFXPopup;
|
||||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import org.jackhuang.hmcl.Metadata;
|
import org.jackhuang.hmcl.Metadata;
|
||||||
import org.jackhuang.hmcl.event.EventBus;
|
import org.jackhuang.hmcl.event.EventBus;
|
||||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||||
@@ -65,7 +66,6 @@ import java.util.Locale;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.wrap;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
@@ -171,16 +171,14 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
|
|||||||
|
|
||||||
// third item in left sidebar
|
// third item in left sidebar
|
||||||
AdvancedListItem gameItem = new AdvancedListItem();
|
AdvancedListItem gameItem = new AdvancedListItem();
|
||||||
gameItem.setLeftGraphic(wrap(SVG.FORMAT_LIST_BULLETED));
|
gameItem.setLeftIcon(SVG.FORMAT_LIST_BULLETED);
|
||||||
gameItem.setActionButtonVisible(false);
|
|
||||||
gameItem.setTitle(i18n("version.manage"));
|
gameItem.setTitle(i18n("version.manage"));
|
||||||
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
||||||
FXUtils.onSecondaryButtonClicked(gameItem, () -> showGameListPopupMenu(gameItem));
|
FXUtils.onSecondaryButtonClicked(gameItem, () -> showGameListPopupMenu(gameItem));
|
||||||
|
|
||||||
// forth item in left sidebar
|
// forth item in left sidebar
|
||||||
AdvancedListItem downloadItem = new AdvancedListItem();
|
AdvancedListItem downloadItem = new AdvancedListItem();
|
||||||
downloadItem.setLeftGraphic(wrap(SVG.DOWNLOAD));
|
downloadItem.setLeftIcon(SVG.DOWNLOAD);
|
||||||
downloadItem.setActionButtonVisible(false);
|
|
||||||
downloadItem.setTitle(i18n("download"));
|
downloadItem.setTitle(i18n("download"));
|
||||||
downloadItem.setOnAction(e -> {
|
downloadItem.setOnAction(e -> {
|
||||||
Controllers.getDownloadPage().showGameDownloads();
|
Controllers.getDownloadPage().showGameDownloads();
|
||||||
@@ -193,8 +191,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
|
|||||||
|
|
||||||
// fifth item in left sidebar
|
// fifth item in left sidebar
|
||||||
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
||||||
launcherSettingsItem.setLeftGraphic(wrap(SVG.SETTINGS));
|
launcherSettingsItem.setLeftIcon(SVG.SETTINGS);
|
||||||
launcherSettingsItem.setActionButtonVisible(false);
|
|
||||||
launcherSettingsItem.setTitle(i18n("settings"));
|
launcherSettingsItem.setTitle(i18n("settings"));
|
||||||
launcherSettingsItem.setOnAction(e -> {
|
launcherSettingsItem.setOnAction(e -> {
|
||||||
Controllers.getSettingsPage().showGameSettings(Profiles.getSelectedProfile());
|
Controllers.getSettingsPage().showGameSettings(Profiles.getSelectedProfile());
|
||||||
@@ -206,8 +203,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
|
|||||||
|
|
||||||
// sixth item in left sidebar
|
// sixth item in left sidebar
|
||||||
AdvancedListItem terracottaItem = new AdvancedListItem();
|
AdvancedListItem terracottaItem = new AdvancedListItem();
|
||||||
terracottaItem.setLeftGraphic(wrap(SVG.GRAPH2));
|
terracottaItem.setLeftIcon(SVG.GRAPH2);
|
||||||
terracottaItem.setActionButtonVisible(false);
|
|
||||||
terracottaItem.setTitle(i18n("terracotta"));
|
terracottaItem.setTitle(i18n("terracotta"));
|
||||||
terracottaItem.setOnAction(e -> {
|
terracottaItem.setOnAction(e -> {
|
||||||
if (TerracottaMetadata.PROVIDER != null) {
|
if (TerracottaMetadata.PROVIDER != null) {
|
||||||
@@ -249,7 +245,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
|
|||||||
setCenter(getSkinnable().getMainPage());
|
setCenter(getSkinnable().getMainPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showGameListPopupMenu(AdvancedListItem gameListItem) {
|
public void showGameListPopupMenu(Region gameListItem) {
|
||||||
GameListPopupMenu.show(gameListItem,
|
GameListPopupMenu.show(gameListItem,
|
||||||
JFXPopup.PopupVPosition.TOP,
|
JFXPopup.PopupVPosition.TOP,
|
||||||
JFXPopup.PopupHPosition.LEFT,
|
JFXPopup.PopupHPosition.LEFT,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.profile;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
@@ -35,7 +36,6 @@ public class ProfileListItemSkin extends SkinBase<ProfileListItem> {
|
|||||||
public ProfileListItemSkin(ProfileListItem skinnable) {
|
public ProfileListItemSkin(ProfileListItem skinnable) {
|
||||||
super(skinnable);
|
super(skinnable);
|
||||||
|
|
||||||
|
|
||||||
BorderPane root = new BorderPane();
|
BorderPane root = new BorderPane();
|
||||||
root.setPickOnBounds(false);
|
root.setPickOnBounds(false);
|
||||||
RipplerContainer container = new RipplerContainer(root);
|
RipplerContainer container = new RipplerContainer(root);
|
||||||
@@ -46,7 +46,9 @@ public class ProfileListItemSkin extends SkinBase<ProfileListItem> {
|
|||||||
|
|
||||||
FXUtils.onClicked(getSkinnable(), () -> getSkinnable().setSelected(true));
|
FXUtils.onClicked(getSkinnable(), () -> getSkinnable().setSelected(true));
|
||||||
|
|
||||||
Node left = FXUtils.wrap(SVG.FOLDER);
|
Node left = SVG.FOLDER.createIcon(20);
|
||||||
|
left.setMouseTransparent(true);
|
||||||
|
BorderPane.setMargin(left, new Insets(0, 6, 0, 6));
|
||||||
root.setLeft(left);
|
root.setLeft(left);
|
||||||
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
|
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.versions;
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import org.jackhuang.hmcl.event.Event;
|
import org.jackhuang.hmcl.event.Event;
|
||||||
@@ -26,7 +27,6 @@ import org.jackhuang.hmcl.setting.VersionIconType;
|
|||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.WeakListenerHolder;
|
import org.jackhuang.hmcl.ui.WeakListenerHolder;
|
||||||
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
|
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -39,14 +39,20 @@ public class GameAdvancedListItem extends AdvancedListItem {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private Consumer<Event> onVersionIconChangedListener;
|
private Consumer<Event> onVersionIconChangedListener;
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousNameCombination")
|
||||||
public GameAdvancedListItem() {
|
public GameAdvancedListItem() {
|
||||||
Pair<Node, ImageView> view = createImageView(null);
|
this.imageView = new ImageView();
|
||||||
setLeftGraphic(view.getKey());
|
FXUtils.limitSize(imageView, LEFT_GRAPHIC_SIZE, LEFT_GRAPHIC_SIZE);
|
||||||
imageView = view.getValue();
|
imageView.setPreserveRatio(true);
|
||||||
|
imageView.setImage(null);
|
||||||
|
|
||||||
|
Node imageViewWrapper = FXUtils.limitingSize(imageView, LEFT_GRAPHIC_SIZE, LEFT_GRAPHIC_SIZE);
|
||||||
|
imageView.setMouseTransparent(true);
|
||||||
|
AdvancedListItem.setAlignment(imageViewWrapper, Pos.CENTER);
|
||||||
|
setLeftGraphic(imageViewWrapper);
|
||||||
|
|
||||||
holder.add(FXUtils.onWeakChangeAndOperate(Profiles.selectedVersionProperty(), this::loadVersion));
|
holder.add(FXUtils.onWeakChangeAndOperate(Profiles.selectedVersionProperty(), this::loadVersion));
|
||||||
|
|
||||||
setActionButtonVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadVersion(String version) {
|
private void loadVersion(String version) {
|
||||||
|
|||||||
@@ -69,8 +69,7 @@ public class GameListPage extends DecoratorAnimatedPage implements DecoratorPage
|
|||||||
AdvancedListItem addProfileItem = new AdvancedListItem();
|
AdvancedListItem addProfileItem = new AdvancedListItem();
|
||||||
addProfileItem.getStyleClass().add("navigation-drawer-item");
|
addProfileItem.getStyleClass().add("navigation-drawer-item");
|
||||||
addProfileItem.setTitle(i18n("profile.new"));
|
addProfileItem.setTitle(i18n("profile.new"));
|
||||||
addProfileItem.setActionButtonVisible(false);
|
addProfileItem.setLeftIcon(SVG.ADD_CIRCLE);
|
||||||
addProfileItem.setLeftGraphic(FXUtils.wrap(SVG.ADD_CIRCLE));
|
|
||||||
addProfileItem.setOnAction(e -> Controllers.navigate(new ProfilePage(null)));
|
addProfileItem.setOnAction(e -> Controllers.navigate(new ProfilePage(null)));
|
||||||
|
|
||||||
pane.setFitToWidth(true);
|
pane.setFitToWidth(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user