From c2eb9af86256dd1ecedf0d09901250682ce003df Mon Sep 17 00:00:00 2001 From: jmillman Date: Wed, 15 Jul 2015 14:27:28 -0400 Subject: [PATCH] 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 --- ...ounds_cyanblue.gif => working_spinner.gif} | Bin .../gui/drawableviews/DrawableTile.java | 125 +++++++++--------- .../gui/drawableviews/DrawableUIBase.java | 7 +- .../gui/drawableviews/GroupPane.java | 36 ++--- .../gui/drawableviews/SlideShowView.java | 14 +- 5 files changed, 94 insertions(+), 88 deletions(-) rename Core/src/org/sleuthkit/autopsy/images/{Throbber_allbackgrounds_cyanblue.gif => working_spinner.gif} (100%) diff --git a/Core/src/org/sleuthkit/autopsy/images/Throbber_allbackgrounds_cyanblue.gif b/Core/src/org/sleuthkit/autopsy/images/working_spinner.gif similarity index 100% rename from Core/src/org/sleuthkit/autopsy/images/Throbber_allbackgrounds_cyanblue.gif rename to Core/src/org/sleuthkit/autopsy/images/working_spinner.gif diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTile.java index 42c6a9b9eb..ef468d7172 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTile.java @@ -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 task; - private SoftReference thumbCache; + private SoftReference 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() { + @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() { - @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(); - } - } - } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java index 267632ed85..ae5ad9d05b 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java @@ -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); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java index c33793ce4d..6e72f1c731 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java @@ -219,7 +219,7 @@ public class GroupPane extends BorderPane { private final InvalidationListener filesSyncListener = (observable) -> { final String header = getHeaderString(); - final List fileIds = getGrouping().fileIds(); + final List 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() { @Override public void handle(ActionEvent t) { - Set fileIdSet = new HashSet<>(getGrouping().fileIds()); + Set 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() { @Override public void handle(ActionEvent t) { - Set fileIdSet = new HashSet<>(getGrouping().fileIds()); + Set 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); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java index 40d6124df8..7e5737637c 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java @@ -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 fileIds = getGroupPane().getGrouping().fileIds(); + final ObservableList fileIds = getGroupPane().getGroup().fileIds(); return getFileID().map(fileID -> " ( " + (fileIds.indexOf(fileID) + 1) + " of " + fileIds.size() + " in group )") .orElse("");