diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/CoreComponentControl.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/CoreComponentControl.java index 7c7b7fd182..2ada97d001 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/CoreComponentControl.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/CoreComponentControl.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.corecomponentinterfaces; import java.util.Collection; import java.util.Iterator; +import java.util.Set; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.util.Lookup; @@ -71,17 +72,47 @@ public class CoreComponentControl { /** * Closes all TopComponent windows that needed ({@link DataExplorer}, {@link DataResult}, and - * {@link DataContent}) + * {@link DataContent}). + * + * Note: The DataContent Top Component must be closed before the Directory Tree + * and Favorites Top Components. Otherwise a NullPointerException will be thrown + * from JFXPanel. */ public static void closeCoreWindows() { WindowManager wm = WindowManager.getDefault(); + Set extends Mode> modes = wm.getModes(); Iterator extends Mode> iter = wm.getModes().iterator(); + TopComponent directoryTree = null; + TopComponent favorites = null; + String tcName = ""; while (iter.hasNext()) { Mode mode = iter.next(); for (TopComponent tc : mode.getTopComponents()) { - tc.close(); + tcName = tc.getName(); + if (tcName == null) { + logger.log(Level.INFO, "tcName was null"); + tcName = ""; + } + switch (tcName) { + case "Directory Tree": + directoryTree = tc; + break; + case "Favorites": + favorites = tc; + break; + default: + tc.close(); + break; + } } } + + if (directoryTree != null) { + directoryTree.close(); + } + if (favorites != null) { + favorites.close(); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java index a825751e4c..d38b2e900c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java @@ -189,8 +189,7 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent, // let the user decide if we should stay with the current viewer int tabIndex = keepCurrentViewer ? currTabIndex : preferredViewerIndex; - // set the tab to the one the user wants, then set that viewer's node. - jTabbedPane1.setSelectedIndex(tabIndex); + UpdateWrapper dcv = viewers.get(tabIndex); // this is really only needed if no tabs were enabled if (jTabbedPane1.isEnabledAt(tabIndex) == false) { @@ -199,6 +198,9 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent, else { dcv.setNode(selectedNode); } + + // set the tab to the one the user wants, then set that viewer's node. + jTabbedPane1.setSelectedIndex(tabIndex); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index af1d14d312..dafffe9ab2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -128,19 +128,19 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo return; //prevent from loading twice if setNode() called mult. times } - resetComponent(); + lastFile = file; final Dimension dims = DataContentViewerMedia.this.getSize(); if (imagePanelInited && containsExt(file.getName(), IMAGES)) { imagePanel.showImageFx(file, dims); - this.switchPanels(false); + this.switchPanels(false); } else if (videoPanelInited && (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) { videoPanel.setupVideo(file, dims); switchPanels(true); } - lastFile = file; + } catch (Exception e) { logger.log(Level.SEVERE, "Exception while setting node", e); } @@ -182,8 +182,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override public void resetComponent() { - videoPanel.reset(); - // @@@ Seems like we should also reset the image viewer... + // No need to reset the video panel. It resets itself when a node is + // set. lastFile = null; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.form index f05c64d887..5143a19b43 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.form @@ -1,6 +1,11 @@
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java index 7e89f8f923..1fa8b72f5d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.corecomponents; -import java.awt.Component; import java.awt.Dimension; import java.io.IOException; import java.nio.file.Paths; @@ -41,7 +40,6 @@ import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; -import static javafx.scene.layout.BorderPane.setAlignment; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; @@ -56,8 +54,8 @@ import static javafx.scene.media.MediaPlayer.Status.READY; import static javafx.scene.media.MediaPlayer.Status.STOPPED; import javafx.scene.media.MediaPlayerBuilder; import javafx.scene.media.MediaView; +import javafx.scene.text.Font; import javafx.util.Duration; -import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; @@ -97,29 +95,28 @@ public class FXVideoPanel extends MediaViewVideoPanel { public FXVideoPanel() { fxInited = Installer.isJavaFxInited(); initComponents(); - customizeComponents(); + if (fxInited) { + setupFx(); + } } public JPanel getVideoPanel() { - return videoPanel; + return this; } - - public Component getVideoComponent() { - return videoComponent; - } - - private void customizeComponents() { - SwingUtilities.invokeLater(new Runnable() { + + private void setupFx() { + Platform.runLater(new Runnable() { @Override public void run() { - videoPanel.removeAll(); - videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS)); - videoPanel.setVisible(true); + videoComponent = new JFXPanel(); + mediaPane = new MediaPane(); + Scene fxScene = new Scene(mediaPane); + videoComponent.setScene(fxScene); - Platform.runLater(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - setupFx(); + add(videoComponent); } }); } @@ -128,12 +125,21 @@ public class FXVideoPanel extends MediaViewVideoPanel { @Override - synchronized void setupVideo(final AbstractFile file, final Dimension dims) { + void setupVideo(final AbstractFile file, final Dimension dims) { + if(file.equals(currentFile)) { + return; + } + if (!Case.isCaseOpen()) { + //handle in-between condition when case is being closed + //and an image was previously selected + return; + } + reset(); currentFile = file; final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC); if (deleted) { mediaPane.setInfoLabelText("Playback of deleted videos is not supported, use an external player."); - videoPanel.removeAll(); + removeAll(); return; } @@ -148,24 +154,10 @@ public class FXVideoPanel extends MediaViewVideoPanel { ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile)); em.execute(); + + mediaPane.setFit(dims); } - synchronized void setupFx() { - if(!fxInited) { - return; - } - videoComponent = new JFXPanel(); - mediaPane = new MediaPane(); - Scene fxScene = new Scene(mediaPane); - videoComponent.setScene(fxScene); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - videoPanel.add(videoComponent); - } - }); - } @Override @@ -205,32 +197,10 @@ public class FXVideoPanel extends MediaViewVideoPanel { //true to disable controls
- * false to enable controls
+ * Reset the progress label and slider to zero.
*/
- private void disableControls(final boolean disable) {
- Platform.runLater(new Runnable() {
- @Override
- public void run() {
- pauseButton.setDisable(disable);
- progressSlider.setDisable(disable);
- }
- });
+ private void resetProgress() {
+ totalHours = 0;
+ totalMinutes = 0;
+ totalSeconds = 0;
+ progressSlider.setValue(0.0);
+ updateTime(Duration.ZERO);
}
/**
@@ -514,6 +523,9 @@ public class FXVideoPanel extends MediaViewVideoPanel {
MediaPlayerBuilder mediaPlayerBuilder = MediaPlayerBuilder.create();
mediaPlayerBuilder.media(media);
mediaPlayerBuilder.onReady(READY_LISTENER);
+ mediaPlayerBuilder.onPaused(NOT_PLAY_LISTENER);
+ mediaPlayerBuilder.onStopped(NOT_PLAY_LISTENER);
+ mediaPlayerBuilder.onPlaying(PLAY_LISTENER);
mediaPlayerBuilder.onEndOfMedia(END_LISTENER);
MediaPlayer player = mediaPlayerBuilder.build();
@@ -538,7 +550,7 @@ public class FXVideoPanel extends MediaViewVideoPanel {
*/
private void updateSlider(Duration currentTime) {
if (progressSlider != null) {
- progressSlider.setDisable(duration.isUnknown());
+ progressSlider.setDisable(currentTime.isUnknown());
if (!progressSlider.isDisabled() && duration.greaterThan(Duration.ZERO)
&& !progressSlider.isValueChanging()) {
progressSlider.setValue(currentTime.divide(duration.toMillis()).toMillis() * 100.0);
@@ -625,14 +637,14 @@ public class FXVideoPanel extends MediaViewVideoPanel {
Duration beginning = mediaPlayer.getStartTime();
mediaPlayer.stop();
mediaPlayer.pause();
- pauseButton.setText("►");
+ pauseButton.setText(PLAY_TEXT);
updateSlider(beginning);
updateTime(beginning);
}
}
/**
- * Responds changes in the MediaPlayer currentTime property.
+ * Responds to changes in the MediaPlayer currentTime property.
*
* Updates the progress slider and label with the current Time.
*/
@@ -643,6 +655,28 @@ public class FXVideoPanel extends MediaViewVideoPanel {
updateTime(newValue);
}
}
+
+ /**
+ * Triggered when MediaPlayer State changes to PAUSED or Stopped.
+ */
+ private class NotPlayListener implements Runnable {
+ @Override
+ public void run() {
+ pauseButton.setText(PLAY_TEXT);
+ pauseButton.setStyle(PLAY_STYLE);
+ }
+ }
+
+ /**
+ * Triggered when MediaPlayer State changes to PLAYING.
+ */
+ private class PlayListener implements Runnable {
+ @Override
+ public void run() {
+ pauseButton.setText(PAUSE_TEXT);
+ pauseButton.setStyle(PAUSE_STYLE);
+ }
+ }
}
/**
@@ -760,5 +794,4 @@ public class FXVideoPanel extends MediaViewVideoPanel {
// return frames;
// }
// }
-
}
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java
index 48e29a1970..955cc1a525 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java
@@ -437,7 +437,7 @@ public class GstVideoPanel extends MediaViewVideoPanel {
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
- //