19 package org.sleuthkit.autopsy.contentviewers;
22 import java.awt.Dimension;
23 import java.awt.EventQueue;
24 import java.awt.event.ActionEvent;
25 import java.util.Collections;
26 import java.util.List;
27 import static java.util.Objects.nonNull;
28 import java.util.SortedSet;
29 import java.util.concurrent.ExecutionException;
30 import java.util.stream.Collectors;
31 import javafx.application.Platform;
32 import javafx.concurrent.Task;
33 import javafx.embed.swing.JFXPanel;
34 import javafx.geometry.Pos;
35 import javafx.scene.Cursor;
36 import javafx.scene.Scene;
37 import javafx.scene.control.Button;
38 import javafx.scene.control.Label;
39 import javafx.scene.control.ProgressBar;
40 import javafx.scene.image.Image;
41 import javafx.scene.image.ImageView;
42 import javafx.scene.layout.BorderPane;
43 import javafx.scene.layout.VBox;
44 import javax.imageio.ImageIO;
45 import javax.swing.JPanel;
46 import org.controlsfx.control.MaskerPane;
47 import org.openide.util.NbBundle;
48 import org.python.google.common.collect.Lists;
61 @NbBundle.Messages({
"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer",
62 "MediaViewImagePanel.errorLabel.text=Could not load file into Media View.",
63 "MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."})
66 private static final Image EXTERNAL =
new Image(
MediaViewImagePanel.class.getResource(
"/org/sleuthkit/autopsy/images/external.png").toExternalForm());
75 private final ProgressBar progressBar =
new ProgressBar();
76 private final MaskerPane maskerPane =
new MaskerPane();
79 ImageIO.scanForPlugins();
93 .collect(Collectors.toList());
104 Platform.runLater(() -> {
107 fxImageView =
new ImageView();
108 borderpane =
new BorderPane(fxImageView);
109 borderpane.getStyleClass().add(
"bg");
110 fxPanel =
new JFXPanel();
111 Scene scene =
new Scene(borderpane);
112 scene.getStylesheets().add(
MediaViewImagePanel.class.getResource(
"MediaViewImagePanel.css").toExternalForm());
113 fxPanel.setScene(scene);
116 fxImageView.fitWidthProperty().bind(scene.widthProperty());
117 fxImageView.fitHeightProperty().bind(scene.heightProperty());
118 fxImageView.setPreserveRatio(
true);
119 fxImageView.setSmooth(
true);
120 fxImageView.setCache(
true);
122 EventQueue.invokeLater(() -> {
137 Platform.runLater(() -> {
138 fxImageView.setImage(null);
139 borderpane.setCenter(null);
144 final Button externalViewerButton =
new Button(Bundle.MediaViewImagePanel_externalViewerButton_text(),
new ImageView(EXTERNAL));
145 externalViewerButton.setOnAction(actionEvent
151 .actionPerformed(
new ActionEvent(
this, ActionEvent.ACTION_PERFORMED,
""))
154 final VBox errorNode =
new VBox(10,
new Label(errorMessage), externalViewerButton);
155 errorNode.setAlignment(Pos.CENTER);
156 borderpane.setCenter(errorNode);
165 void showImageFx(
final AbstractFile file,
final Dimension dims) {
170 Platform.runLater(() -> {
171 if (readImageTask != null) {
172 readImageTask.cancel();
174 readImageTask = ImageUtils.newReadImageTask(file);
175 readImageTask.setOnSucceeded(succeeded -> {
176 if (!Case.isCaseOpen()) {
188 Image fxImage = readImageTask.get();
189 if (nonNull(fxImage)) {
191 fxImageView.setImage(fxImage);
192 borderpane.setCenter(fxImageView);
194 showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file);
196 }
catch (InterruptedException | ExecutionException ex) {
197 showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file);
199 borderpane.setCursor(Cursor.DEFAULT);
201 readImageTask.setOnFailed(failed -> {
202 if (!Case.isCaseOpen()) {
212 Throwable exception = readImageTask.getException();
213 if (exception instanceof OutOfMemoryError
214 && exception.getMessage().contains(
"Java heap space")) {
215 showErrorNode(Bundle.MediaViewImagePanel_errorLabel_OOMText(), file);
217 showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file);
220 borderpane.setCursor(Cursor.DEFAULT);
223 maskerPane.setProgressNode(progressBar);
224 progressBar.progressProperty().bind(readImageTask.progressProperty());
225 maskerPane.textProperty().bind(readImageTask.messageProperty());
226 borderpane.setCenter(maskerPane);
227 borderpane.setCursor(Cursor.WAIT);
228 new Thread(readImageTask).start();
237 return Collections.unmodifiableList(Lists.newArrayList(supportedMimes));
247 return getExtensions();
256 return Collections.unmodifiableList(supportedExtensions);
269 @SuppressWarnings(
"unchecked")
271 private
void initComponents() {
273 setBackground(
new java.awt.Color(0, 0, 0));
274 setLayout(
new javax.swing.BoxLayout(
this, javax.swing.BoxLayout.Y_AXIS));
static boolean isJavaFxInited()
List< String > getMimeTypes()
boolean isSupported(AbstractFile file)
Task< Image > readImageTask
static List< String > getSupportedImageExtensions()
List< String > getExtensionsList()
void showErrorNode(String errorMessage, AbstractFile file)
List< String > getExtensions()
synchronized static Logger getLogger(String name)
static boolean isImageThumbnailSupported(AbstractFile file)
static SortedSet< String > getSupportedImageMimeTypes()