Skip to content

Commit 389d430

Browse files
authored
fix #2094 (#2096)
1 parent 8b98932 commit 389d430

1 file changed

Lines changed: 57 additions & 34 deletions

File tree

HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
import com.jfoenix.controls.JFXDialog;
2121
import com.jfoenix.controls.JFXSnackbar;
2222
import javafx.application.Platform;
23-
import javafx.beans.binding.Bindings;
23+
import javafx.beans.InvalidationListener;
24+
import javafx.beans.WeakInvalidationListener;
2425
import javafx.beans.value.ChangeListener;
2526
import javafx.beans.value.ObservableValue;
2627
import javafx.event.EventHandler;
@@ -35,6 +36,7 @@
3536
import org.jackhuang.hmcl.Launcher;
3637
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
3738
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
39+
import org.jackhuang.hmcl.task.Schedulers;
3840
import org.jackhuang.hmcl.ui.Controllers;
3941
import org.jackhuang.hmcl.ui.FXUtils;
4042
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
@@ -55,6 +57,7 @@
5557
import java.util.Locale;
5658
import java.util.Optional;
5759
import java.util.Random;
60+
import java.util.concurrent.CompletableFuture;
5861
import java.util.logging.Level;
5962
import java.util.stream.Stream;
6063

@@ -89,10 +92,23 @@ public DecoratorController(Stage stage, Node mainPage) {
8992
decorator.onBackNavButtonActionProperty().set(e -> back());
9093
decorator.onRefreshNavButtonActionProperty().set(e -> refresh());
9194

92-
setupBackground();
93-
9495
setupAuthlibInjectorDnD();
9596

97+
// Setup background
98+
decorator.setContentBackground(getBackground());
99+
changeBackgroundListener = o -> {
100+
final int currentCount = ++this.changeBackgroundCount;
101+
CompletableFuture.supplyAsync(this::getBackground, Schedulers.io())
102+
.thenAcceptAsync(background -> {
103+
if (this.changeBackgroundCount == currentCount)
104+
decorator.setContentBackground(background);
105+
}, Schedulers.javafx());
106+
};
107+
WeakInvalidationListener weakListener = new WeakInvalidationListener(changeBackgroundListener);
108+
config().backgroundImageTypeProperty().addListener(weakListener);
109+
config().backgroundImageProperty().addListener(weakListener);
110+
config().backgroundImageUrlProperty().addListener(weakListener);
111+
96112
// pass key events to current dialog / current page
97113
decorator.addEventFilter(KeyEvent.ANY, e -> {
98114
if (!(e.getTarget() instanceof Node)) {
@@ -134,37 +150,40 @@ public Decorator getDecorator() {
134150

135151
// ==== Background ====
136152

137-
private void setupBackground() {
138-
decorator.contentBackgroundProperty().bind(
139-
Bindings.createObjectBinding(
140-
() -> {
141-
Image image = null;
142-
if (config().getBackgroundImageType() == EnumBackgroundImage.CUSTOM && config().getBackgroundImage() != null) {
143-
image = tryLoadImage(Paths.get(config().getBackgroundImage()))
144-
.orElse(null);
145-
}
146-
if (config().getBackgroundImageType() == EnumBackgroundImage.NETWORK) {
147-
if (!NetworkUtils.isURL(config().getBackgroundImageUrl())) {
148-
image = loadDefaultBackgroundImage();
149-
} else {
150-
image = new Image(config().getBackgroundImageUrl(), true);
151-
}
152-
} else if (config().getBackgroundImageType() == EnumBackgroundImage.CLASSIC) {
153-
image = newImage("/assets/img/background-classic.jpg");
154-
} else if (config().getBackgroundImageType() == EnumBackgroundImage.TRANSLUCENT) {
155-
return new Background(new BackgroundFill(new Color(1, 1, 1, 0.5), CornerRadii.EMPTY, Insets.EMPTY));
156-
}
157-
if (image == null) {
158-
image = loadDefaultBackgroundImage();
159-
}
160-
return new Background(new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)));
161-
},
162-
config().backgroundImageTypeProperty(),
163-
config().backgroundImageProperty(),
164-
config().backgroundImageUrlProperty()));
153+
//FXThread
154+
private int changeBackgroundCount = 0;
155+
156+
@SuppressWarnings("FieldCanBeLocal") // Strong reference
157+
private final InvalidationListener changeBackgroundListener;
158+
159+
private Background getBackground() {
160+
EnumBackgroundImage imageType = config().getBackgroundImageType();
161+
162+
Image image = null;
163+
switch (imageType) {
164+
case CUSTOM:
165+
String backgroundImage = config().getBackgroundImage();
166+
if (backgroundImage != null)
167+
image = tryLoadImage(Paths.get(backgroundImage)).orElse(null);
168+
break;
169+
case NETWORK:
170+
String backgroundImageUrl = config().getBackgroundImageUrl();
171+
if (backgroundImageUrl != null && NetworkUtils.isURL(backgroundImageUrl))
172+
image = tryLoadImage(backgroundImageUrl).orElse(null);
173+
break;
174+
case CLASSIC:
175+
image = newImage("/assets/img/background-classic.jpg");
176+
break;
177+
case TRANSLUCENT:
178+
return new Background(new BackgroundFill(new Color(1, 1, 1, 0.5), CornerRadii.EMPTY, Insets.EMPTY));
179+
}
180+
if (image == null) {
181+
image = loadDefaultBackgroundImage();
182+
}
183+
return new Background(new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)));
165184
}
166185

167-
private Image defaultBackground;
186+
private volatile Image defaultBackground;
168187

169188
/**
170189
* Load background image from bg/, background.png, background.jpg, background.gif
@@ -196,7 +215,7 @@ private Optional<Image> randomImageIn(Path imageDir) {
196215
List<Path> candidates;
197216
try (Stream<Path> stream = Files.list(imageDir)) {
198217
candidates = stream
199-
.filter(Files::isReadable)
218+
.filter(Files::isReadable)
200219
.filter(it -> {
201220
String ext = getExtension(it).toLowerCase(Locale.ROOT);
202221
return ext.equals("png") || ext.equals("jpg") || ext.equals("gif");
@@ -224,9 +243,13 @@ private Optional<Image> tryLoadImage(Path path) {
224243
if (!Files.isReadable(path))
225244
return Optional.empty();
226245

246+
return tryLoadImage(path.toAbsolutePath().toUri().toString());
247+
}
248+
249+
private Optional<Image> tryLoadImage(String url) {
227250
Image img;
228251
try {
229-
img = new Image(path.toAbsolutePath().toUri().toString());
252+
img = new Image(url);
230253
} catch (IllegalArgumentException e) {
231254
LOG.log(WARNING, "Couldn't load background image", e);
232255
return Optional.empty();

0 commit comments

Comments
 (0)