优化 AdvancedListItem (#5460)

This commit is contained in:
Glavo
2026-02-06 22:48:41 +08:00
committed by GitHub
parent 5b11202a9c
commit 570e1e2029
11 changed files with 118 additions and 152 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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