package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
import com.google.common.eventbus.Subscribe;
import java.util.Collection;
import java.util.Optional;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
/**
* Interface for classes that are views of a single DrawableFile. Implementation
* of DrawableView must be registered with {@link CategoryManager#registerListener(java.lang.Object)
* } to have there {@link DrawableView#handleCategoryChanged(org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent)
* } method invoked
*/
public interface DrawableView {
//TODO: do this all in css? -jm
static final int CAT_BORDER_WIDTH = 10;
static final BorderWidths CAT_BORDER_WIDTHS = new BorderWidths(CAT_BORDER_WIDTH);
static final CornerRadii CAT_CORNER_RADII = new CornerRadii(3);
static final Border HASH_BORDER = new Border(new BorderStroke(Color.PURPLE, BorderStrokeStyle.DASHED, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT1_BORDER = new Border(new BorderStroke(Category.ONE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT2_BORDER = new Border(new BorderStroke(Category.TWO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT3_BORDER = new Border(new BorderStroke(Category.THREE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT4_BORDER = new Border(new BorderStroke(Category.FOUR.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT5_BORDER = new Border(new BorderStroke(Category.FIVE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
static final Border CAT0_BORDER = new Border(new BorderStroke(Category.ZERO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
Region getCategoryBorderRegion();
Optional<DrawableFile> getFile();
void setFile(final Long fileID);
Optional<Long> getFileID();
/**
* update the visual representation of the category of the assigned file.
* Implementations of {@link DrawableView} must register themselves with
* {@link CategoryManager#registerListener(java.lang.Object)} to ahve this
* method invoked
*
* @param evt the CategoryChangeEvent to handle
*/
@Subscribe
default void handleCategoryChanged(org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager.CategoryChangeEvent evt) {
getFileID().ifPresent(fileID -> {
if (evt.getFileIDs().contains(fileID)) {
updateCategory();
}
});
}
@Subscribe
void handleTagAdded(ContentTagAddedEvent evt);
@Subscribe
void handleTagDeleted(ContentTagDeletedEvent evt);
ImageGalleryController getController();
default boolean hasHashHit() {
try {
return getFile().map(DrawableFile::getHashSetNamesUnchecked)
.map((Collection<String> t) -> t.isEmpty() == false)
.orElse(false);
} catch (NullPointerException ex) {
// I think this happens when we're in the process of removing images from the view while
// also trying to update it?
Logger.getLogger(DrawableView.class.getName()).log(Level.WARNING, "Error looking up hash set hits"); //NON-NLS
return false;
}
}
static Border getCategoryBorder(Category category) {
if (category != null) {
switch (category) {
case ONE:
return CAT1_BORDER;
case TWO:
return CAT2_BORDER;
case THREE:
return CAT3_BORDER;
case FOUR:
return CAT4_BORDER;
case FIVE:
return CAT5_BORDER;
case ZERO:
default:
return CAT0_BORDER;
}
} else {
return CAT0_BORDER;
}
}
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
default Category updateCategory() {
if (getFile().isPresent()) {
final Category category = getFile().map(DrawableFile::getCategory).orElse(Category.ZERO);
final Border border = hasHashHit() && (category == Category.ZERO) ? HASH_BORDER : getCategoryBorder(category);
Platform.runLater(() -> getCategoryBorderRegion().setBorder(border));
return category;
} else {
return Category.ZERO;
}
}
}