Try to fix #462.

This commit is contained in:
huanghongxun 2018-10-05 22:27:19 +08:00
parent 1b1f22b9fa
commit 6b3152c4b5
6 changed files with 65 additions and 99 deletions

View File

@ -19,10 +19,8 @@ package org.jackhuang.hmcl.setting;
import com.jfoenix.concurrency.JFXUtilities;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.event.EventBus;
@ -30,9 +28,11 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
import static javafx.collections.FXCollections.observableArrayList;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
@ -43,8 +43,6 @@ public final class Profiles {
public static final String DEFAULT_PROFILE = "Default";
public static final String HOME_PROFILE = "Home";
private static InvalidationListener listener = o -> loadVersion();
private Profiles() {
}
@ -65,16 +63,14 @@ public final class Profiles {
private static ObjectProperty<Profile> selectedProfile = new SimpleObjectProperty<Profile>() {
{
profiles.addListener(onInvalidating(this::invalidated));
this.addListener(this::change);
}
@Override
protected void invalidated() {
Profile profile = get();
if (!initialized)
return;
if (get() != null)
get().removeListener(listener);
Profile profile = get();
if (profiles.isEmpty()) {
if (profile != null) {
@ -88,18 +84,20 @@ public final class Profiles {
}
}
if (!initialized)
return;
config().setSelectedProfile(profile == null ? "" : profile.getName());
loadVersion();
}
private void change(ObservableValue<? extends Profile> observableValue, Profile oldProfile, Profile newProfile) {
if (oldProfile != null)
oldProfile.selectedVersionProperty().removeListener(listener);
if (newProfile != null)
newProfile.selectedVersionProperty().addListener(listener);
if (profile != null) {
if (profile.getRepository().isLoaded())
selectedVersion.bind(profile.selectedVersionProperty());
else {
selectedVersion.unbind();
selectedVersion.set(null);
// bind when repository was reloaded.
profile.getRepository().refreshVersionsAsync().start();
}
} else {
selectedVersion.unbind();
selectedVersion.set(null);
}
}
};
@ -154,19 +152,23 @@ public final class Profiles {
// Platform.runLater is necessary or profiles will be empty
// since checkProfiles adds 2 base profile later.
Platform.runLater(() -> {
initialized = true;
selectedProfile.set(
profiles.stream()
.filter(it -> it.getName().equals(config().getSelectedProfile()))
.findFirst()
.orElse(profiles.get(0)));
initialized = true;
});
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> {
JFXUtilities.runInFX(() -> {
if (selectedProfile.get() != null && selectedProfile.get().getRepository() == event.getSource())
loadVersion();
Profile profile = selectedProfile.get();
if (profile != null && profile.getRepository() == event.getSource()) {
selectedVersion.bind(profile.selectedVersionProperty());
for (Consumer<Profile> listener : versionsListeners)
listener.accept(profile);
}
});
});
}
@ -197,14 +199,17 @@ public final class Profiles {
return selectedVersion.getReadOnlyProperty();
}
// Guaranteed that the repository is loaded.
public static String getSelectedVersion() {
return selectedVersion.get();
}
private static void loadVersion() {
Profile profile = selectedProfile.get();
if (profile == null || !profile.getRepository().isLoaded()) return;
JFXUtilities.runInFX(() ->
selectedVersion.set(profile.getSelectedVersion()));
private static final List<Consumer<Profile>> versionsListeners = new LinkedList<>();
public static void registerVersionsListener(Consumer<Profile> listener) {
Profile profile = getSelectedProfile();
if (profile != null && profile.getRepository().isLoaded())
listener.accept(profile);
versionsListeners.add(listener);
}
}

View File

@ -90,13 +90,13 @@ public final class FXUtils {
}
public static <T> void onChangeAndOperate(ObservableValue<T> value, Consumer<T> consumer) {
onChange(value, consumer);
consumer.accept(value.getValue());
onChange(value, consumer);
}
public static <T> void onWeakChangeAndOperate(ObservableValue<T> value, Consumer<T> consumer) {
onWeakChange(value, consumer);
consumer.accept(value.getValue());
onWeakChange(value, consumer);
}
public static void runLaterIf(BooleanSupplier condition, Runnable runnable) {

View File

@ -33,8 +33,6 @@ import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.game.HMCLGameRepository;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
@ -81,7 +79,6 @@ public final class MainPage extends StackPane implements DecoratorPage {
@FXML
private Rectangle separator;
private Profile profile;
{
FXUtils.loadFXML(this, "/assets/fxml/main.fxml");
@ -126,41 +123,30 @@ public final class MainPage extends StackPane implements DecoratorPage {
}
});
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(event -> {
if (event.getSource() == profile.getRepository())
loadVersions((HMCLGameRepository) event.getSource());
});
Profiles.selectedProfileProperty().addListener((a, b, newValue) -> profile = newValue);
profile = Profiles.getSelectedProfile();
if (profile != null) {
if (profile.getRepository().isLoaded())
loadVersions(profile.getRepository());
else
profile.getRepository().refreshVersionsAsync().start();
}
Profiles.registerVersionsListener(this::loadVersions);
}
private void loadVersions(HMCLGameRepository repository) {
private void loadVersions(Profile profile) {
HMCLGameRepository repository = profile.getRepository();
List<Node> children = repository.getVersions().parallelStream()
.filter(version -> !version.isHidden())
.sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId())))
.map(version -> {
StackPane pane = new StackPane();
GameItem item = new GameItem(repository.getProfile(), version.getId());
GameItem item = new GameItem(profile, version.getId());
pane.getChildren().setAll(item);
pane.getStyleClass().setAll("menu-container");
item.setMouseTransparent(true);
RipplerContainer container = new RipplerContainer(pane);
container.setOnMouseClicked(e -> {
repository.getProfile().setSelectedVersion(version.getId());
profile.setSelectedVersion(version.getId());
popup.hide();
});
return container;
})
.collect(Collectors.toList());
JFXUtilities.runInFX(() -> {
if (profile == repository.getProfile())
if (profile == Profiles.getSelectedProfile())
menu.getContent().setAll(children);
});
}

