Skip to content

Commit e323185

Browse files
authored
使用 LineSelectButton 代替 JFXComboxBox (#5337)
1 parent 90a795b commit e323185

25 files changed

Lines changed: 801 additions & 398 deletions

HMCL/src/main/java/com/jfoenix/controls/JFXPopup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public void show(Node node, PopupVPosition vAlign, PopupHPosition hAlign, double
137137

138138
boolean isRTL = node.getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT;
139139

140-
this.show(parent,
140+
this.show(node,
141141
parent.getX() + scene.getX() + origin.getX() + (hAlign == PopupHPosition.RIGHT ? ((Region) node).getWidth() : 0),
142142
parent.getY() + origin.getY() + scene.getY() + (vAlign == PopupVPosition.BOTTOM ? ((Region) node).getHeight() : 0)
143143
);

HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public enum SVG {
123123
TEXTURE("M4.4-3Q3.925-3.1 3.5125-3.5125T3-4.4L19.6-21Q20.125-20.875 20.5-20.4875T21.025-19.6L4.4-3ZM3-9.3V-12.1L11.9-21H14.7L3-9.3ZM3-17V-19Q3-19.825 3.5875-20.4125T5-21H7L3-17ZM17-3 21-7V-5Q21-4.175 20.4125-3.5875T19-3H17ZM9.3-3 21-14.7V-11.9L12.1-3H9.3Z"),
124124
TRIP("M4 21Q3.175 21 2.5875 20.4125T2 19V8Q2 7.175 2.5875 6.5875T4 6H8V4Q8 3.175 8.5875 2.5875T10 2H14Q14.825 2 15.4125 2.5875T16 4V6H20Q20.825 6 21.4125 6.5875T22 8V19Q22 19.825 21.4125 20.4125T20 21H4ZM10 6H14V4H10V6ZM6 8H4V19H6V8ZM16 19V8H8V19H16ZM18 8V19H20V8H18ZM12 13.5Z"),
125125
TUNE("M11 21V15H13V17H21V19H13V21H11ZM3 19V17H9V19H3ZM7 15V13H3V11H7V9H9V15H7ZM11 13V11H21V13H11ZM15 9V3H17V5H21V7H17V9H15ZM3 7V5H13V7H3Z"),
126+
UNFOLD_MORE("M12 21 7.5 16.5l1.45-1.45L12 18.1l3.05-3.05 1.45 1.45L12 21ZM8.95 9.05 7.5 7.6 12 3.1l4.5 4.5-1.45 1.45L12 6 8.95 9.05Z"),
126127
UPDATE("M12 21Q10.125 21 8.4875 20.2875T5.6375 18.3625Q4.425 17.15 3.7125 15.5125T3 12Q3 10.125 3.7125 8.4875T5.6375 5.6375Q6.85 4.425 8.4875 3.7125T12 3Q14.05 3 15.8875 3.875T19 6.35V4H21V10H15V8H17.75Q16.725 6.6 15.225 5.8T12 5Q9.075 5 7.0375 7.0375T5 12Q5 14.925 7.0375 16.9625T12 19Q14.625 19 16.5875 17.3T18.9 13H20.95Q20.575 16.425 18.0125 18.7125T12 21ZM14.8 16.2 11 12.4V7H13V11.6L16.2 14.8 14.8 16.2Z"),
127128
UNDO("M8 19q-.425 0-.712-.288T7 18t.288-.712T8 17h6.1q1.575 0 2.738-1T18 13.5T16.838 11T14.1 10H7.8l1.9 1.9q.275.275.275.7t-.275.7t-.7.275t-.7-.275L4.7 9.7q-.15-.15-.213-.325T4.426 9t.063-.375T4.7 8.3l3.6-3.6q.275-.275.7-.275t.7.275t.275.7t-.275.7L7.8 8h6.3q2.425 0 4.163 1.575T20 13.5t-1.737 3.925T14.1 19z"),
128129
VISIBILITY("M12 16q1.875 0 3.1875-1.3125T16.5 11.5 15.1875 8.3125 12 7 8.8125 8.3125 7.5 11.5t1.3125 3.1875T12 16Zm0-1.8q-1.125 0-1.9125-.7875T9.3 11.5t.7875-1.9125T12 8.8q1.125 0 1.9125.7875T14.7 11.5q0 1.125-.7875 1.9125T12 14.2ZM12 19q-3.65 0-6.65-2.0375T1 11.5Q2.35 8.075 5.35 6.0375T12 4q3.65 0 6.65 2.0375T23 11.5q-1.35 3.425-4.35 5.4625T12 19Zm0-7.5ZM12 17q2.825 0 5.1875-1.4875T20.8 11.5q-1.25-2.525-3.6125-4.0125T12 6 6.8125 7.4875 3.2 11.5q1.25 2.525 3.6125 4.0125T12 17Z"),

HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private static final class Skin extends ControlSkinBase<ComponentList> {
142142
if (node.getProperties().containsKey("ComponentList.vgrow")) {
143143
VBox.setVgrow(cell, (Priority) node.getProperties().get("ComponentList.vgrow"));
144144
}
145-
if (node.getProperties().containsKey("ComponentList.noPadding")) {
145+
if (node instanceof LineButtonBase || node.getProperties().containsKey("ComponentList.noPadding")) {
146146
cell.getStyleClass().add("no-padding");
147147
}
148148
return cell;
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Hello Minecraft! Launcher
3+
* Copyright (C) 2026 huangyuhui <huanghongxun2008@126.com> and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
package org.jackhuang.hmcl.ui.construct;
19+
20+
import javafx.beans.property.SimpleStringProperty;
21+
import javafx.beans.property.StringProperty;
22+
import javafx.beans.property.StringPropertyBase;
23+
import javafx.geometry.Insets;
24+
import javafx.geometry.Pos;
25+
import javafx.scene.control.Label;
26+
import javafx.scene.layout.BorderPane;
27+
import javafx.scene.layout.Region;
28+
import javafx.scene.layout.StackPane;
29+
import javafx.scene.layout.VBox;
30+
31+
/// @author Glavo
32+
public abstract class LineButtonBase extends StackPane {
33+
34+
private static final Insets PADDING = new Insets(8, 8, 8, 16);
35+
36+
protected final BorderPane root;
37+
protected final RipplerContainer container;
38+
39+
private final Label titleLabel;
40+
41+
public LineButtonBase() {
42+
this.root = new BorderPane();
43+
root.setPadding(PADDING);
44+
root.setMinHeight(48);
45+
46+
this.container = new RipplerContainer(root);
47+
this.getChildren().setAll(container);
48+
49+
this.titleLabel = new Label();
50+
root.setCenter(titleLabel);
51+
BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT);
52+
titleLabel.textProperty().bind(titleProperty());
53+
titleLabel.getStyleClass().add("title");
54+
}
55+
56+
private final StringProperty title = new SimpleStringProperty(this, "title");
57+
58+
public StringProperty titleProperty() {
59+
return title;
60+
}
61+
62+
public String getTitle() {
63+
return titleProperty().get();
64+
}
65+
66+
public void setTitle(String title) {
67+
this.titleProperty().set(title);
68+
}
69+
70+
private StringProperty subtitle;
71+
72+
public StringProperty subtitleProperty() {
73+
if (subtitle == null) {
74+
subtitle = new StringPropertyBase() {
75+
private VBox left;
76+
private Label subtitleLabel;
77+
78+
@Override
79+
public String getName() {
80+
return "subtitle";
81+
}
82+
83+
@Override
84+
public Object getBean() {
85+
return LineButtonBase.this;
86+
}
87+
88+
@Override
89+
protected void invalidated() {
90+
String subtitle = get();
91+
if (subtitle != null && !subtitle.isEmpty()) {
92+
if (left == null) {
93+
left = new VBox();
94+
left.setMouseTransparent(true);
95+
left.setAlignment(Pos.CENTER_LEFT);
96+
97+
subtitleLabel = new Label();
98+
subtitleLabel.setWrapText(true);
99+
subtitleLabel.setMinHeight(Region.USE_PREF_SIZE);
100+
subtitleLabel.getStyleClass().add("subtitle");
101+
}
102+
subtitleLabel.setText(subtitle);
103+
left.getChildren().setAll(titleLabel, subtitleLabel);
104+
root.setCenter(left);
105+
} else if (left != null) {
106+
subtitleLabel.setText(null);
107+
root.setCenter(titleLabel);
108+
}
109+
}
110+
};
111+
}
112+
113+
return subtitle;
114+
}
115+
116+
public String getSubtitle() {
117+
return subtitleProperty().get();
118+
}
119+
120+
public void setSubtitle(String subtitle) {
121+
subtitleProperty().set(subtitle);
122+
}
123+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Hello Minecraft! Launcher
3+
* Copyright (C) 2026 huangyuhui <huanghongxun2008@126.com> and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
package org.jackhuang.hmcl.ui.construct;
19+
20+
import javafx.beans.property.ObjectProperty;
21+
import javafx.beans.property.ObjectPropertyBase;
22+
import javafx.beans.property.SimpleStringProperty;
23+
import javafx.beans.property.StringProperty;
24+
import javafx.event.ActionEvent;
25+
import javafx.event.EventHandler;
26+
import javafx.geometry.Insets;
27+
import javafx.geometry.Pos;
28+
import javafx.scene.Node;
29+
import javafx.scene.control.Label;
30+
import javafx.scene.layout.HBox;
31+
import org.jackhuang.hmcl.ui.FXUtils;
32+
import org.jackhuang.hmcl.ui.SVG;
33+
34+
/// @author Glavo
35+
public final class LineNavigationButton extends LineButtonBase {
36+
private static final String DEFAULT_STYLE_CLASS = "line-navigation-button";
37+
38+
public LineNavigationButton() {
39+
getStyleClass().add(DEFAULT_STYLE_CLASS);
40+
41+
root.setMouseTransparent(true);
42+
43+
HBox right = new HBox();
44+
root.setRight(right);
45+
{
46+
right.setAlignment(Pos.CENTER_RIGHT);
47+
48+
Label valueLabel = new Label();
49+
valueLabel.getStyleClass().add("subtitle");
50+
valueLabel.textProperty().bind(messageProperty());
51+
52+
Node arrowIcon = SVG.ARROW_FORWARD.createIcon(24);
53+
HBox.setMargin(arrowIcon, new Insets(0, 8, 0, 8));
54+
55+
disabledProperty().addListener((observable, oldValue, newValue) ->
56+
arrowIcon.setOpacity(newValue ? 0.4 : 1.0));
57+
58+
right.getChildren().setAll(valueLabel, arrowIcon);
59+
}
60+
61+
FXUtils.onClicked(container, this::fire);
62+
}
63+
64+
public void fire() {
65+
fireEvent(new ActionEvent());
66+
}
67+
68+
private final ObjectProperty<EventHandler<ActionEvent>> onAction = new ObjectPropertyBase<>() {
69+
70+
@Override
71+
protected void invalidated() {
72+
setEventHandler(ActionEvent.ACTION, get());
73+
}
74+
75+
@Override
76+
public Object getBean() {
77+
return LineNavigationButton.this;
78+
}
79+
80+
@Override
81+
public String getName() {
82+
return "onAction";
83+
}
84+
};
85+
86+
public ObjectProperty<EventHandler<ActionEvent>> onActionProperty() {
87+
return onAction;
88+
}
89+
90+
public EventHandler<ActionEvent> getOnAction() {
91+
return onActionProperty().get();
92+
}
93+
94+
public void setOnAction(EventHandler<ActionEvent> value) {
95+
onActionProperty().set(value);
96+
}
97+
98+
private final StringProperty message = new SimpleStringProperty(this, "message", "");
99+
100+
public StringProperty messageProperty() {
101+
return message;
102+
}
103+
104+
public String getMessage() {
105+
return messageProperty().get();
106+
}
107+
108+
public void setMessage(String message) {
109+
messageProperty().set(message);
110+
}
111+
112+
}

0 commit comments

Comments
 (0)