diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java index 4bbf5f1d5b..d56b21a058 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java @@ -20,16 +20,18 @@ import com.jfoenix.controls.JFXPopup; import javafx.beans.InvalidationListener; import javafx.beans.binding.Bindings; -import javafx.beans.property.*; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.css.PseudoClass; import javafx.geometry.Pos; import javafx.scene.control.Label; -import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; -import javafx.scene.input.ScrollEvent; -import javafx.scene.layout.*; +import javafx.scene.input.*; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.util.javafx.MappedObservableList; @@ -51,6 +53,8 @@ public final class LineSelectButton extends LineButton { public LineSelectButton() { this.getStyleClass().add(DEFAULT_STYLE_CLASS); + this.addEventHandler(KeyEvent.KEY_PRESSED, this::handleKeyEvent); + InvalidationListener updateTrailingText = observable -> { T value = getValue(); if (value != null) { @@ -81,6 +85,8 @@ public void fire() { PopupMenu popupMenu = new PopupMenu(); this.popup = new JFXPopup(popupMenu); + popupMenu.addEventHandler(KeyEvent.KEY_PRESSED, this::handleKeyEvent); + ripplerContainer.addEventFilter(ScrollEvent.ANY, ignored -> popup.hide()); Bindings.bindContent(popupMenu.getContent(), MappedObservableList.create(itemsProperty(), item -> { @@ -213,4 +219,32 @@ public ObservableList getItems() { return items.get(); } + private void handleKeyEvent(KeyEvent event) { + ObservableList list = getItems(); + if (list == null || list.isEmpty()) return; + int index = list.indexOf(getValue()); + + var code = event.getCode(); + + if (code == KeyCode.UP) { + if (index > 0) { + setValue(list.get(index - 1)); + } else { + setValue(list.get(list.size() - 1)); + } + event.consume(); + } else if (code == KeyCode.DOWN) { + if (index < list.size() - 1) { + setValue(list.get(index + 1)); + } else { + setValue(list.get(0)); + } + event.consume(); + } else if (code == KeyCode.ENTER || code == KeyCode.ESCAPE) { + if (popup != null && popup.isShowing()) { + popup.hide(); + event.consume(); + } + } + } }