支持在“实例管理”按钮上通过滚动滚轮切换游戏实例 (#4509)

This commit is contained in:
Glavo 2025-09-20 20:15:11 +08:00 committed by GitHub
parent dd7703c7a9
commit 867a04dfba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 39 deletions

View File

@ -93,10 +93,7 @@ import java.nio.file.PathMatcher;
import java.util.List; import java.util.List;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier; import java.util.function.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -1370,6 +1367,27 @@ public final class FXUtils {
}); });
} }
public static <T> void onScroll(Node node, List<T> list,
ToIntFunction<List<T>> finder,
Consumer<T> updater
) {
node.addEventHandler(ScrollEvent.SCROLL, event -> {
double deltaY = event.getDeltaY();
if (deltaY == 0)
return;
int index = finder.applyAsInt(list);
if (index < 0) return;
if (deltaY > 0) // up
index--;
else // down
index++;
updater.accept(list.get((index + list.size()) % list.size()));
event.consume();
});
}
public static void copyOnDoubleClick(Labeled label) { public static void copyOnDoubleClick(Labeled label) {
label.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> { label.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2) { if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2) {

View File

@ -21,7 +21,6 @@ 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.collections.ObservableList;
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;
@ -77,25 +76,9 @@ public class AccountAdvancedListItem extends AdvancedListItem {
setActionButtonVisible(false); setActionButtonVisible(false);
setOnScroll(event -> { FXUtils.onScroll(this, Accounts.getAccounts(),
double deltaY = event.getDeltaY(); accounts -> accounts.indexOf(account.get()),
if (deltaY == 0) Accounts::setSelectedAccount);
return;
Account current = account.get();
if (current == null) return;
ObservableList<Account> accounts = Accounts.getAccounts();
int currentIndex = accounts.indexOf(current);
if (currentIndex < 0) return;
if (deltaY > 0) // up
currentIndex--;
else // down
currentIndex++;
Accounts.setSelectedAccount(accounts.get((currentIndex + accounts.size()) % accounts.size()));
});
} }
public ObjectProperty<Account> accountProperty() { public ObjectProperty<Account> accountProperty() {

View File

@ -208,20 +208,11 @@ public final class MainPage extends StackPane implements DecoratorPage {
launchPane.getStyleClass().add("launch-pane"); launchPane.getStyleClass().add("launch-pane");
launchPane.setMaxWidth(230); launchPane.setMaxWidth(230);
launchPane.setMaxHeight(55); launchPane.setMaxHeight(55);
launchPane.setOnScroll(event -> { FXUtils.onScroll(launchPane, versions, list -> {
double deltaY = event.getDeltaY();
if (deltaY == 0)
return;
String currentId = getCurrentGame(); String currentId = getCurrentGame();
int index = Lang.indexWhere(versions, instance -> instance.getId().equals(currentId)); return Lang.indexWhere(list, instance -> instance.getId().equals(currentId));
if (index < 0) return; }, it -> profile.setSelectedVersion(it.getId()));
if (deltaY > 0) // up
index--;
else // down
index++;
profile.setSelectedVersion(versions.get((index + versions.size()) % versions.size()).getId());
});
StackPane.setAlignment(launchPane, Pos.BOTTOM_RIGHT); StackPane.setAlignment(launchPane, Pos.BOTTOM_RIGHT);
{ {
JFXButton launchButton = new JFXButton(); JFXButton launchButton = new JFXButton();
@ -435,6 +426,10 @@ public final class MainPage extends StackPane implements DecoratorPage {
return state; return state;
} }
public Profile getProfile() {
return profile;
}
public String getCurrentGame() { public String getCurrentGame() {
return currentGame.get(); return currentGame.get();
} }
@ -447,6 +442,10 @@ public final class MainPage extends StackPane implements DecoratorPage {
this.currentGame.set(currentGame); this.currentGame.set(currentGame);
} }
public ObservableList<Version> getVersions() {
return versions;
}
public boolean isShowUpdate() { public boolean isShowUpdate() {
return showUpdate.get(); return showUpdate.get();
} }

View File

@ -154,6 +154,10 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
Versions.modifyGameSettings(profile, version); Versions.modifyGameSettings(profile, version);
} }
}); });
FXUtils.onScroll(gameListItem, getSkinnable().getMainPage().getVersions(), list -> {
String currentId = getSkinnable().getMainPage().getCurrentGame();
return Lang.indexWhere(list, instance -> instance.getId().equals(currentId));
}, it -> getSkinnable().getMainPage().getProfile().setSelectedVersion(it.getId()));
// third item in left sidebar // third item in left sidebar
AdvancedListItem gameItem = new AdvancedListItem(); AdvancedListItem gameItem = new AdvancedListItem();
@ -194,8 +198,7 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
.add(downloadItem) .add(downloadItem)
.startCategory(i18n("settings.launcher.general").toUpperCase(Locale.ROOT)) .startCategory(i18n("settings.launcher.general").toUpperCase(Locale.ROOT))
.add(launcherSettingsItem) .add(launcherSettingsItem)
.add(chatItem) .add(chatItem);
;
// the root page, with the sidebar in left, navigator in center. // the root page, with the sidebar in left, navigator in center.
setLeft(sideBar); setLeft(sideBar);