From 401ea719e97ea9e69954d5861952c17aa7989502 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Jun 2017 13:08:03 -0400 Subject: [PATCH 1/2] 2780 multi line support for Results Content Viewer table --- .../DataContentViewerArtifact.java | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 8ad63473d4..5b6d06ce72 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -52,8 +52,8 @@ import org.netbeans.swing.etable.ETable; /** * Instances of this class display the BlackboardArtifacts associated with the - * Content represented by a Node. Each BlackboardArtifact is rendered displayed in a JTable - * representation of its BlackboardAttributes. + * Content represented by a Node. Each BlackboardArtifact is rendered displayed + * in a JTable representation of its BlackboardAttributes. */ @ServiceProvider(service = DataContentViewer.class, position = 3) public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer { @@ -85,6 +85,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat resultsTableScrollPane.setViewportView(resultsTable); customizeComponents(); resetComponents(); + resultsTable.setDefaultRenderer(Object.class, new MultiLineTableCellRenderer()); } private void initResultsTable() { @@ -96,15 +97,37 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat return false; } }); + resultsTable.setCellSelectionEnabled(true); resultsTable.getTableHeader().setReorderingAllowed(false); resultsTable.setColumnHidingAllowed(false); resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); - updateColumnSizes(); + resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); + } + /** + * Sets the row heights to the heights of the content in their Value column. + */ + private void updateRowHeights() { + int valueColIndex = -1; + for (int col = 0; col < resultsTable.getColumnCount(); col++) { + if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) { + valueColIndex = col; + } + } + if (valueColIndex != -1) { + for (int row = 0; row < resultsTable.getRowCount(); row++) { + int rowHeight = resultsTable.prepareRenderer(resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex).getPreferredSize().height; + resultsTable.setRowHeight(row, rowHeight); + } + } + } + + /** + * Update the column widths so that the Value column has most of the space. + */ private void updateColumnSizes() { - resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); Enumeration columns = resultsTable.getColumnModel().getColumns(); while (columns.hasMoreElements()) { TableColumn col = columns.nextElement(); @@ -551,6 +574,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS); updateColumnSizes(); + updateRowHeights(); resultsTable.clearSelection(); this.setCursor(null); @@ -568,6 +592,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); tModel.setDataVector(waitRow, COLUMN_HEADERS); updateColumnSizes(); + updateRowHeights(); resultsTable.clearSelection(); // The output of the previous task is no longer relevant. if (currentTask != null) { @@ -758,4 +783,26 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } } } + + /** + * TableCellRenderer for displaying multiline text which reflects the line + * breaks included in the text when displayed. + */ + private class MultiLineTableCellRenderer extends javax.swing.JList implements javax.swing.table.TableCellRenderer { + + @Override + public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value instanceof String) { + String[] data = ((String) value).split("\\r?\\n|\\r"); //split on all line breaks to support multi-line viewing + setListData(data); + } + //cell backgroud color when selected + if (isSelected) { + setBackground(javax.swing.UIManager.getColor("Table.selectionBackground")); + } else { + setBackground(javax.swing.UIManager.getColor("Table.background")); + } + return this; + } + } } From 443b3edad08e4aed97b59f358bd68be8f45e06c6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 27 Jun 2017 13:29:06 -0400 Subject: [PATCH 2/2] 2780 - allows for word wrap in table cells with long lined content --- .../DataContentViewerArtifact.java | 68 ++++++++++++++++--- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 5b6d06ce72..2c9fa00b0d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -32,8 +32,14 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JMenuItem; import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.TableColumnModelEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; +import javax.swing.event.TableColumnModelListener; +import javax.swing.text.JTextComponent; +import javax.swing.text.View; import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.Lookup; @@ -78,6 +84,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat Bundle.DataContentViewerArtifact_attrsTableHeader_value(), Bundle.DataContentViewerArtifact_attrsTableHeader_sources()}; private static final int[] COLUMN_WIDTHS = {100, 800, 100}; + private static final int CELL_BOTTOM_MARGIN = 5; public DataContentViewerArtifact() { initResultsTable(); @@ -97,11 +104,34 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat return false; } }); - resultsTable.setCellSelectionEnabled(true); resultsTable.getTableHeader().setReorderingAllowed(false); resultsTable.setColumnHidingAllowed(false); resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); + resultsTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() { + + @Override + public void columnAdded(TableColumnModelEvent e) { + } + + @Override + public void columnRemoved(TableColumnModelEvent e) { + } + + @Override + public void columnMoved(TableColumnModelEvent e) { + + } + + @Override + public void columnMarginChanged(ChangeEvent e) { + updateRowHeights(); //When the user changes column width we may need to resize row height + } + + @Override + public void columnSelectionChanged(ListSelectionEvent e) { + } + }); resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); } @@ -118,8 +148,23 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } if (valueColIndex != -1) { for (int row = 0; row < resultsTable.getRowCount(); row++) { - int rowHeight = resultsTable.prepareRenderer(resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex).getPreferredSize().height; - resultsTable.setRowHeight(row, rowHeight); + Component comp = resultsTable.prepareRenderer( + resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex); + final int rowHeight; + if (comp instanceof JTextComponent) { + final JTextComponent tc = (JTextComponent) comp; + final View rootView = tc.getUI().getRootView(tc); + java.awt.Insets i = tc.getInsets(null); + rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex) + .getPreferredWidth() - i.left - i.right, + Integer.MAX_VALUE); + rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS); + } else { + rowHeight = comp.getPreferredSize().height; + } + if (rowHeight > 0) { + resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN); + } } } } @@ -785,24 +830,25 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } /** - * TableCellRenderer for displaying multiline text which reflects the line - * breaks included in the text when displayed. + * TableCellRenderer for displaying multiline text. */ - private class MultiLineTableCellRenderer extends javax.swing.JList implements javax.swing.table.TableCellRenderer { + private class MultiLineTableCellRenderer implements javax.swing.table.TableCellRenderer { @Override public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + javax.swing.JTextArea jtex = new javax.swing.JTextArea(); if (value instanceof String) { - String[] data = ((String) value).split("\\r?\\n|\\r"); //split on all line breaks to support multi-line viewing - setListData(data); + jtex.setText((String) value); + jtex.setLineWrap(true); + jtex.setWrapStyleWord(true); } //cell backgroud color when selected if (isSelected) { - setBackground(javax.swing.UIManager.getColor("Table.selectionBackground")); + jtex.setBackground(javax.swing.UIManager.getColor("Table.selectionBackground")); } else { - setBackground(javax.swing.UIManager.getColor("Table.background")); + jtex.setBackground(javax.swing.UIManager.getColor("Table.background")); } - return this; + return jtex; } } }