Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ public final class Controllers {
});
private static Lazy<RootPage> rootPage = new Lazy<>(RootPage::new);
private static DecoratorController decorator;
private static Lazy<DownloadPage> downloadPage = new Lazy<>(DownloadPage::new);
private static DownloadPage downloadPage;
private static Lazy<AccountListPage> accountListPage = new Lazy<>(() -> {
AccountListPage accountListPage = new AccountListPage();
accountListPage.selectedAccountProperty().bindBidirectional(Accounts.selectedAccountProperty());
accountListPage.accountsProperty().bindContent(Accounts.getAccounts());
accountListPage.authServersProperty().bindContentBidirectional(config().getAuthlibInjectorServers());
return accountListPage;
});
private static Lazy<LauncherSettingsPage> settingsPage = new Lazy<>(LauncherSettingsPage::new);
private static LauncherSettingsPage settingsPage;
private static Lazy<TerracottaPage> terracottaPage = new Lazy<>(TerracottaPage::new);

private Controllers() {
Expand Down Expand Up @@ -142,7 +142,18 @@ public static RootPage getRootPage() {

// FXThread
public static LauncherSettingsPage getSettingsPage() {
return settingsPage.get();
if (settingsPage == null) {
settingsPage = new LauncherSettingsPage();
}
return settingsPage;
}

@FXThread
public static void prepareSettingsPage() {
if (settingsPage == null) {
LOG.info("Prepare the settings page");
settingsPage = FXUtils.prepareNode(new LauncherSettingsPage());
}
}

// FXThread
Expand All @@ -152,7 +163,18 @@ public static AccountListPage getAccountListPage() {

// FXThread
public static DownloadPage getDownloadPage() {
return downloadPage.get();
if (downloadPage == null) {
downloadPage = new DownloadPage();
}
return downloadPage;
}

@FXThread
public static void prepareDownloadPage() {
if (downloadPage == null) {
LOG.info("Prepare the download page");
downloadPage = FXUtils.prepareNode(new DownloadPage());
}
}

// FXThread
Expand Down Expand Up @@ -533,6 +555,7 @@ public static void shutdown() {
downloadPage = null;
accountListPage = null;
settingsPage = null;
terracottaPage = null;
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type mismatch: terracottaPage is declared as Lazy<TerracottaPage> (line 115), but here it's being assigned null. Either change the field declaration to Lazy<TerracottaPage> terracottaPage (nullable) or remove this line since Lazy instances don't need to be nulled out in shutdown.

Suggested change
terracottaPage = null;

Copilot uses AI. Check for mistakes.
decorator = null;
stage = null;
scene = null;
Expand Down
20 changes: 20 additions & 0 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import javafx.collections.ObservableMap;
import javafx.event.Event;
import javafx.event.EventDispatcher;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
Expand All @@ -54,6 +55,7 @@
import javafx.util.Callback;
import javafx.util.Duration;
import javafx.util.StringConverter;
import org.jackhuang.hmcl.setting.StyleSheets;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.task.CacheFileTask;
import org.jackhuang.hmcl.task.Schedulers;
Expand Down Expand Up @@ -1367,6 +1369,24 @@ public static void onClicked(Node node, Runnable action) {
});
}

public static <N extends Parent> N prepareNode(N node) {
Scene dummyScene = new Scene(node);
StyleSheets.init(dummyScene);
node.applyCss();
node.layout();
return node;
}

public static void prepareOnMouseEnter(Node node, Runnable action) {
node.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<>() {
@Override
public void handle(MouseEvent e) {
node.removeEventFilter(MouseEvent.MOUSE_ENTERED, this);
action.run();
}
});
}

public static <T> void onScroll(Node node, List<T> list,
ToIntFunction<List<T>> finder,
Consumer<T> updater
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ private Tab<?> findNearestAvailableTab(int tabIndex, boolean doSelect) {
}
}

class Tab<T extends Node> {
final class Tab<T extends Node> {
private final StringProperty id = new SimpleStringProperty(this, "id");
private final StringProperty text = new SimpleStringProperty(this, "text");
private final ReadOnlyBooleanWrapper selected = new ReadOnlyBooleanWrapper(this, "selected");
Expand Down
8 changes: 7 additions & 1 deletion HMCL/src/main/java/org/jackhuang/hmcl/ui/main/RootPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.account.AccountAdvancedListItem;
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
Expand Down Expand Up @@ -175,20 +176,25 @@ protected Skin(RootPage control) {
downloadItem.setTitle(i18n("download"));
downloadItem.setOnAction(e -> Controllers.navigate(Controllers.getDownloadPage()));
FXUtils.installFastTooltip(downloadItem, i18n("download.hint"));
if (AnimationUtils.isAnimationEnabled()) {
FXUtils.prepareOnMouseEnter(downloadItem, Controllers::prepareDownloadPage);
}

// fifth item in left sidebar
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
launcherSettingsItem.setLeftGraphic(wrap(SVG.SETTINGS));
launcherSettingsItem.setActionButtonVisible(false);
launcherSettingsItem.setTitle(i18n("settings"));
launcherSettingsItem.setOnAction(e -> Controllers.navigate(Controllers.getSettingsPage()));
if (AnimationUtils.isAnimationEnabled()) {
FXUtils.prepareOnMouseEnter(launcherSettingsItem, Controllers::prepareSettingsPage);
}

// sixth item in left sidebar
AdvancedListItem terracottaItem = new AdvancedListItem();
terracottaItem.setLeftGraphic(wrap(SVG.GRAPH2));
terracottaItem.setActionButtonVisible(false);
terracottaItem.setTitle(i18n("terracotta"));

terracottaItem.setOnAction(e -> {
if (TerracottaMetadata.PROVIDER != null) {
Controllers.navigate(Controllers.getTerracottaPage());
Expand Down
Loading