145 lines
5.3 KiB
Java
145 lines
5.3 KiB
Java
package ctbrec.ui.action;
|
|
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Image;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.util.Arrays;
|
|
import java.util.UUID;
|
|
import java.util.function.Consumer;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import ctbrec.Config;
|
|
import ctbrec.Model;
|
|
import ctbrec.StringUtil;
|
|
import ctbrec.ui.controls.Dialogs;
|
|
import ctbrec.ui.controls.FileSelectionBox;
|
|
import javafx.geometry.Insets;
|
|
import javafx.scene.Cursor;
|
|
import javafx.scene.Node;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.layout.GridPane;
|
|
|
|
public class SetPortraitAction {
|
|
private static final Logger LOG = LoggerFactory.getLogger(SetPortraitAction.class);
|
|
public static final String FORMAT = "jpg";
|
|
|
|
private Node source;
|
|
private Model model;
|
|
private Consumer<Model> callback;
|
|
|
|
public SetPortraitAction(Node source, Model selectedModel, Consumer<Model> callback) {
|
|
this.source = source;
|
|
this.model = selectedModel;
|
|
this.callback = callback;
|
|
}
|
|
|
|
public void execute() {
|
|
source.setCursor(Cursor.WAIT);
|
|
String portraitId = Config.getInstance().getSettings().modelPortraits.getOrDefault(model.getUrl(),
|
|
UUID.nameUUIDFromBytes(model.getUrl().getBytes(StandardCharsets.UTF_8)).toString());
|
|
|
|
GridPane pane = new GridPane();
|
|
Label l = new Label("Select a portrait image. Leave empty to remove a portrait again.");
|
|
pane.add(l, 0, 0);
|
|
FileSelectionBox portraitSelectionBox = new FileSelectionBox();
|
|
pane.add(portraitSelectionBox, 0, 1);
|
|
GridPane.setMargin(l, new Insets(5));
|
|
GridPane.setMargin(portraitSelectionBox, new Insets(5));
|
|
boolean accepted = Dialogs.showCustomInput(source.getScene(), "Select a portrait image", pane);
|
|
if (!accepted) {
|
|
source.setCursor(Cursor.DEFAULT);
|
|
return;
|
|
}
|
|
String selectedFile = portraitSelectionBox.fileProperty().getValue();
|
|
|
|
if (StringUtil.isBlank(selectedFile)) {
|
|
removePortrait(portraitId);
|
|
} else {
|
|
LOG.debug("User selected {}", selectedFile);
|
|
boolean success = processImageFile(portraitId, selectedFile);
|
|
if (success) {
|
|
Config.getInstance().getSettings().modelPortraits.put(model.getUrl(), portraitId);
|
|
try {
|
|
Config.getInstance().save();
|
|
runCallback();
|
|
} catch (IOException e) {
|
|
Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e);
|
|
}
|
|
}
|
|
}
|
|
source.setCursor(Cursor.DEFAULT);
|
|
}
|
|
|
|
private void removePortrait(String portraitId) {
|
|
File portraitFile = getPortraitFile(portraitId);
|
|
try {
|
|
if (portraitFile.exists()) {
|
|
Files.delete(portraitFile.toPath());
|
|
}
|
|
Config.getInstance().getSettings().modelPortraits.remove(model.getUrl());
|
|
Config.getInstance().save();
|
|
runCallback();
|
|
} catch (IOException e) {
|
|
Dialogs.showError("Remove Portrait", "Couldn't remove portrait image: ", e);
|
|
}
|
|
}
|
|
|
|
private void runCallback() {
|
|
if (callback != null) {
|
|
try {
|
|
callback.accept(model);
|
|
} catch (Exception e) {
|
|
LOG.error("Error while executing callback", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean processImageFile(String portraitId, String selectedFile) {
|
|
try {
|
|
BufferedImage portrait = convertToScaledJpg(selectedFile);
|
|
boolean success = copyToCacheAsJpg(portraitId, portrait);
|
|
if (!success) {
|
|
LOG.debug("Available formats: {}", Arrays.toString(ImageIO.getWriterFormatNames()));
|
|
throw new IOException("No suitable writer found for image format " + FORMAT);
|
|
}
|
|
return success;
|
|
} catch (IOException e) {
|
|
LOG.error("Error while changing portrait image", e);
|
|
Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private BufferedImage convertToScaledJpg(String file) throws IOException {
|
|
BufferedImage portrait = ImageIO.read(new File(file));
|
|
Image scaledPortrait = portrait.getScaledInstance(-1, 256, Image.SCALE_SMOOTH);
|
|
BufferedImage bimage = new BufferedImage(scaledPortrait.getWidth(null), scaledPortrait.getHeight(null), BufferedImage.TYPE_INT_RGB);
|
|
Graphics2D bGr = bimage.createGraphics();
|
|
bGr.drawImage(scaledPortrait, 0, 0, null);
|
|
bGr.dispose();
|
|
return bimage;
|
|
}
|
|
|
|
private boolean copyToCacheAsJpg(String portraitId, BufferedImage portrait) throws IOException {
|
|
File output = getPortraitFile(portraitId);
|
|
Files.createDirectories(output.getParentFile().toPath());
|
|
LOG.debug("Writing scaled portrait to {}", output);
|
|
return ImageIO.write(portrait, FORMAT, output);
|
|
}
|
|
|
|
private File getPortraitFile(String portraitId) {
|
|
File configDir = Config.getInstance().getConfigDir();
|
|
File portraitDir = new File(configDir, "portraits");
|
|
File output = new File(portraitDir, portraitId + '.' + FORMAT);
|
|
return output;
|
|
}
|
|
}
|