@@ -20,7 +20,8 @@ package org.jackhuang.hmcl.ui.decorator;
|
|||||||
import com.jfoenix.controls.JFXDialog;
|
import com.jfoenix.controls.JFXDialog;
|
||||||
import com.jfoenix.controls.JFXSnackbar;
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.InvalidationListener;
|
||||||
|
import javafx.beans.WeakInvalidationListener;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
@@ -35,6 +36,7 @@ import javafx.stage.Stage;
|
|||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
|
||||||
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
|
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
|
||||||
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
|
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
|
||||||
@@ -55,6 +57,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -89,10 +92,23 @@ public class DecoratorController {
|
|||||||
decorator.onBackNavButtonActionProperty().set(e -> back());
|
decorator.onBackNavButtonActionProperty().set(e -> back());
|
||||||
decorator.onRefreshNavButtonActionProperty().set(e -> refresh());
|
decorator.onRefreshNavButtonActionProperty().set(e -> refresh());
|
||||||
|
|
||||||
setupBackground();
|
|
||||||
|
|
||||||
setupAuthlibInjectorDnD();
|
setupAuthlibInjectorDnD();
|
||||||
|
|
||||||
|
// Setup background
|
||||||
|
decorator.setContentBackground(getBackground());
|
||||||
|
changeBackgroundListener = o -> {
|
||||||
|
final int currentCount = ++this.changeBackgroundCount;
|
||||||
|
CompletableFuture.supplyAsync(this::getBackground, Schedulers.io())
|
||||||
|
.thenAcceptAsync(background -> {
|
||||||
|
if (this.changeBackgroundCount == currentCount)
|
||||||
|
decorator.setContentBackground(background);
|
||||||
|
}, Schedulers.javafx());
|
||||||
|
};
|
||||||
|
WeakInvalidationListener weakListener = new WeakInvalidationListener(changeBackgroundListener);
|
||||||
|
config().backgroundImageTypeProperty().addListener(weakListener);
|
||||||
|
config().backgroundImageProperty().addListener(weakListener);
|
||||||
|
config().backgroundImageUrlProperty().addListener(weakListener);
|
||||||
|
|
||||||
// pass key events to current dialog / current page
|
// pass key events to current dialog / current page
|
||||||
decorator.addEventFilter(KeyEvent.ANY, e -> {
|
decorator.addEventFilter(KeyEvent.ANY, e -> {
|
||||||
if (!(e.getTarget() instanceof Node)) {
|
if (!(e.getTarget() instanceof Node)) {
|
||||||
@@ -134,37 +150,40 @@ public class DecoratorController {
|
|||||||
|
|
||||||
// ==== Background ====
|
// ==== Background ====
|
||||||
|
|
||||||
private void setupBackground() {
|
//FXThread
|
||||||
decorator.contentBackgroundProperty().bind(
|
private int changeBackgroundCount = 0;
|
||||||
Bindings.createObjectBinding(
|
|
||||||
() -> {
|
@SuppressWarnings("FieldCanBeLocal") // Strong reference
|
||||||
Image image = null;
|
private final InvalidationListener changeBackgroundListener;
|
||||||
if (config().getBackgroundImageType() == EnumBackgroundImage.CUSTOM && config().getBackgroundImage() != null) {
|
|
||||||
image = tryLoadImage(Paths.get(config().getBackgroundImage()))
|
private Background getBackground() {
|
||||||
.orElse(null);
|
EnumBackgroundImage imageType = config().getBackgroundImageType();
|
||||||
}
|
|
||||||
if (config().getBackgroundImageType() == EnumBackgroundImage.NETWORK) {
|
Image image = null;
|
||||||
if (!NetworkUtils.isURL(config().getBackgroundImageUrl())) {
|
switch (imageType) {
|
||||||
image = loadDefaultBackgroundImage();
|
case CUSTOM:
|
||||||
} else {
|
String backgroundImage = config().getBackgroundImage();
|
||||||
image = new Image(config().getBackgroundImageUrl(), true);
|
if (backgroundImage != null)
|
||||||
}
|
image = tryLoadImage(Paths.get(backgroundImage)).orElse(null);
|
||||||
} else if (config().getBackgroundImageType() == EnumBackgroundImage.CLASSIC) {
|
break;
|
||||||
image = newImage("/assets/img/background-classic.jpg");
|
case NETWORK:
|
||||||
} else if (config().getBackgroundImageType() == EnumBackgroundImage.TRANSLUCENT) {
|
String backgroundImageUrl = config().getBackgroundImageUrl();
|
||||||
return new Background(new BackgroundFill(new Color(1, 1, 1, 0.5), CornerRadii.EMPTY, Insets.EMPTY));
|
if (backgroundImageUrl != null && NetworkUtils.isURL(backgroundImageUrl))
|
||||||
}
|
image = tryLoadImage(backgroundImageUrl).orElse(null);
|
||||||
if (image == null) {
|
break;
|
||||||
image = loadDefaultBackgroundImage();
|
case CLASSIC:
|
||||||
}
|
image = newImage("/assets/img/background-classic.jpg");
|
||||||
return new Background(new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)));
|
break;
|
||||||
},
|
case TRANSLUCENT:
|
||||||
config().backgroundImageTypeProperty(),
|
return new Background(new BackgroundFill(new Color(1, 1, 1, 0.5), CornerRadii.EMPTY, Insets.EMPTY));
|
||||||
config().backgroundImageProperty(),
|
}
|
||||||
config().backgroundImageUrlProperty()));
|
if (image == null) {
|
||||||
|
image = loadDefaultBackgroundImage();
|
||||||
|
}
|
||||||
|
return new Background(new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image defaultBackground;
|
private volatile Image defaultBackground;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load background image from bg/, background.png, background.jpg, background.gif
|
* Load background image from bg/, background.png, background.jpg, background.gif
|
||||||
@@ -196,7 +215,7 @@ public class DecoratorController {
|
|||||||
List<Path> candidates;
|
List<Path> candidates;
|
||||||
try (Stream<Path> stream = Files.list(imageDir)) {
|
try (Stream<Path> stream = Files.list(imageDir)) {
|
||||||
candidates = stream
|
candidates = stream
|
||||||
.filter(Files::isReadable)
|
.filter(Files::isReadable)
|
||||||
.filter(it -> {
|
.filter(it -> {
|
||||||
String ext = getExtension(it).toLowerCase(Locale.ROOT);
|
String ext = getExtension(it).toLowerCase(Locale.ROOT);
|
||||||
return ext.equals("png") || ext.equals("jpg") || ext.equals("gif");
|
return ext.equals("png") || ext.equals("jpg") || ext.equals("gif");
|
||||||
@@ -224,9 +243,13 @@ public class DecoratorController {
|
|||||||
if (!Files.isReadable(path))
|
if (!Files.isReadable(path))
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
||||||
|
return tryLoadImage(path.toAbsolutePath().toUri().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Image> tryLoadImage(String url) {
|
||||||
Image img;
|
Image img;
|
||||||
try {
|
try {
|
||||||
img = new Image(path.toAbsolutePath().toUri().toString());
|
img = new Image(url);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
LOG.log(WARNING, "Couldn't load background image", e);
|
LOG.log(WARNING, "Couldn't load background image", e);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|||||||
Reference in New Issue
Block a user