Skip to content

Commit e38eb85

Browse files
committed
重构 JavaManagementPage 以使用 ListCell 展示元素
1 parent ea407be commit e38eb85

1 file changed

Lines changed: 117 additions & 92 deletions

File tree

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

Lines changed: 117 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@
1818
package org.jackhuang.hmcl.ui.main;
1919

2020
import com.jfoenix.controls.JFXButton;
21+
import com.jfoenix.controls.JFXListView;
2122
import javafx.beans.binding.Bindings;
2223
import javafx.beans.value.ChangeListener;
2324
import javafx.collections.FXCollections;
2425
import javafx.geometry.Insets;
2526
import javafx.geometry.Pos;
2627
import javafx.scene.Node;
27-
import javafx.scene.control.Control;
28+
import javafx.scene.control.ListCell;
2829
import javafx.scene.control.Skin;
29-
import javafx.scene.control.SkinBase;
30+
import javafx.scene.control.Tooltip;
3031
import javafx.scene.layout.BorderPane;
3132
import javafx.scene.layout.HBox;
33+
import javafx.scene.layout.StackPane;
3234
import javafx.stage.FileChooser;
3335
import org.jackhuang.hmcl.java.JavaInfo;
3436
import org.jackhuang.hmcl.java.JavaManager;
@@ -42,6 +44,7 @@
4244
import org.jackhuang.hmcl.ui.construct.RipplerContainer;
4345
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
4446
import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider;
47+
import org.jackhuang.hmcl.util.FXThread;
4548
import org.jackhuang.hmcl.util.Pair;
4649
import org.jackhuang.hmcl.util.TaskCancellationAction;
4750
import org.jackhuang.hmcl.util.io.FileUtils;
@@ -62,7 +65,7 @@
6265
/**
6366
* @author Glavo
6467
*/
65-
public final class JavaManagementPage extends ListPageBase<JavaManagementPage.JavaItem> {
68+
public final class JavaManagementPage extends ListPageBase<JavaRuntime> {
6669

6770
@SuppressWarnings("FieldCanBeLocal")
6871
private final ChangeListener<Collection<JavaRuntime>> listener;
@@ -172,117 +175,95 @@ private void onInstallArchive(Path file) {
172175
}).start();
173176
}
174177

175-
// FXThread
178+
@FXThread
176179
private void loadJava(Collection<JavaRuntime> javaRuntimes) {
177180
if (javaRuntimes != null) {
178-
List<JavaItem> items = new ArrayList<>();
179-
for (JavaRuntime java : javaRuntimes) {
180-
items.add(new JavaItem(java));
181-
}
182-
this.setItems(FXCollections.observableList(items));
181+
this.setItems(FXCollections.observableArrayList(javaRuntimes));
183182
this.setLoading(false);
184-
} else
183+
} else {
184+
this.setItems(FXCollections.emptyObservableList());
185185
this.setLoading(true);
186+
}
186187
}
187188

