diff --git a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED
index 2aced0f0a0..f69686a0ea 100644
--- a/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/discovery/Bundle.properties-MERGED
@@ -139,7 +139,6 @@ FileSearchFiltering.TagsFilter.or=\ or
FileSearchFiltering.UserCreatedFilter.desc=Files that contain EXIF data
FileSearchPanel.dialogTitle.text=Test file search
FileSearchPanel.sortingPanel.border.title=Grouping
-FileSearchPanel.searchButton.text=Show
FileSearchPanel.addButton.text=Add
FileSearchPanel.steptwo.documents=Step 2: Filter which documents to show
FileSearchPanel.steptwo.images=Step 2: Filter which images to show
@@ -165,7 +164,6 @@ FileSearchDialog.objCheckBox.text=Objects
FileSearchDialog.exifCheckBox.text=Must contain EXIF data
FileSearchDialog.notableCheckBox.text=Must have been tagged as notable
FileSearchDialog.scoreCheckBox.text=Has score
-FileSearchPanel.cancelButton.text=Cancel
FileSearchPanel.hashSetCheckbox.text=Hash Set:
FileSearchPanel.tagsCheckbox.text=Tag:
FileSearchPanel.interestingItemsCheckbox.text=Interesting Item:
@@ -209,16 +207,17 @@ FileSearchPanel.excludeRadioButton.text=Exclude
FileSearchPanel.knownFilesCheckbox.toolTipText=
FileSearchPanel.knownFilesCheckbox.text=Hide known files
GroupListPanel.groupKeyList.border.title=Groups
-DiscoveryTopComponent.imagesButton.text=Images
-DiscoveryTopComponent.videosButton.text=Videos
ResultsPanel.resultsSplitPane.toolTipText=
FileSearchPanel.stepThreeLabel.text=Step 3: Choose display settings
-DiscoveryTopComponent.stepOneLabel.text=Step 1: Pick File Type
-DiscoveryTopComponent.documentsButton.text=Documents
DocumentPanel.fileSizeLabel.toolTipText=
DocumentPanel.isDeletedLabel.toolTipText=
ImageThumbnailPanel.isDeletedLabel.toolTipText=
FileSearchPanel.userCreatedCheckbox.text=Possibly User Created
+DiscoveryDialog.documentsButton.text=Documents
+DiscoveryDialog.videosButton.text=Videos
+DiscoveryDialog.imagesButton.text=Images
+DiscoveryDialog.searchButton.text=Show
+DiscoveryDialog.cancelButton.text=Cancel
ResultsPanel.unableToCreate.text=Unable to create summary.
ResultsPanel.viewFileInDir.name=View File in Directory
VideoThumbnailPanel.bytes.text=bytes
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.form
new file mode 100644
index 0000000000..058ed2dd31
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.form
@@ -0,0 +1,43 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.java
new file mode 100644
index 0000000000..c49cbe0edc
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/discovery/DetailsPanel.java
@@ -0,0 +1,60 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.discovery;
+
+import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
+
+/**
+ *
+ * @author wschaefer
+ */
+public class DetailsPanel extends javax.swing.JPanel {
+
+ private final DataContentPanel dataContentPanel;
+
+ /**
+ * Creates new form DetailsPanel
+ */
+ public DetailsPanel() {
+ initComponents();
+ dataContentPanel = DataContentPanel.createInstance();
+ detailsSplitPane.setBottomComponent(dataContentPanel);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ detailsSplitPane = new javax.swing.JSplitPane();
+
+ detailsSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 667, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(detailsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 667, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 402, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(detailsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JSplitPane detailsSplitPane;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.form
index bc265187e9..407e17c946 100644
--- a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.form
@@ -30,7 +30,7 @@
-
+
@@ -312,22 +312,16 @@
-
-
-
-
-
-
@@ -358,11 +352,11 @@
-
+
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java
index 9a22418fb7..7bd732d18a 100644
--- a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java
@@ -56,10 +56,11 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.textsummarizer.TextSummary;
+import java.awt.Graphics;
/**
- * Panel for displaying of Discovery results and handling the paging of
- * those results.
+ * Panel for displaying of Discovery results and handling the paging of those
+ * results.
*/
public class ResultsPanel extends javax.swing.JPanel {
@@ -82,6 +83,14 @@ public class ResultsPanel extends javax.swing.JPanel {
private final DefaultListModel instancesListModel = new DefaultListModel<>();
private ListSelectionListener listener = null;
+ private int dividerLocation = 1;
+
+ private static final int ANIMATION_INCREMENT = 10;
+
+ private SwingAnimator fadeInAnimator = null;
+
+ private SwingAnimator fadeOutAnimator = null;
+
/**
* Creates new form ResultsPanel.
*/
@@ -164,6 +173,7 @@ public class ResultsPanel extends javax.swing.JPanel {
if (files.isEmpty()) {
//if there are no files currently remove the current items without removing listener to cause content viewer to reset
instancesListModel.removeAllElements();
+ fadeOut();
} else {
//remove listener so content viewer node is not set multiple times
instancesList.removeListSelectionListener(listener);
@@ -176,10 +186,12 @@ public class ResultsPanel extends javax.swing.JPanel {
if (!instancesListModel.isEmpty()) {
instancesList.setSelectedIndex(0);
}
+ fadeIn();
}
});
}
+
/**
* Get the AbstractFile for the item currently selected in the instances
* list.
@@ -425,7 +437,7 @@ public class ResultsPanel extends javax.swing.JPanel {
javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
javax.swing.Box.Filler filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
- javax.swing.JSplitPane resultsSplitPane = new javax.swing.JSplitPane();
+ resultsSplitPane = new javax.swing.JSplitPane();
javax.swing.JPanel instancesPanel = new javax.swing.JPanel();
javax.swing.JScrollPane instancesScrollPane = new javax.swing.JScrollPane();
instancesList = new javax.swing.JList<>();
@@ -580,11 +592,9 @@ public class ResultsPanel extends javax.swing.JPanel {
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
pagingPanel.add(filler4, gridBagConstraints);
- resultsSplitPane.setDividerLocation(380);
resultsSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
resultsSplitPane.setResizeWeight(1.0);
resultsSplitPane.setToolTipText(org.openide.util.NbBundle.getMessage(ResultsPanel.class, "ResultsPanel.resultsSplitPane.toolTipText")); // NOI18N
- resultsSplitPane.setLastDividerLocation(180);
resultsSplitPane.setOpaque(false);
resultsSplitPane.setPreferredSize(new java.awt.Dimension(777, 440));
@@ -609,11 +619,11 @@ public class ResultsPanel extends javax.swing.JPanel {
);
instancesPanelLayout.setVerticalGroup(
instancesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 68, Short.MAX_VALUE)
+ .addGap(0, 433, Short.MAX_VALUE)
.addGroup(instancesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, instancesPanelLayout.createSequentialGroup()
.addGap(0, 0, 0)
- .addComponent(instancesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addComponent(instancesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 433, Short.MAX_VALUE)))
);
resultsSplitPane.setRightComponent(instancesPanel);
@@ -627,14 +637,14 @@ public class ResultsPanel extends javax.swing.JPanel {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pagingPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
- .addComponent(resultsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(resultsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(pagingPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
- .addComponent(resultsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 436, Short.MAX_VALUE)
+ .addComponent(resultsSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 34, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
}// //GEN-END:initComponents
@@ -723,6 +733,7 @@ public class ResultsPanel extends javax.swing.JPanel {
private javax.swing.JButton nextPageButton;
private javax.swing.JComboBox pageSizeComboBox;
private javax.swing.JButton previousPageButton;
+ private javax.swing.JSplitPane resultsSplitPane;
private javax.swing.JPanel resultsViewerPanel;
// End of variables declaration//GEN-END:variables
@@ -878,4 +889,154 @@ public class ResultsPanel extends javax.swing.JPanel {
}
}
+
+ /**
+ *
+ * Sets the alpha value
+ *
+ * @param a
+ *
+ */
+ public void setDividerLocation(int a) {
+
+ this.dividerLocation = a;
+
+ }
+
+ /**
+ *
+ * Fades this JPanel in. *
+ */
+ public void fadeIn() {
+
+ stop();
+
+ fadeInAnimator = new SwingAnimator(new FadeInCallback());
+
+ fadeInAnimator.start();
+
+ }
+
+ /**
+ *
+ * Fades this JPanel out
+ *
+ */
+ public void fadeOut() {
+
+ stop();
+
+ fadeOutAnimator = new SwingAnimator(new FadeOutCallback());
+
+ fadeOutAnimator.start();
+
+ }
+
+ /**
+ *
+ * Stops all animators. *
+ */
+ private void stop() {
+
+ if (fadeOutAnimator != null && fadeOutAnimator.isRunning()) {
+
+ fadeOutAnimator.stop();
+
+ }
+
+ if (fadeInAnimator != null && fadeInAnimator.isRunning()) {
+
+ fadeInAnimator.stop();
+
+ }
+
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+
+ if (dividerLocation <= resultsSplitPane.getHeight() && dividerLocation >= (resultsSplitPane.getHeight() - 100)) {
+ resultsSplitPane.setDividerLocation(dividerLocation);
+ }
+
+ super.paintComponent(g);
+
+ }
+
+ /**
+ *
+ * Callback implementation for fading in
+ *
+ * @author Greg Cope
+ *
+ *
+ *
+ */
+ private class FadeInCallback implements SwingAnimatorCallback {
+
+ @Override
+
+ public void callback(Object caller) {
+
+ dividerLocation -= ANIMATION_INCREMENT;
+
+ repaint();
+
+ }
+
+ @Override
+
+ public boolean hasTerminated() {
+
+ if (dividerLocation <= (resultsSplitPane.getHeight() - 100)) {
+
+ dividerLocation = resultsSplitPane.getHeight() - 100;
+ System.out.println("FADE IN COMPLETE");
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ }
+
+ /**
+ *
+ * Callback implementation to fade out
+ *
+ * @author Greg Cope
+ *
+ *
+ *
+ */
+ private class FadeOutCallback implements SwingAnimatorCallback {
+
+ @Override
+
+ public void callback(Object caller) {
+
+ dividerLocation += ANIMATION_INCREMENT;
+
+ repaint();
+
+ }
+
+ @Override
+
+ public boolean hasTerminated() {
+
+ if (dividerLocation >= resultsSplitPane.getHeight()) {
+
+ dividerLocation = resultsSplitPane.getHeight();
+ System.out.println("FADE OUT COMPLETE");
+ return true;
+ }
+
+ return false;
+ }
+
+ }
+
}
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java
new file mode 100644
index 0000000000..d744f5c3d8
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java
@@ -0,0 +1,193 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.discovery;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.Timer;
+
+/**
+ *
+ * Class to animate Layouts and Fades for a given component.
+ *
+ *
+ * @author Greg Cope
+ *
+ *
+ *
+ */
+public final class SwingAnimator {
+
+ //callback object
+ private final SwingAnimatorCallback callback;
+
+ //Timer to animate on the EDT
+ private Timer timer = null;
+
+ //duration in milliseconds betweeen each firing of the Timer
+ private static final int INITIAL_DURATION = 10;
+ private static int duration = INITIAL_DURATION;
+
+ /**
+ *
+ * Constructs a new SwingAnimator.
+ *
+ *
+ * @param callback The object to callback to
+ *
+ */
+ public SwingAnimator(SwingAnimatorCallback callback) {
+
+ this(callback, false);
+
+ }
+
+ /**
+ *
+ *
+ *
+ * @param callback The object to callback to
+ *
+ * @param start true to automatically start the animation, false
+ * otherwise
+ *
+ */
+ public SwingAnimator(SwingAnimatorCallback callback, boolean start) {
+
+ this(callback, INITIAL_DURATION, start);
+
+ }
+
+ /**
+ *
+ *
+ *
+ * @param callback The object to callback to
+ *
+ * @param frameTiming Timing between each call to callback.
+ *
+ * @param start true to automatically start the animation, false
+ * otherwise
+ *
+ */
+ public SwingAnimator(SwingAnimatorCallback callback, int frameTiming, boolean start) {
+
+ this.callback = callback;
+
+ duration = frameTiming;
+
+ if (start) {
+
+ start();
+
+ }
+
+ }
+
+ /**
+ *
+ *
+ *
+ * @param callback The object to callback to
+ *
+ * @param frameTiming Timing between each call to callback.
+ *
+ */
+ public SwingAnimator(SwingAnimatorCallback callback, int frameTiming) {
+
+ this(callback, frameTiming, false);
+
+ }
+
+ /**
+ *
+ * Checks if this animator is running.
+ *
+ * @return
+ *
+ */
+ public boolean isRunning() {
+
+ if (timer == null) {
+
+ return false;
+
+ }
+
+ return timer.isRunning();
+
+ }
+
+ /**
+ *
+ * Stops the timer
+ *
+ */
+ public void stop() {
+
+ if (timer != null) {
+
+ timer.stop();
+
+ }
+
+ }
+
+ /**
+ *
+ * Starts the timer to fire. If the current timer is non-null and running,
+ * this method will first
+ *
+ * stop the timer before beginning a new one. *
+ */
+ public void start() {
+
+ if (timer != null && timer.isRunning()) {
+
+ stop();
+
+ }
+
+ timer = new Timer(duration, new CallbackListener());
+
+ timer.start();
+
+ }
+
+ /**
+ *
+ * ActionListener implements to be passed to the internal timer instance
+ *
+ * @author Greg Cope
+ *
+ *
+ *
+ */
+ private class CallbackListener implements ActionListener {
+
+ @Override
+
+ public void actionPerformed(ActionEvent e) {
+
+ if (callback.hasTerminated()) {
+
+ if (timer == null) {
+
+ throw new IllegalStateException("Callback listener should not be fired outside of SwingAnimator timer control");
+
+ }
+
+ timer.stop();
+
+ }
+
+ callback.callback(SwingAnimator.this);
+
+ }
+
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java
new file mode 100644
index 0000000000..31a8fdba0d
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java
@@ -0,0 +1,35 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.discovery;
+
+/**
+ *
+ * Callback interface to be notified by a SwingAnimator of a new time frame. *
+ * @author Greg Cope
+ *
+ *
+ *
+ */
+public interface SwingAnimatorCallback {
+
+ /**
+ *
+ * Callback method for the SwingAnimator
+ *
+ * @param caller
+ *
+ */
+ public void callback(Object caller);
+
+ /**
+ *
+ * Returns true if the SwingAnimator should terminate. *
+ * @return
+ *
+ */
+ public boolean hasTerminated();
+
+}