Add Image Caching #95

Merged
kske merged 2 commits from f/image-cache into develop 2020-10-13 11:30:20 +02:00
3 changed files with 42 additions and 16 deletions
Showing only changes of commit 3c7f2da752 - Show all commits

View File

@ -132,7 +132,6 @@ public final class ChatScene implements EventListener, Restorable {
private Chat currentChat; private Chat currentChat;
private FilteredList<Chat> chats; private FilteredList<Chat> chats;
private boolean recording;
private Attachment pendingAttachment; private Attachment pendingAttachment;
private boolean postingPermanentlyDisabled; private boolean postingPermanentlyDisabled;
private boolean isCustomAttachmentImage; private boolean isCustomAttachmentImage;
@ -354,7 +353,8 @@ public final class ChatScene implements EventListener, Restorable {
// Discard the pending attachment // Discard the pending attachment
if (recorder.isRecording()) { if (recorder.isRecording()) {
recorder.cancel(); recorder.cancel();
recording = false; voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
voiceButton.setText(null);
} }
pendingAttachment = null; pendingAttachment = null;
updateAttachmentView(false); updateAttachmentView(false);
@ -414,18 +414,16 @@ public final class ChatScene implements EventListener, Restorable {
private void voiceButtonClicked() { private void voiceButtonClicked() {
new Thread(() -> { new Thread(() -> {
try { try {
if (!recording) { if (!recorder.isRecording()) {
recording = true;
Platform.runLater(() -> { Platform.runLater(() -> {
voiceButton.setText("Recording"); voiceButton.setText("Recording");
voiceButton.setGraphic(new ImageView(IconUtil.loadIcon("microphone_recording", DEFAULT_ICON_SIZE))); voiceButton.setGraphic(new ImageView(IconUtil.loadIcon("microphone_recording", DEFAULT_ICON_SIZE)));
}); });
recorder.start(); recorder.start();
} else { } else {
pendingAttachment = new Attachment(recorder.finish(), "Voice_recording_" pendingAttachment = new Attachment(recorder.finish(), "Voice_recording_"
+ DateTimeFormatter.ofPattern("yyyy_MM_dd-HH_mm_ss").format(LocalDateTime.now()) + "." + AudioRecorder.FILE_FORMAT, + DateTimeFormatter.ofPattern("yyyy_MM_dd-HH_mm_ss").format(LocalDateTime.now()) + "." + AudioRecorder.FILE_FORMAT,
AttachmentType.VOICE); AttachmentType.VOICE);
recording = false;
Platform.runLater(() -> { Platform.runLater(() -> {
voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE))); voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
voiceButton.setText(null); voiceButton.setText(null);

View File

@ -21,8 +21,11 @@ import envoy.util.EnvoyLog;
*/ */
public final class IconUtil { public final class IconUtil {
private IconUtil() {} private static final HashMap<String, Image> cache = new HashMap<>();
private static final HashMap<String, BufferedImage> awtCache = new HashMap<>();
private IconUtil() {}
/** /**
* Loads an image from the resource folder. * Loads an image from the resource folder.
* *
@ -30,7 +33,14 @@ public final class IconUtil {
* @return the loaded image * @return the loaded image
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
public static Image load(String path) { return new Image(IconUtil.class.getResource(path).toExternalForm()); } public static Image load(String path) {
if (cache.containsKey(path)) return cache.get(path);
else {
final var image = new Image(IconUtil.class.getResource(path).toExternalForm());
cache.put(path, image);
return image;
}
}
/** /**
* Loads an image from the resource folder and scales it to the given size. * Loads an image from the resource folder and scales it to the given size.
@ -39,9 +49,21 @@ public final class IconUtil {
* @param size the size to scale the icon to * @param size the size to scale the icon to
* @return the scaled image * @return the scaled image
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
* @apiNote There is an extraordinarily low chance that there is a size and name
* conflict. To achieve that however, you basically have to name your
* image intentionally like that. For normal human readable names or
* even automatically generated ones it will never occur.
*/ */
public static Image load(String path, int size) { public static Image load(String path, int size) {
return new Image(IconUtil.class.getResource(path).toExternalForm(), size, size, true, true);
// Minimizing the risk of size and name conflict
final var sizeSpecificString = path + size + "+a* ";
if (cache.containsKey(sizeSpecificString)) return cache.get(sizeSpecificString);
else {
final var image = new Image(IconUtil.class.getResource(path).toExternalForm(), size, size, true, true);
cache.put(sizeSpecificString, image);
return image;
}
} }
/** /**
@ -138,13 +160,19 @@ public final class IconUtil {
* @since Envoy Client v0.2-beta * @since Envoy Client v0.2-beta
*/ */
public static BufferedImage loadAWTCompatible(String path) { public static BufferedImage loadAWTCompatible(String path) {
BufferedImage image = null; if (awtCache.containsKey(path)) return awtCache.get(path);
try { else {
image = ImageIO.read(IconUtil.class.getResource(path)); BufferedImage image = null;
} catch (final IOException e) { try {
EnvoyLog.getLogger(IconUtil.class).log(Level.WARNING, String.format("Could not load image at path %s: ", path), e); image = ImageIO.read(IconUtil.class.getResource(path));
} catch (final IOException e) {
EnvoyLog.getLogger(IconUtil.class).log(Level.WARNING, String.format("Could not load image at path %s: ", path), e);
}
// If an IOException occurs we don't assume it'll be fixed on the next call
awtCache.put(path, image);
return image;
} }
return image;
} }
/** /**

View File

@ -175,7 +175,7 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
<HBox.margin> <HBox.margin>
<Insets bottom="35.0" left="5.0" top="35.0"/> <Insets bottom="35.0" left="5.0" top="35.0" />
</HBox.margin> </HBox.margin>
</Button> </Button>
</children> </children>