fix implementation of Background loading of video thumbs in IG

don't transition through null file when reassigning file to DrawableTiles, prevents buildup of load tasks
bring GrouPane methods in line with current nomenclature
reduce calls to FileSyncListener
This commit is contained in:
jmillman 2015-07-15 14:27:28 -04:00
parent 66e9277f5f
commit c2eb9af862
5 changed files with 94 additions and 88 deletions

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -20,13 +20,14 @@ package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
import java.lang.ref.SoftReference;
import java.util.Objects;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.CacheHint;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.effect.DropShadow;
@ -61,7 +62,7 @@ public class DrawableTile extends DrawableTileBase {
private ImageView imageView;
private Task<Image> task;
private SoftReference<Image> thumbCache;
private SoftReference<Image> thumbnailCache;
@Override
synchronized protected void disposeContent() {
@ -69,7 +70,7 @@ public class DrawableTile extends DrawableTileBase {
task.cancel(true);
}
task = null;
thumbCache = null;
thumbnailCache = null;
}
@FXML
@ -117,11 +118,66 @@ public class DrawableTile extends DrawableTileBase {
@Override
synchronized protected void updateContent() {
Node thumbnail = getThumbnail();
Platform.runLater(() -> {
imageBorder.setCenter(thumbnail);
});
if (getFile().isPresent() == false) {
thumbnailCache = null;
Platform.runLater(() -> {
imageView.setImage(null);
imageBorder.setCenter(null);
});
} else {
Image thumbnail = isNull(thumbnailCache) ? null : thumbnailCache.get();
if (nonNull(thumbnail)) {
setImageHelper(thumbnail);
} else if (isNull(task) || task.isDone()) {
DrawableFile<?> file = getFile().get();
task = new Task<Image>() {
@Override
protected Image call() throws Exception {
if (isCancelled() == false) {
return file.getThumbnail();
} else {
return null;
}
}
@Override
protected void failed() {
super.failed();
}
@Override
protected void succeeded() {
super.succeeded();
if (isCancelled() == false) {
try {
synchronized (DrawableTile.this) {
final Image thumbnail = get();
thumbnailCache = new SoftReference<>(thumbnail);
setImageHelper(thumbnailCache.get());
}
} catch (InterruptedException | ExecutionException ex) {
LOGGER.log(Level.WARNING, "failed to get thumbnail for" + file.getName(), ex);
}
}
synchronized (DrawableTile.this) {
task = null;
}
}
};
Platform.runLater(() -> {
imageBorder.setCenter(new ProgressIndicator());
});
new Thread(task).start();
}
}
}
private void setImageHelper(final Image t) {
Platform.runLater(() -> {
imageView.setImage(t);
imageBorder.setCenter(imageView);
});
}
@Override
@ -129,59 +185,4 @@ public class DrawableTile extends DrawableTileBase {
return getFile().map(AbstractContent::getName).orElse("");
}
synchronized private Node getThumbnail() {
if (getFile().isPresent() == false) {
return null;
} else {
Image thumbnail = (thumbCache == null)
? null : thumbCache.get();
if (thumbnail != null) {
Platform.runLater(() -> {
imageView.setImage(thumbnail);
});
return imageView;
} else {
if (task == null || task.isDone()) {
DrawableFile<?> file = getFile().get();
task = new Task<Image>() {
@Override
protected Image call() throws Exception {
if (isCancelled() == false) {
return file.getThumbnail();
} else {
return null;
}
}
@Override
protected void failed() {
super.failed();
}
@Override
protected void succeeded() {
super.succeeded();
if (isCancelled() == false) {
try {
synchronized (DrawableTile.this) {
thumbCache = new SoftReference<>(get());
}
updateContent();
} catch (InterruptedException | ExecutionException ex) {
LOGGER.log(Level.WARNING, "failed to get thumbnail for" + file.getName(), ex);
}
}
synchronized (DrawableTile.this) {
task = null;
}
}
};
new Thread(task).start();
}
return new ProgressIndicator();
}
}
}
}

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
import java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.Optional;
import java.util.logging.Level;
import javafx.scene.layout.AnchorPane;
@ -86,9 +85,11 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
synchronized public void setFile(Long newFileID) {
if (getFileID().isPresent()) {
if (Objects.equals(newFileID, getFileID().get()) == false) {
setFileHelper(newFileID);
if (Objects.nonNull(newFileID)) {
setFileHelper(newFileID);
}
}
} else if (nonNull(newFileID)) {
} else if (Objects.nonNull(newFileID)) {
setFileHelper(newFileID);
}
}

View File

@ -219,7 +219,7 @@ public class GroupPane extends BorderPane {
private final InvalidationListener filesSyncListener = (observable) -> {
final String header = getHeaderString();
final List<Long> fileIds = getGrouping().fileIds();
final List<Long> fileIds = getGroup().fileIds();
Platform.runLater(() -> {
slideShowToggle.setDisable(fileIds.isEmpty());
gridView.getItems().setAll(fileIds);
@ -245,8 +245,8 @@ public class GroupPane extends BorderPane {
}
//assign last selected file or if none first file in group
if (slideShowFileID == null || getGrouping().fileIds().contains(slideShowFileID) == false) {
slideShowPane.setFile(getGrouping().fileIds().get(0));
if (slideShowFileID == null || getGroup().fileIds().contains(slideShowFileID) == false) {
slideShowPane.setFile(getGroup().fileIds().get(0));
} else {
slideShowPane.setFile(slideShowFileID);
}
@ -267,7 +267,7 @@ public class GroupPane extends BorderPane {
this.scrollToFileID(globalSelectionModel.lastSelectedProperty().get());
}
public DrawableGroup getGrouping() {
public DrawableGroup getGroup() {
return grouping.get();
}
@ -276,7 +276,7 @@ public class GroupPane extends BorderPane {
menuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
Set<Long> fileIdSet = new HashSet<>(getGrouping().fileIds());
Set<Long> fileIdSet = new HashSet<>(getGroup().fileIds());
new CategorizeAction(controller).addTagsToFiles(controller.getTagsManager().getTagName(cat), "", fileIdSet);
grpCatSplitMenu.setText(cat.getDisplayName());
@ -291,7 +291,7 @@ public class GroupPane extends BorderPane {
menuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
Set<Long> fileIdSet = new HashSet<>(getGrouping().fileIds());
Set<Long> fileIdSet = new HashSet<>(getGroup().fileIds());
new AddDrawableTagAction(controller).addTagsToFiles(tn, "", fileIdSet);
grpTagSplitMenu.setText(tn.getDisplayName());
@ -302,14 +302,14 @@ public class GroupPane extends BorderPane {
}
private void selectAllFiles() {
globalSelectionModel.clearAndSelectAll(getGrouping().fileIds());
globalSelectionModel.clearAndSelectAll(getGroup().fileIds());
}
/** create the string to display in the group header */
protected String getHeaderString() {
return isNull(getGrouping()) ? ""
: StringUtils.defaultIfBlank(getGrouping().getGroupByValueDislpayName(), DrawableGroup.getBlankGroupName()) + " -- "
+ getGrouping().getHashSetHitsCount() + " hash set hits / " + getGrouping().getSize() + " files";
return isNull(getGroup()) ? ""
: StringUtils.defaultIfBlank(getGroup().getGroupByValueDislpayName(), DrawableGroup.getBlankGroupName()) + " -- "
+ getGroup().getHashSetHitsCount() + " hash set hits / " + getGroup().getSize() + " files";
}
ContextMenu getContextMenu() {
@ -579,11 +579,11 @@ public class GroupPane extends BorderPane {
* @param grouping the new grouping assigned to this group
*/
void setViewState(GroupViewState viewState) {
if (nonNull(getGrouping())) {
getGrouping().fileIds().removeListener(filesSyncListener);
}
if (isNull(viewState) || isNull(viewState.getGroup())) {
if (nonNull(getGroup())) {
getGroup().fileIds().removeListener(filesSyncListener);
}
this.grouping.set(null);
Platform.runLater(() -> {
@ -599,15 +599,18 @@ public class GroupPane extends BorderPane {
});
} else {
if (this.grouping.get() != viewState.getGroup()) {
if (getGroup() != viewState.getGroup()) {
if (nonNull(getGroup())) {
getGroup().fileIds().removeListener(filesSyncListener);
}
this.grouping.set(viewState.getGroup());
this.getGrouping().fileIds().addListener(filesSyncListener);
getGroup().fileIds().addListener(filesSyncListener);
final String header = getHeaderString();
gridView.getItems().setAll(getGrouping().fileIds());
Platform.runLater(() -> {
gridView.getItems().setAll(getGroup().fileIds());
slideShowToggle.setDisable(gridView.getItems().isEmpty());
groupLabel.setText(header);
resetScrollBar();
@ -686,6 +689,7 @@ public class GroupPane extends BorderPane {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
tile.setFile(item);
}

View File

@ -195,8 +195,8 @@ public class SlideShowView extends DrawableTileBase {
getGroupPane().grouping().addListener((Observable observable) -> {
syncButtonVisibility();
if (getGroupPane().getGrouping() != null) {
getGroupPane().getGrouping().fileIds().addListener((Observable observable1) -> {
if (getGroupPane().getGroup() != null) {
getGroupPane().getGroup().fileIds().addListener((Observable observable1) -> {
syncButtonVisibility();
});
}
@ -206,7 +206,7 @@ public class SlideShowView extends DrawableTileBase {
@ThreadConfined(type = ThreadType.ANY)
private void syncButtonVisibility() {
try {
final boolean hasMultipleFiles = getGroupPane().getGrouping().fileIds().size() > 1;
final boolean hasMultipleFiles = getGroupPane().getGroup().fileIds().size() > 1;
Platform.runLater(() -> {
rightButton.setVisible(hasMultipleFiles);
leftButton.setVisible(hasMultipleFiles);
@ -288,12 +288,12 @@ public class SlideShowView extends DrawableTileBase {
@ThreadConfined(type = ThreadType.JFX)
synchronized private void cycleSlideShowImage(int direction) {
stopVideo();
final int groupSize = getGroupPane().getGrouping().fileIds().size();
final int groupSize = getGroupPane().getGroup().fileIds().size();
final Integer nextIndex = getFileID().map(fileID -> {
final int currentIndex = getGroupPane().getGrouping().fileIds().indexOf(fileID);
final int currentIndex = getGroupPane().getGroup().fileIds().indexOf(fileID);
return (currentIndex + direction + groupSize) % groupSize;
}).orElse(0);
setFile(getGroupPane().getGrouping().fileIds().get(nextIndex)
setFile(getGroupPane().getGroup().fileIds().get(nextIndex)
);
}
@ -302,7 +302,7 @@ public class SlideShowView extends DrawableTileBase {
* of y"
*/
private String getSupplementalText() {
final ObservableList<Long> fileIds = getGroupPane().getGrouping().fileIds();
final ObservableList<Long> fileIds = getGroupPane().getGroup().fileIds();
return getFileID().map(fileID -> " ( " + (fileIds.indexOf(fileID) + 1) + " of " + fileIds.size() + " in group )")
.orElse("");