19 package org.sleuthkit.autopsy.corecomponents;
 
   21 import java.awt.Cursor;
 
   22 import java.awt.FontMetrics;
 
   23 import java.awt.Graphics;
 
   24 import java.awt.dnd.DnDConstants;
 
   25 import java.awt.event.MouseEvent;
 
   26 import java.awt.event.MouseListener;
 
   27 import java.beans.PropertyChangeEvent;
 
   28 import java.lang.reflect.InvocationTargetException;
 
   29 import java.util.ArrayList;
 
   30 import java.util.LinkedHashSet;
 
   31 import java.util.List;
 
   33 import javax.swing.Action;
 
   34 import javax.swing.JTable;
 
   35 import javax.swing.ListSelectionModel;
 
   36 import javax.swing.SwingUtilities;
 
   37 import org.netbeans.swing.outline.DefaultOutlineModel;
 
   38 import org.openide.explorer.ExplorerManager;
 
   39 import org.openide.explorer.view.OutlineView;
 
   40 import org.openide.nodes.AbstractNode;
 
   41 import org.openide.nodes.Children;
 
   42 import org.openide.nodes.Node;
 
   43 import org.openide.nodes.Node.Property;
 
   44 import org.openide.nodes.Node.PropertySet;
 
   45 import org.openide.nodes.NodeEvent;
 
   46 import org.openide.nodes.NodeListener;
 
   47 import org.openide.nodes.NodeMemberEvent;
 
   48 import org.openide.nodes.NodeReorderEvent;
 
   49 import org.openide.nodes.Sheet;
 
   50 import org.openide.util.NbBundle;
 
   73         super(explorerManager);
 
   89         ov.setAllowedDragActions(DnDConstants.ACTION_NONE);
 
   91         ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 
   94         ov.getOutline().setRootVisible(
false);
 
   95         ov.getOutline().setDragEnabled(
false);
 
  147     @SuppressWarnings(
"unchecked")
 
  154         tableScrollPanel.addComponentListener(
new java.awt.event.ComponentAdapter() {
 
  155             public void componentResized(java.awt.event.ComponentEvent evt) {
 
  160         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  161         this.setLayout(layout);
 
  162         layout.setHorizontalGroup(
 
  163             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  164             .addComponent(
tableScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 691, Short.MAX_VALUE)
 
  166         layout.setVerticalGroup(
 
  167             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  168             .addComponent(
tableScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 366, Short.MAX_VALUE)
 
  186         Node firstChild = parent.getChildren().getNodeAt(0);
 
  188         if (firstChild == null) {
 
  189             throw new IllegalArgumentException(
 
  190                     NbBundle.getMessage(
this.getClass(), 
"DataResultViewerTable.illegalArgExc.noChildFromParent"));
 
  192             for (PropertySet ps : firstChild.getPropertySets()) {
 
  193                 if (ps.getName().equals(Sheet.PROPERTIES)) {
 
  194                     return ps.getProperties();
 
  198             throw new IllegalArgumentException(
 
  199                     NbBundle.getMessage(
this.getClass(), 
"DataResultViewerTable.illegalArgExc.childWithoutPropertySet"));
 
  212     @SuppressWarnings(
"rawtypes")
 
  214         Node firstChild = parent.getChildren().getNodeAt(0);
 
  216         Property[] properties = null;
 
  218         if (firstChild == null) {
 
  219             throw new IllegalArgumentException(
 
  220                     NbBundle.getMessage(
this.getClass(), 
"DataResultViewerTable.illegalArgExc.noChildFromParent"));
 
  222             Set<Property> allProperties = 
new LinkedHashSet<>();
 
  223             while (firstChild != null) {
 
  224                 for (PropertySet ps : firstChild.getPropertySets()) {
 
  225                     final Property[] props = ps.getProperties();
 
  226                     final int propsNum = props.length;
 
  227                     for (
int i = 0; i < propsNum; ++i) {
 
  228                         allProperties.add(props[i]);
 
  231                 firstChild = firstChild.getChildren().getNodeAt(0);
 
  234             properties = allProperties.toArray(
new Property<?>[0]);
 
  250         Children children = parent.getChildren();
 
  252         for (Node child : children.getNodes()) {
 
  253             if (++childCount > rows) {
 
  256             for (PropertySet ps : child.getPropertySets()) {
 
  257                 final Property<?>[] props = ps.getProperties();
 
  258                 final int propsNum = props.length;
 
  259                 for (
int j = 0; j < propsNum; ++j) {
 
  260                     propertiesAcc.add(props[j]);
 
  281         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  283             boolean hasChildren = 
false;
 
  285             if (selectedNode != null) {
 
  287                 hasChildren = selectedNode.getChildren().getNodesCount() > 0;
 
  290             Node oldNode = this.em.getRootContext();
 
  291             if (oldNode != null) {
 
  292                 oldNode.removeNodeListener(dummyNodeListener);
 
  297                 Node root = selectedNode;
 
  298                 dummyNodeListener.
reset();
 
  299                 root.addNodeListener(dummyNodeListener);
 
  303                 Node emptyNode = 
new AbstractNode(Children.LEAF);
 
  304                 em.setRootContext(emptyNode); 
 
  305                 ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
 
  306                 ov.setPropertyColumns(); 
 
  309             this.setCursor(null);
 
  321         em.setRootContext(root);
 
  339         propertiesAcc.clear();
 
  341         List<Node.Property<?>> props = 
new ArrayList<>(
propertiesAcc);
 
  354         if (props.size() > 0) {
 
  355             Node.Property<?> prop = props.remove(0);
 
  356             ((DefaultOutlineModel) ov.getOutline().getOutlineModel()).setNodesColumnLabel(prop.getDisplayName());
 
  360         String[] propStrings = 
new String[props.size() * 2];
 
  361         for (
int i = 0; i < props.size(); i++) {
 
  362             props.get(i).setValue(
"ComparableColumnTTV", Boolean.TRUE); 
 
  365                 props.get(i).setValue(
"TreeColumnTTV", Boolean.TRUE); 
 
  366                 props.get(i).setValue(
"SortingColumnTTV", Boolean.TRUE); 
 
  368             propStrings[2 * i] = props.get(i).getName();
 
  369             propStrings[2 * i + 1] = props.get(i).getDisplayName();
 
  372         ov.setPropertyColumns(propStrings);
 
  375         int totalColumns = props.size();
 
  383         ov.getOutline().setAutoResizeMode((props.size() > 0) ? JTable.AUTO_RESIZE_OFF : JTable.AUTO_RESIZE_ALL_COLUMNS);
 
  389         if (content != null) {
 
  391             final Graphics graphics = ov.getGraphics();
 
  392             if (graphics != null) {
 
  393                 final FontMetrics metrics = graphics.getFontMetrics();
 
  396                 int nodeColWidth = Math.min(
getMaxColumnWidth(0, metrics, margin, 40, firstColumnLabel, content), 250); 
 
  397                 ov.getOutline().getColumnModel().getColumn(0).setPreferredWidth(nodeColWidth);
 
  400                 for (
int colIndex = startColumn; colIndex <= totalColumns; colIndex++) {
 
  401                     int colWidth = Math.min(
getMaxColumnWidth(colIndex, metrics, margin, 8, props, content), 350);
 
  402                     ov.getOutline().getColumnModel().getColumn(colIndex).setPreferredWidth(colWidth);
 
  407             if (content.length <= 0) {
 
  409                 ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
 
  481         int numRows = Math.min(maxRows, node.getChildren().getNodesCount());
 
  482         Object[][] rowValues = 
new Object[numRows][];
 
  484         for (Node child : node.getChildren().getNodes()) {
 
  485             if (rowCount >= maxRows) {
 
  493             if (rowCount > numRows) {
 
  496             PropertySet[] propertySets = child.getPropertySets();
 
  497             if (propertySets.length > 0) {
 
  498                 Property<?>[] properties = propertySets[0].getProperties();
 
  499                 rowValues[rowCount] = 
new Object[properties.length];
 
  500                 for (
int j = 0; j < properties.length; ++j) {
 
  502                         rowValues[rowCount][j] = properties[j].getValue();
 
  503                     } 
catch (IllegalAccessException | InvocationTargetException ignore) {
 
  504                         rowValues[rowCount][j] = 
"n/a"; 
 
  515         return NbBundle.getMessage(this.getClass(), 
"DataResultViewerTable.title");
 
  535     @SuppressWarnings(
"rawtypes")
 
  536     private 
int getMaxColumnWidth(
int index, FontMetrics metrics, 
int margin, 
int padding, List<Node.Property<?>> header, Object[][] table) {
 
  538         String headerName = header.get(index - 1).getDisplayName();
 
  555     private synchronized int getMaxColumnWidth(
int index, FontMetrics metrics, 
int margin, 
int padding, String header, Object[][] table) {
 
  557         String headerName = header;
 
  558         int headerWidth = metrics.stringWidth(headerName); 
 
  562         for (
int i = 0; i < table.length; i++) {
 
  563             if (table[i] == null || index >= table[i].length) {
 
  566             String test = table[i][index].toString();
 
  567             colWidth = Math.max(colWidth, metrics.stringWidth(test));
 
  574         int width = Math.max(headerWidth, colWidth);
 
  585         super.clearComponent();
 
  590         private volatile boolean load = 
true;
 
  598             Node[] delta = nme.getDelta();
 
  601                 if (SwingUtilities.isEventDispatchThread()) {
 
  604                     SwingUtilities.invokeLater(
new Runnable() {
 
  615             for (Node n : delta) {
 
  616                 if (!n.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) {
 
Set< Property<?> > propertiesAcc
void childrenReordered(NodeReorderEvent nre)
final DummyNodeListener dummyNodeListener
void getAllChildPropertyHeadersRec(Node parent, int rows)
void propertyChange(PropertyChangeEvent evt)
void tableScrollPanelComponentResized(java.awt.event.ComponentEvent evt)
int getMaxColumnWidth(int index, FontMetrics metrics, int margin, int padding, List< Node.Property<?>> header, Object[][] table)
boolean isSupported(Node selectedNode)
DataResultViewer createInstance()
void childrenRemoved(NodeMemberEvent nme)
void nodeDestroyed(NodeEvent ne)
static Object[][] getRowValues(Node node, int maxRows)
boolean containsReal(Node[] delta)
synchronized int getMaxColumnWidth(int index, FontMetrics metrics, int margin, int padding, String header, Object[][] table)
void childrenAdded(final NodeMemberEvent nme)
void setNode(Node selectedNode)
Node.Property<?>[] getChildPropertyHeaders(Node parent)
Node.Property[] getAllChildPropertyHeaders(Node parent)
static final String DUMMY_NODE_DISPLAY_NAME
DataResultViewerTable(ExplorerManager explorerManager)
void setupTable(final Node root)
javax.swing.JScrollPane tableScrollPanel