diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 2296419cd9..7429c69b37 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -19,7 +19,6 @@ OutputViewPanel.currentPageLabel.text=1 OutputViewPanel.pageLabel.text=Page: OutputViewPanel.filePathLabel.text=FilePath OutputViewPanel.nextPageButton.text=Next Page -DataResultTopComponent.directoryTablePath.text=directoryPath DataContentViewerHex.filePathLabel.text=FilePath DataContentViewerHex.pageLabel.text=Page: DataContentViewerHex.currentPageLabel.text=1 @@ -45,8 +44,6 @@ DataContentViewerString.totalPageLabel.text_1=100 DataContentViewerPicture.picLabel.text=[Picture goes Here] DataContentViewerHex.pageLabel2.text=Page DataContentViewerString.pageLabel2.text=Page -DataResultTopComponent.matchLabel.text=Results -DataResultTopComponent.numberMatchLabel.text=0 # Product Information panel @@ -104,3 +101,6 @@ GeneralPanel.keepCurrentViewerRB.text=Stay on the same file viewer GeneralPanel.useBestViewerRB.toolTipText=For example, change from Hex to Media when a JPEG is selected. GeneralPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected. AdvancedConfigurationDialog.cancelButton.text=Cancel +DataResultPanel.directoryTablePath.text=directoryPath +DataResultPanel.numberMatchLabel.text=0 +DataResultPanel.matchLabel.text=Results diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form new file mode 100644 index 0000000000..5984e7cd6d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form @@ -0,0 +1,72 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java new file mode 100644 index 0000000000..9a521e4af1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -0,0 +1,415 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.corecomponents; + +import java.awt.Cursor; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JTabbedPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.openide.nodes.Node; +import org.openide.util.Lookup; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; + +/** + * Data result panel component with its viewer tabs + * + * The component is a generic JPanel and it can be reused in other swing + * components or a TopComponent + */ +public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener { + + private Node rootNode; + private PropertyChangeSupport pcs = new PropertyChangeSupport(this); + /** + * Name of property change fired when a file search result is closed + */ + public static String REMOVE_FILESEARCH = "RemoveFileSearchTopComponent"; + private static String DEFAULT_PREFERRED_ID = "DataResultPanel"; + // Different DataResultsViewers + private final List viewers = new ArrayList(); + //custom content viewer to send selections to, or null if the main one + private DataContent customContentViewer; + private boolean isMain; + private String title; + + /** + * Creates new form DataResultPanel + */ + private DataResultPanel() { + initComponents(); + } + + /** + * Creates new form DataResultPanel + */ + public DataResultPanel(boolean isMain, String title) { + this(); + + this.isMain = isMain; + this.title = title; + + this.dataResultTabbedPanel.addChangeListener(this); + } + + /** + * Create a new, custom data result panel, in addition to the application + * main one + * + * @param name unique name of the data result window, also used as title + * @param customContentViewer custom content viewer to send selection events + * to + */ + public DataResultPanel(String name, DataContentTopComponent customContentViewer) { + this(false, name); + + //custom content viewer tc to setup for every result viewer + this.customContentViewer = customContentViewer; //TODO change to content panel + } + + /** + * Creates a new non-default DataResult component + * + * @param title Title of the component window + * @param pathText Descriptive text about the source of the nodes displayed + * @param givenNode The new root node + * @param totalMatches Cardinality of root node's children + * @return + */ + public static DataResultPanel createInstance(String title, String pathText, Node givenNode, int totalMatches) { + DataResultPanel newDataResult = new DataResultPanel(false, title); + + createInstanceCommon(pathText, givenNode, totalMatches, newDataResult); + + return newDataResult; + } + + /** + * Creates a new non-default DataResult component + * + * @param title Title of the component window + * @param customModeName custom mode to dock this custom TopComponent to + * @param pathText Descriptive text about the source of the nodes displayed + * @param givenNode The new root node + * @param totalMatches Cardinality of root node's children + * @param dataContentWindow a handle to data content top component window to + * @return + */ + public static DataResultPanel createInstance(String title, String pathText, Node givenNode, int totalMatches, DataContentTopComponent dataContentWindow) { + DataResultPanel newDataResult = new DataResultPanel(title, dataContentWindow); + + createInstanceCommon(pathText, givenNode, totalMatches, newDataResult); + return newDataResult; + } + + private static void createInstanceCommon(String pathText, Node givenNode, int totalMatches, DataResultPanel newDataResult) { + newDataResult.numberMatchLabel.setText(Integer.toString(totalMatches)); + + // set the tree table view + newDataResult.setNode(givenNode); + newDataResult.setPath(pathText); + } + + public void componentOpened() { + // Add all the DataContentViewer to the tabbed pannel. + // (Only when the it's opened at the first time: tabCount = 0) + int totalTabs = this.dataResultTabbedPanel.getTabCount(); + if (totalTabs == 0) { + // find all dataContentViewer and add them to the tabbed pane + for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { + DataResultViewer drv = factory.getInstance(); + UpdateWrapper resultViewer = new UpdateWrapper(drv); + if (customContentViewer != null) { + //set custom content viewer to respond to events from this result viewer + resultViewer.setContentViewer(customContentViewer); + } + this.viewers.add(resultViewer); + this.dataResultTabbedPanel.addTab(drv.getTitle(), drv.getComponent()); + + } + } + + if (this.preferredID().equals(DEFAULT_PREFERRED_ID)) { + // if no node selected on DataExplorer, clear the field + if (rootNode == null) { + setNode(rootNode); + } + } + + + + + } + + public void componentClosed() { + pcs.firePropertyChange(REMOVE_FILESEARCH, "", this); // notify to remove this from the menu + + // try to remove any references to this class + PropertyChangeListener[] pcl = pcs.getPropertyChangeListeners(); + for (int i = 0; i < pcl.length; i++) { + pcs.removePropertyChangeListener(pcl[i]); + } + + // clear all set nodes + for (UpdateWrapper drv : this.viewers) { + drv.setNode(null); + } + + if (!this.isMain) { + for (UpdateWrapper drv : this.viewers) { + drv.clearComponent(); + } + this.directoryTablePath.removeAll(); + this.directoryTablePath = null; + this.numberMatchLabel.removeAll(); + this.numberMatchLabel = null; + this.numberMatchLabel.removeAll(); + this.numberMatchLabel = null; + this.setLayout(null); + this.pcs = null; + this.removeAll(); + } + + } + + protected String preferredID() { + if (this.isMain) { + return DEFAULT_PREFERRED_ID; + } else { + return this.getName(); + } + } + + @Override + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + this.pcs.addPropertyChangeListener(listener); + } + + @Override + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + this.pcs.removePropertyChangeListener(listener); + } + + @Override + public String getPreferredID() { + return this.preferredID(); + } + + @Override + public void setNode(Node selectedNode) { + this.rootNode = selectedNode; + if (selectedNode != null) { + int childrenCount = selectedNode.getChildren().getNodesCount(true); + this.numberMatchLabel.setText(Integer.toString(childrenCount)); + } + + this.numberMatchLabel.setVisible(true); + this.numberMatchLabel.setVisible(true); + + resetTabs(selectedNode); + + //update/disable tabs based on if supported for this node + int drvC = 0; + for (UpdateWrapper drv : viewers) { + + if (drv.isSupported(selectedNode)) { + dataResultTabbedPanel.setEnabledAt(drvC, true); + } else { + dataResultTabbedPanel.setEnabledAt(drvC, false); + } + ++drvC; + } + + // set the display on the current active tab + int currentActiveTab = this.dataResultTabbedPanel.getSelectedIndex(); + if (currentActiveTab != -1) { + UpdateWrapper drv = viewers.get(currentActiveTab); + drv.setNode(selectedNode); + } + } + + @Override + public void setTitle(String title) { + setName(title); + } + + @Override + public void setPath(String pathText) { + this.directoryTablePath.setText(pathText); + } + + @Override + public boolean isMain() { + return this.isMain; + } + + public boolean canClose() { + return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case + } + + @Override + public void stateChanged(ChangeEvent e) { + JTabbedPane pane = (JTabbedPane) e.getSource(); + + // Get and set current selected tab + int currentTab = pane.getSelectedIndex(); + if (currentTab != -1) { + UpdateWrapper drv = this.viewers.get(currentTab); + if (drv.isOutdated()) { + // change the cursor to "waiting cursor" for this operation + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + drv.setNode(rootNode); + } finally { + this.setCursor(null); + } + } + } + } + + /** + * Resets the tabs based on the selected Node. If the selected node is null + * or not supported, disable that tab as well. + * + * @param selectedNode the selected content Node + */ + public void resetTabs(Node selectedNode) { + + for (UpdateWrapper drv : this.viewers) { + drv.resetComponent(); + } + } + + public void setSelectedNodes(Node[] selected) { + for (UpdateWrapper drv : this.viewers) { + drv.setSelectedNodes(selected); + } + } + + public Node getRootNode() { + return this.rootNode; + } + + /** + * 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() { + + directoryTablePath = new javax.swing.JLabel(); + numberMatchLabel = new javax.swing.JLabel(); + matchLabel = new javax.swing.JLabel(); + dataResultTabbedPanel = new javax.swing.JTabbedPane(); + + org.openide.awt.Mnemonics.setLocalizedText(directoryTablePath, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.directoryTablePath.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(numberMatchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.numberMatchLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(matchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.matchLabel.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(directoryTablePath) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 518, Short.MAX_VALUE) + .addComponent(numberMatchLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(matchLabel)) + .addComponent(dataResultTabbedPanel) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(numberMatchLabel) + .addComponent(matchLabel)) + .addComponent(directoryTablePath)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 334, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTabbedPane dataResultTabbedPanel; + private javax.swing.JLabel directoryTablePath; + private javax.swing.JLabel matchLabel; + private javax.swing.JLabel numberMatchLabel; + // End of variables declaration//GEN-END:variables + + private static class UpdateWrapper { + + private DataResultViewer wrapped; + private boolean outdated; + + UpdateWrapper(DataResultViewer wrapped) { + this.wrapped = wrapped; + this.outdated = true; + } + + void setNode(Node selectedNode) { + this.wrapped.setNode(selectedNode); + this.outdated = false; + } + + void resetComponent() { + this.wrapped.resetComponent(); + this.outdated = true; + } + + void clearComponent() { + this.wrapped.clearComponent(); + this.outdated = true; + } + + boolean isOutdated() { + return this.outdated; + } + + void setSelectedNodes(Node[] selected) { + this.wrapped.setSelectedNodes(selected); + } + + boolean isSupported(Node selectedNode) { + return this.wrapped.isSupported(selectedNode); + } + + void setContentViewer(DataContent contentViewer) { + this.wrapped.setContentViewer(contentViewer); + } + } + + /** + * + * @param numMatches + */ + public void setNumMatches(int numMatches) { + this.numberMatchLabel.setText(Integer.toString(numMatches)); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.form index adedece8ca..2c9fb994ae 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.form @@ -16,57 +16,13 @@ - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java index 0a638fe9b7..f7715702e6 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java @@ -42,23 +42,12 @@ import org.sleuthkit.autopsy.coreutils.Logger; /** * Top component which displays result (top-right editor mode by default). */ -public class DataResultTopComponent extends TopComponent implements DataResult, ChangeListener { +public class DataResultTopComponent extends TopComponent implements DataResult { private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName()); - private Node rootNode; - private PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private DataResultPanel dataResultPanel; //embedded component with all the logic private boolean isMain; private String customModeName; - private static final String DEFAULT_MODE = "editor"; - private static String DEFAULT_PREFERRED_ID = "DataResultTopComponent"; - /** - * Name of property change fired when a file search result is closed - */ - public static String REMOVE_FILESEARCH = "RemoveFileSearchTopComponent"; - // Different DataResultsViewers - private List viewers = new ArrayList(); - //custom content viewer to send selections to, or null if the main one - private DataContent customContentViewer; /** * Create a new data result top component @@ -71,16 +60,11 @@ public class DataResultTopComponent extends TopComponent implements DataResult, super(); initComponents(); - setToolTipText(NbBundle.getMessage(DataResultTopComponent.class, "HINT_NodeTableTopComponent")); - setTitle(title); // set the title - this.isMain = isMain; - this.customModeName = null; - putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.valueOf(isMain)); // set option to close compoment in GUI - putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, true); - putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, true); + this.dataResultPanel = new DataResultPanel(isMain, title); + + customizeComponent(isMain, title); - this.dataResultTabbedPanel.addChangeListener(this); } /** @@ -93,57 +77,32 @@ public class DataResultTopComponent extends TopComponent implements DataResult, * to */ public DataResultTopComponent(String name, String mode, DataContentTopComponent customContentViewer) { - this(false, name); + super(); + this.customModeName = mode; + + customizeComponent(isMain, name);; //custom content viewer tc to setup for every result viewer - this.customContentViewer = customContentViewer; - this.customModeName = mode; + dataResultPanel = new DataResultPanel(name, customContentViewer); + } - private static class UpdateWrapper { + private void customizeComponent(boolean isMain, String title) { + this.isMain = isMain; + this.customModeName = null; - private DataResultViewer wrapped; - private boolean outdated; + setToolTipText(NbBundle.getMessage(DataResultTopComponent.class, "HINT_NodeTableTopComponent")); - UpdateWrapper(DataResultViewer wrapped) { - this.wrapped = wrapped; - this.outdated = true; - } + setTitle(title); // set the title - void setNode(Node selectedNode) { - this.wrapped.setNode(selectedNode); - this.outdated = false; - } + putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.valueOf(isMain)); // set option to close compoment in GUI + putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, true); + putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, true); - void resetComponent() { - this.wrapped.resetComponent(); - this.outdated = true; - } - - void clearComponent() { - this.wrapped.clearComponent(); - this.outdated = true; - } - - boolean isOutdated() { - return this.outdated; - } - - void setSelectedNodes(Node[] selected) { - this.wrapped.setSelectedNodes(selected); - } - - boolean isSupported(Node selectedNode) { - return this.wrapped.isSupported(selectedNode); - } - - void setContentViewer(DataContent contentViewer) { - this.wrapped.setContentViewer(contentViewer); - } } private static void createInstanceCommon(String pathText, Node givenNode, int totalMatches, DataResultTopComponent newDataResult) { - newDataResult.numberMatchLabel.setText(Integer.toString(totalMatches)); + newDataResult.setNumMatches(totalMatches); newDataResult.open(); // open it first so the component can be initialized @@ -195,46 +154,18 @@ public class DataResultTopComponent extends TopComponent implements DataResult, // //GEN-BEGIN:initComponents private void initComponents() { - directoryTablePath = new javax.swing.JLabel(); - matchLabel = new javax.swing.JLabel(); - numberMatchLabel = new javax.swing.JLabel(); - dataResultTabbedPanel = new javax.swing.JTabbedPane(); - - org.openide.awt.Mnemonics.setLocalizedText(directoryTablePath, org.openide.util.NbBundle.getMessage(DataResultTopComponent.class, "DataResultTopComponent.directoryTablePath.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(matchLabel, org.openide.util.NbBundle.getMessage(DataResultTopComponent.class, "DataResultTopComponent.matchLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(numberMatchLabel, org.openide.util.NbBundle.getMessage(DataResultTopComponent.class, "DataResultTopComponent.numberMatchLabel.text")); // NOI18N - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(directoryTablePath) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 855, Short.MAX_VALUE) - .addComponent(numberMatchLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(matchLabel)) - .addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 967, Short.MAX_VALUE) + .addGap(0, 967, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(matchLabel) - .addComponent(numberMatchLabel)) - .addComponent(directoryTablePath)) - .addGap(0, 0, 0) - .addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 565, Short.MAX_VALUE)) + .addGap(0, 579, Short.MAX_VALUE) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JTabbedPane dataResultTabbedPanel; - private javax.swing.JLabel directoryTablePath; - private javax.swing.JLabel matchLabel; - private javax.swing.JLabel numberMatchLabel; // End of variables declaration//GEN-END:variables @Override @@ -273,86 +204,30 @@ public class DataResultTopComponent extends TopComponent implements DataResult, @Override public void componentOpened() { - // Add all the DataContentViewer to the tabbed pannel. - // (Only when the it's opened at the first time: tabCount = 0) - int totalTabs = this.dataResultTabbedPanel.getTabCount(); - if (totalTabs == 0) { - // find all dataContentViewer and add them to the tabbed pane - for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { - DataResultViewer drv = factory.getInstance(); - UpdateWrapper resultViewer = new UpdateWrapper(drv); - if (customContentViewer != null) { - //set custom content viewer to respond to events from this result viewer - resultViewer.setContentViewer(customContentViewer); - } - this.viewers.add(resultViewer); - this.dataResultTabbedPanel.addTab(drv.getTitle(), drv.getComponent()); - - } - } - - if (this.preferredID().equals(DataResultTopComponent.DEFAULT_PREFERRED_ID)) { - // if no node selected on DataExplorer, clear the field - if (rootNode == null) { - setNode(rootNode); - } - } - - - - + this.dataResultPanel.componentOpened(); } @Override public void componentClosed() { - pcs.firePropertyChange(REMOVE_FILESEARCH, "", this); // notify to remove this from the menu - - // try to remove any references to this class - PropertyChangeListener[] pcl = pcs.getPropertyChangeListeners(); - for (int i = 0; i < pcl.length; i++) { - pcs.removePropertyChangeListener(pcl[i]); - } - - // clear all set nodes - for (UpdateWrapper drv : this.viewers) { - drv.setNode(null); - } - - if (!this.isMain) { - for (UpdateWrapper drv : this.viewers) { - drv.clearComponent(); - } - this.directoryTablePath.removeAll(); - this.directoryTablePath = null; - this.matchLabel.removeAll(); - this.matchLabel = null; - this.numberMatchLabel.removeAll(); - this.numberMatchLabel = null; - this.setLayout(null); - this.pcs = null; - this.removeAll(); - } - + dataResultPanel.componentClosed(); } @Override protected String preferredID() { - if (this.isMain) { - return DEFAULT_PREFERRED_ID; - } else { - return this.getName(); - } + + return this.getName(); + } - @Override - public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { - this.pcs.addPropertyChangeListener(listener); - } - - @Override - public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { - this.pcs.removePropertyChangeListener(listener); - } +// @Override +// public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { +// dataResultPanel.addPropertyChangeListener(listener); +// } +// +// @Override +// public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { +// dataResultPanel.removePropertyChangeListener(listener); +// } @Override public String getPreferredID() { @@ -361,35 +236,7 @@ public class DataResultTopComponent extends TopComponent implements DataResult, @Override public void setNode(Node selectedNode) { - this.rootNode = selectedNode; - if (selectedNode != null) { - int childrenCount = selectedNode.getChildren().getNodesCount(true); - this.numberMatchLabel.setText(Integer.toString(childrenCount)); - } - - this.numberMatchLabel.setVisible(true); - this.matchLabel.setVisible(true); - - resetTabs(selectedNode); - - //update/disable tabs based on if supported for this node - int drvC = 0; - for (UpdateWrapper drv : viewers) { - - if (drv.isSupported(selectedNode)) { - dataResultTabbedPanel.setEnabledAt(drvC, true); - } else { - dataResultTabbedPanel.setEnabledAt(drvC, false); - } - ++drvC; - } - - // set the display on the current active tab - int currentActiveTab = this.dataResultTabbedPanel.getSelectedIndex(); - if (currentActiveTab != -1) { - UpdateWrapper drv = viewers.get(currentActiveTab); - drv.setNode(selectedNode); - } + dataResultPanel.setNode(selectedNode); } @Override @@ -399,12 +246,12 @@ public class DataResultTopComponent extends TopComponent implements DataResult, @Override public void setPath(String pathText) { - this.directoryTablePath.setText(pathText); + dataResultPanel.setPath(pathText); } @Override public boolean isMain() { - return this.isMain; + return isMain; } @Override @@ -412,26 +259,6 @@ public class DataResultTopComponent extends TopComponent implements DataResult, return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case } - @Override - public void stateChanged(ChangeEvent e) { - JTabbedPane pane = (JTabbedPane) e.getSource(); - - // Get and set current selected tab - int currentTab = pane.getSelectedIndex(); - if (currentTab != -1) { - UpdateWrapper drv = this.viewers.get(currentTab); - if (drv.isOutdated()) { - // change the cursor to "waiting cursor" for this operation - this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - drv.setNode(rootNode); - } finally { - this.setCursor(null); - } - } - } - } - /** * Resets the tabs based on the selected Node. If the selected node is null * or not supported, disable that tab as well. @@ -440,18 +267,18 @@ public class DataResultTopComponent extends TopComponent implements DataResult, */ public void resetTabs(Node selectedNode) { - for (UpdateWrapper drv : this.viewers) { - drv.resetComponent(); - } + dataResultPanel.resetTabs(selectedNode); } public void setSelectedNodes(Node[] selected) { - for (UpdateWrapper drv : this.viewers) { - drv.setSelectedNodes(selected); - } + dataResultPanel.setSelectedNodes(selected); } public Node getRootNode() { - return this.rootNode; + return dataResultPanel.getRootNode(); + } + + void setNumMatches(int matches) { + this.dataResultPanel.setNumMatches(matches); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 606db5bec8..bc45b72d91 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Cursor; import java.awt.FontMetrics; +import java.awt.Graphics; import java.awt.dnd.DnDConstants; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -58,7 +59,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { OutlineView ov = ((OutlineView) this.tableScrollPanel); ov.setAllowedDragActions(DnDConstants.ACTION_NONE); - ov.setAllowedDropActions(DnDConstants.ACTION_NONE ); + ov.setAllowedDropActions(DnDConstants.ACTION_NONE); // only allow one item to be selected at a time ov.getOutline().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -85,10 +86,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public void nodeSelected(Node selectedNode) { - } - - /** * This method is called from within the constructor to initialize the form. @@ -246,7 +244,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { em.setRootContext(root); - OutlineView ov = ((OutlineView) this.tableScrollPanel); + final OutlineView ov = ((OutlineView) this.tableScrollPanel); propertiesAcc.clear(); @@ -296,9 +294,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { int startColumn = 1; ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - // get the fontmetrics - //FontMetrics metrics = ttv.getGraphics().getFontMetrics(); - FontMetrics metrics = ov.getGraphics().getFontMetrics(); + // get first 100 rows values for the table Object[][] content = null; @@ -306,6 +302,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (content != null) { + // get the fontmetrics + final Graphics graphics = ov.getGraphics(); + final FontMetrics metrics = graphics.getFontMetrics(); + // for the "Name" column int nodeColWidth = Math.min(getMaxColumnWidth(0, metrics, margin, 40, firstColumnLabel, content), 250); // Note: 40 is the width of the icon + node lines. Change this value if those values change! ov.getOutline().getColumnModel().getColumn(0).setPreferredWidth(nodeColWidth); @@ -324,10 +324,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } else { + final OutlineView ov = ((OutlineView) this.tableScrollPanel); Node emptyNode = new AbstractNode(Children.LEAF); em.setRootContext(emptyNode); // make empty node - ((OutlineView) this.tableScrollPanel).getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - ((OutlineView) this.tableScrollPanel).setPropertyColumns(); // set the empty property header + ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + ov.setPropertyColumns(); // set the empty property header } } finally { this.setCursor(null); @@ -436,6 +437,4 @@ public class DataResultViewerTable extends AbstractDataResultViewer { super.clearComponent(); } - - } diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index 68b89014e9..d68eb7bab4 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -32,10 +32,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -50,6 +48,7 @@ import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.windows.TopComponent; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; @@ -80,7 +79,7 @@ public class FileSearchPanel extends javax.swing.JPanel { Object newValue = evt.getNewValue(); // if the one of the "FileSearchResult" window is closed - if (changed.equals(DataResultTopComponent.REMOVE_FILESEARCH)) { + if (changed.equals(DataResultPanel.REMOVE_FILESEARCH)) { searchResults.remove((DataResultTopComponent) newValue); } } diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchTopComponent.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchTopComponent.java index dfab9f87cb..edcf8f1b12 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchTopComponent.java @@ -29,7 +29,6 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -48,6 +47,7 @@ import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer; +import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; @@ -285,7 +285,7 @@ public final class FileSearchTopComponent extends TopComponent implements DataEx Object newValue = evt.getNewValue(); // if the one of the "FileSearchResult" window is closed - if (changed.equals(DataResultTopComponent.REMOVE_FILESEARCH)) { + if (changed.equals(DataResultPanel.REMOVE_FILESEARCH)) { searchResults.remove((DataResultTopComponent) newValue); }