View File

@ -24,6 +24,7 @@ import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
@ -78,7 +79,6 @@ class ComponentListCell extends StackPane {
content.getStyleClass().add("options-sublist");
BorderPane groupNode = new BorderPane();
groupNode.getStyleClass().add("options-list-item-header");
Node expandIcon = SVG.expand(Theme.blackFillBinding(), 10, 10);
JFXButton expandButton = new JFXButton();
@ -86,6 +86,7 @@ class ComponentListCell extends StackPane {
expandButton.getStyleClass().add("options-list-item-expand-button");
VBox labelVBox = new VBox();
labelVBox.setAlignment(Pos.CENTER_LEFT);
if (list instanceof ComponentSublist) {
Node leftNode = ((ComponentSublist) list).getHeaderLeft();
@ -94,13 +95,11 @@ class ComponentListCell extends StackPane {
} else {
Label label = new Label();
label.textProperty().bind(list.titleProperty());
label.setMouseTransparent(true);
labelVBox.getChildren().add(label);
if (list.isHasSubtitle()) {
Label subtitleLabel = new Label();
subtitleLabel.textProperty().bind(list.subtitleProperty());
subtitleLabel.setMouseTransparent(true);
subtitleLabel.getStyleClass().add("subtitle-label");
labelVBox.getChildren().add(subtitleLabel);
}
@ -109,6 +108,7 @@ class ComponentListCell extends StackPane {
groupNode.setLeft(labelVBox);
HBox right = new HBox();
right.setAlignment(Pos.CENTER_RIGHT);
if (list instanceof ComponentSublist) {
Node rightNode = ((ComponentSublist) list).getHeaderRight();
if (rightNode != null)
@ -116,18 +116,13 @@ class ComponentListCell extends StackPane {
}
right.getChildren().add(expandButton);
groupNode.setRight(right);
labelVBox.setAlignment(Pos.CENTER_LEFT);
right.setAlignment(Pos.CENTER_RIGHT);
VBox container = new VBox();
container.setStyle("-fx-padding: 8 0 0 0;");
container.setPadding(new Insets(8, 0, 0, 0));
FXUtils.setLimitHeight(container, 0);
FXUtils.setOverflowHidden(container, true);
container.getChildren().setAll(content);
VBox holder = new VBox();
holder.getChildren().setAll(groupNode, container);
holder.getStyleClass().add("options-list-item-container");
groupNode.setBottom(container);
expandButton.setOnMouseClicked(e -> {
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
@ -159,7 +154,7 @@ class ComponentListCell extends StackPane {
expandedProperty().addListener((a, b, newValue) ->
expandIcon.setRotate(newValue ? 180 : 0));
getChildren().setAll(holder);
getChildren().setAll(groupNode);
} else
getChildren().setAll(content);
}

View File

@ -17,39 +17,28 @@
*/
package org.jackhuang.hmcl.ui.versions;
import com.jfoenix.concurrency.JFXUtilities;
import javafx.beans.InvalidationListener;
import javafx.scene.image.Image;
import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.WeakListenerHolder;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import java.io.File;
import java.util.Objects;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class GameAdvancedListItem extends AdvancedListItem {
public GameAdvancedListItem() {
FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), version -> {
FXUtils.runLaterIf(() -> !Objects.nonNull(Profiles.getSelectedProfile()), () -> {
imageProperty().set(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version));
if (version != null) {
setTitle(version);
setSubtitle(null);
} else {
setTitle(i18n("version.empty"));
setSubtitle(i18n("version.empty.add"));
}
});
if (version != null) {
setTitle(version);
setSubtitle(null);
setImage(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version));
} else {
setTitle(i18n("version.empty"));
setSubtitle(i18n("version.empty.add"));
setImage(new Image("/assets/img/grass.png"));
}
});
setRightGraphic(SVG.gear(Theme.blackFillBinding(), -1, -1));

View File

@ -47,28 +47,19 @@ public class GameList extends Control implements DecoratorPage {
private final BooleanProperty loading = new SimpleBooleanProperty(true);
private final ListProperty<GameListItem> items = new SimpleListProperty<>(FXCollections.observableArrayList());
private Profile profile;
private ToggleGroup toggleGroup;
public GameList() {
EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(event -> {
if (event.getSource() == profile.getRepository())
loadVersions((HMCLGameRepository) event.getSource());
});
EventBus.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(event -> {
if (event.getSource() == profile.getRepository())
if (event.getSource() == Profiles.getSelectedProfile().getRepository())
JFXUtilities.runInFX(() -> loading.set(true));
});
Profiles.selectedProfileProperty().addListener((a, b, newValue) -> profile = newValue);
profile = Profiles.getSelectedProfile();
if (profile.getRepository().isLoaded())
loadVersions(profile.getRepository());
else
profile.getRepository().refreshVersionsAsync().start();
Profiles.registerVersionsListener(this::loadVersions);
}
private void loadVersions(HMCLGameRepository repository) {
private void loadVersions(Profile profile) {
HMCLGameRepository repository = profile.getRepository();
toggleGroup = new ToggleGroup();
WeakListenerHolder listenerHolder = new WeakListenerHolder();
toggleGroup.getProperties().put("ReferenceHolder", listenerHolder);
@ -78,7 +69,7 @@ public class GameList extends Control implements DecoratorPage {
.map(version -> new GameListItem(toggleGroup, profile, version.getId()))
.collect(Collectors.toList());
JFXUtilities.runInFX(() -> {
if (profile == repository.getProfile()) {
if (profile == Profiles.getSelectedProfile()) {
loading.set(false);
items.setAll(children);
children.forEach(GameListItem::checkSelection);
@ -115,11 +106,11 @@ public class GameList extends Control implements DecoratorPage {
}
public void refresh() {
profile.getRepository().refreshVersionsAsync().start();
Profiles.getSelectedProfile().getRepository().refreshVersionsAsync().start();
}
public void modifyGlobalGameSettings() {
Versions.modifyGlobalSettings(profile);
Versions.modifyGlobalSettings(Profiles.getSelectedProfile());
}
@Override