188-
static final class JavaItem extends Control {
189-
private final JavaRuntime java;
189+
private static final class JavaPageSkin extends ToolbarListPageSkin<JavaRuntime, JavaManagementPage> {
190190

191-
public JavaItem(JavaRuntime java) {
192-
this.java = java;
191+
JavaPageSkin(JavaManagementPage skinnable) {
192+
super(skinnable);
193193
}
194194

195-
public JavaRuntime getJava() {
196-
return java;
197-
}
195+
@Override
196+
protected List<Node> initializeToolbar(JavaManagementPage skinnable) {
197+
ArrayList<Node> res = new ArrayList<>(4);
198198

199-
public void onReveal() {
200-
Path target;
201-
Path parent = java.getBinary().getParent();
202-
if (parent != null
203-
&& parent.getParent() != null
204-
&& parent.getFileName() != null
205-
&& parent.getFileName().toString().equals("bin")
206-
&& Files.exists(parent.getParent().resolve("release"))) {
207-
target = parent.getParent();
208-
} else {
209-
target = java.getBinary();
199+
res.add(createToolbarButton2(i18n("button.refresh"), SVG.REFRESH, JavaManager::refresh));
200+
if (skinnable.onInstallJava != null) {
201+
res.add(createToolbarButton2(i18n("java.download"), SVG.DOWNLOAD, skinnable.onInstallJava));
210202
}
203+
res.add(createToolbarButton2(i18n("java.add"), SVG.ADD, skinnable::onAddJava));
211204

212-
FXUtils.showFileInExplorer(target);
213-
}
205+
JFXButton disableJava = createToolbarButton2(i18n("java.disabled.management"), SVG.FORMAT_LIST_BULLETED, skinnable::onShowRestoreJavaPage);
206+
disableJava.disableProperty().bind(Bindings.isEmpty(ConfigHolder.globalConfig().getDisabledJava()));
207+
res.add(disableJava);
214208

215-
public void onRemove() {
216-
if (java.isManaged()) {
217-
Controllers.taskDialog(JavaManager.getUninstallJavaTask(java), i18n("java.uninstall"), TaskCancellationAction.NORMAL);
218-
} else {
219-
String path = java.getBinary().toString();
220-
ConfigHolder.globalConfig().getUserJava().remove(path);
221-
ConfigHolder.globalConfig().getDisabledJava().add(path);
222-
try {
223-
JavaManager.removeJava(java);
224-
} catch (InterruptedException ignored) {
225-
}
226-
}
209+
return res;
227210
}
228211

229212
@Override
230-
protected Skin<?> createDefaultSkin() {
231-
return new JavaRuntimeItemSkin(this);
213+
protected ListCell<JavaRuntime> createListCell(JFXListView<JavaRuntime> listView) {
214+
return new JavaItemCell();
232215
}
233-
234216
}
235217

236-
private static final class JavaRuntimeItemSkin extends SkinBase<JavaItem> {
218+
private static final class JavaItemCell extends ListCell<JavaRuntime> {
219+
private final Node graphic;
220+
private final TwoLineListItem content;
237221

238-
JavaRuntimeItemSkin(JavaItem control) {
239-
super(control);
240-
JavaRuntime java = control.getJava();
241-
String vendor = JavaInfo.normalizeVendor(java.getVendor());
222+
private SVG removeIcon;
223+
private final StackPane removeIconPane;
224+
private final Tooltip removeTooltip = new Tooltip();
242225

226+
JavaItemCell() {
243227
BorderPane root = new BorderPane();
244228

245229
HBox center = new HBox();
246230
center.setMouseTransparent(true);
247231
center.setSpacing(8);
248232
center.setAlignment(Pos.CENTER_LEFT);
249233

250-
TwoLineListItem item = new TwoLineListItem();
251-
item.setTitle((java.isJDK() ? "JDK" : "JRE") + " " + java.getVersion());
252-
item.setSubtitle(java.getBinary().toString());
253-
item.addTag(i18n("java.info.architecture") + ": " + java.getArchitecture().getDisplayName());
254-
if (vendor != null)
255-
item.addTag(i18n("java.info.vendor") + ": " + vendor);
256-
BorderPane.setAlignment(item, Pos.CENTER);
257-
center.getChildren().setAll(item);
234+
this.content = new TwoLineListItem();
235+
236+
BorderPane.setAlignment(content, Pos.CENTER);
237+
center.getChildren().setAll(content);
258238
root.setCenter(center);
259239

260240
HBox right = new HBox();
261241
right.setAlignment(Pos.CENTER_RIGHT);
262242
{
263243
JFXButton revealButton = new JFXButton();
264-
revealButton.getStyleClass().add("toggle-icon4");
265244
revealButton.setGraphic(FXUtils.limitingSize(SVG.FOLDER_OPEN.createIcon(24), 24, 24));
266-
revealButton.setOnAction(e -> control.onReveal());
245+
revealButton.getStyleClass().add("toggle-icon4");
246+
revealButton.setOnAction(e -> {
247+
JavaRuntime java = getItem();
248+
if (java != null)
249+
onReveal(java);
250+
});
267251
FXUtils.installFastTooltip(revealButton, i18n("reveal.in_file_manager"));
268252

269253
JFXButton removeButton = new JFXButton();
270254
removeButton.getStyleClass().add("toggle-icon4");
271-
removeButton.setOnAction(e -> Controllers.confirm(
272-
java.isManaged() ? i18n("java.uninstall.confirm") : i18n("java.disable.confirm"),
273-
i18n("message.warning"),
274-
control::onRemove,
275-
null
276-
));
277-
if (java.isManaged()) {
278-
removeButton.setGraphic(FXUtils.limitingSize(SVG.DELETE_FOREVER.createIcon(24), 24, 24));
279-
FXUtils.installFastTooltip(removeButton, i18n("java.uninstall"));
280-
if (JavaRuntime.CURRENT_JAVA != null && java.getBinary().equals(JavaRuntime.CURRENT_JAVA.getBinary()))
281-
removeButton.setDisable(true);
282-
} else {
283-
removeButton.setGraphic(FXUtils.limitingSize(SVG.DELETE.createIcon(24), 24, 24));
284-
FXUtils.installFastTooltip(removeButton, i18n("java.disable"));
285-
}
255+
removeButton.setOnAction(e -> {
256+
JavaRuntime java = getItem();
257+
if (java != null)
258+
onRemove(java);
259+
});
260+
FXUtils.installFastTooltip(removeButton, removeTooltip);
261+
262+
this.removeIconPane = new StackPane();
263+
removeIconPane.setAlignment(Pos.CENTER);
264+
FXUtils.setLimitWidth(removeIconPane, 24);
265+
FXUtils.setLimitHeight(removeIconPane, 24);
266+
removeButton.setGraphic(removeIconPane);
286267

287268
right.getChildren().setAll(revealButton, removeButton);
288269
}
@@ -291,31 +272,75 @@ private static final class JavaRuntimeItemSkin extends SkinBase<JavaItem> {
291272
root.getStyleClass().add("md-list-cell");
292273
root.setPadding(new Insets(8));
293274

294-
getChildren().setAll(new RipplerContainer(root));
275+
this.graphic = new RipplerContainer(root);
295276
}
296-
}
297277

298-
private static final class JavaPageSkin extends ToolbarListPageSkin<JavaItem, JavaManagementPage> {
278+
@Override
279+
protected void updateItem(JavaRuntime item, boolean empty) {
280+
super.updateItem(item, empty);
281+
if (empty || item == null) {
282+
setGraphic(null);
283+
} else {
284+
content.setTitle((item.isJDK() ? "JDK" : "JRE") + " " + item.getVersion());
285+
content.setSubtitle(item.getBinary().toString());
286+
287+
content.getTags().clear();
288+
content.addTag(i18n("java.info.architecture") + ": " + item.getArchitecture().getDisplayName());
289+
String vendor = JavaInfo.normalizeVendor(item.getVendor());
290+
if (vendor != null)
291+
content.addTag(i18n("java.info.vendor") + ": " + vendor);
292+
293+
SVG newRemoveIcon = item.isManaged() ? SVG.DELETE_FOREVER : SVG.DELETE;
294+
if (removeIcon != newRemoveIcon) {
295+
removeIcon = newRemoveIcon;
296+
removeIconPane.getChildren().setAll(removeIcon.createIcon(24));
297+
removeTooltip.setText(item.isManaged() ? i18n("java.uninstall") : i18n("java.disable"));
298+
}
299299

300-
JavaPageSkin(JavaManagementPage skinnable) {
301-
super(skinnable);
300+
setGraphic(graphic);
301+
}
302302
}
303303

304-
@Override
305-
protected List<Node> initializeToolbar(JavaManagementPage skinnable) {
306-
ArrayList<Node> res = new ArrayList<>(4);
307-
308-
res.add(createToolbarButton2(i18n("button.refresh"), SVG.REFRESH, JavaManager::refresh));
309-
if (skinnable.onInstallJava != null) {
310-
res.add(createToolbarButton2(i18n("java.download"), SVG.DOWNLOAD, skinnable.onInstallJava));
304+
private void onReveal(JavaRuntime java) {
305+
Path target;
306+
Path parent = java.getBinary().getParent();
307+
if (parent != null
308+
&& parent.getParent() != null
309+
&& parent.getFileName() != null
310+
&& parent.getFileName().toString().equals("bin")
311+
&& Files.exists(parent.getParent().resolve("release"))) {
312+
target = parent.getParent();
313+
} else {
314+
target = java.getBinary();
311315
}
312-
res.add(createToolbarButton2(i18n("java.add"), SVG.ADD, skinnable::onAddJava));
313316

314-
JFXButton disableJava = createToolbarButton2(i18n("java.disabled.management"), SVG.FORMAT_LIST_BULLETED, skinnable::onShowRestoreJavaPage);
315-
disableJava.disableProperty().bind(Bindings.isEmpty(ConfigHolder.globalConfig().getDisabledJava()));
316-
res.add(disableJava);
317+
FXUtils.showFileInExplorer(target);
318+
}
317319

318-
return res;
320+
private void onRemove(JavaRuntime java) {
321+
if (java.isManaged()) {
322+
Controllers.confirm(
323+
i18n("java.uninstall.confirm"),
324+
i18n("message.warning"),
325+
() -> Controllers.taskDialog(JavaManager.getUninstallJavaTask(java), i18n("java.uninstall"), TaskCancellationAction.NORMAL),
326+
null
327+
);
328+
} else {
329+
Controllers.confirm(
330+
i18n("java.disable.confirm"),
331+
i18n("message.warning"),
332+
() -> {
333+
String path = java.getBinary().toString();
334+
ConfigHolder.globalConfig().getUserJava().remove(path);
335+
ConfigHolder.globalConfig().getDisabledJava().add(path);
336+
try {
337+
JavaManager.removeJava(java);
338+
} catch (InterruptedException ignored) {
339+
}
340+
},
341+
null
342+
);
343+
}
319344
}
320345
}
321346
}

0 commit comments

Comments
 (0)