From e0d4971e4d84ef4bf696e78490db252b9018ef11 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Wed, 31 May 2017 15:35:34 +0200 Subject: [PATCH 1/3] persist hidden columns first pass --- .../corecomponents/DataResultViewerTable.java | 142 +++++++++++++++--- 1 file changed, 117 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index c6ce3485e5..5366426a54 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -30,6 +30,7 @@ import java.beans.PropertyVetoException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; @@ -37,6 +38,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.prefs.Preferences; import java.util.stream.Stream; @@ -48,11 +50,15 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import org.netbeans.swing.etable.ETableColumn; +import org.netbeans.swing.etable.ETableColumnModel; +import org.netbeans.swing.etable.TableColumnSelector; import org.netbeans.swing.outline.DefaultOutlineCellRenderer; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; +import org.netbeans.swing.outline.OutlineModel; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; import org.openide.nodes.AbstractNode; @@ -105,6 +111,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * Convience reference to internal Outline. */ private Outline outline; + private TableListener tableListener; /** * Creates a DataResultViewerTable object that is compatible with node @@ -137,7 +144,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { outline.setDefaultRenderer(Object.class, new ColorTagCustomRenderer()); // add a listener so that when columns are moved, the new order is stored - TableListener tableListener = new TableListener(); + tableListener = new TableListener(); outline.getColumnModel().addColumnModelListener(tableListener); // the listener also moves columns back if user tries to move the first column out of place outline.getTableHeader().addMouseListener(tableListener); @@ -236,7 +243,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (oldNode != null) { oldNode.removeNodeListener(pleasewaitNodeListener); } - + tableListener.setInitializationMode(true); if (hasChildren) { currentRoot = selectedNode; pleasewaitNodeListener.reset(); @@ -250,6 +257,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { outlineView.setPropertyColumns(); // set the empty property header } } finally { + tableListener.setInitializationMode(false); this.setCursor(null); } } @@ -259,6 +267,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * the table. */ private void setupTable() { + /** * OutlineView makes the first column be the result of * node.getDisplayName with the icon. This duplicates our first column, @@ -286,30 +295,32 @@ public class DataResultViewerTable extends AbstractDataResultViewer { assignColumns(props); setColumnWidths(); loadColumnSorting(); + loadColumnVisibility(); /** * If one of the child nodes of the root node is to be selected, select * it. */ - SwingUtilities.invokeLater(()->{ - if (currentRoot instanceof TableFilterNode) { - NodeSelectionInfo selectedChildInfo = ((TableFilterNode) currentRoot).getChildNodeSelectionInfo(); - if (null != selectedChildInfo) { - Node[] childNodes = currentRoot.getChildren().getNodes(true); - for (int i = 0; i < childNodes.length; ++i) { - Node childNode = childNodes[i]; - if (selectedChildInfo.matches(childNode)) { - try { - em.setSelectedNodes(new Node[]{childNode}); - } catch (PropertyVetoException ex) { - logger.log(Level.SEVERE, "Failed to select node specified by selected child info", ex); + SwingUtilities.invokeLater(() -> { + if (currentRoot instanceof TableFilterNode) { + NodeSelectionInfo selectedChildInfo = ((TableFilterNode) currentRoot).getChildNodeSelectionInfo(); + if (null != selectedChildInfo) { + Node[] childNodes = currentRoot.getChildren().getNodes(true); + for (int i = 0; i < childNodes.length; ++i) { + Node childNode = childNodes[i]; + if (selectedChildInfo.matches(childNode)) { + try { + em.setSelectedNodes(new Node[]{childNode}); + } catch (PropertyVetoException ex) { + logger.log(Level.SEVERE, "Failed to select node specified by selected child info", ex); + } + break; } - break; } + ((TableFilterNode) currentRoot).setChildNodeSelectionInfo(null); } - ((TableFilterNode) currentRoot).setChildNodeSelectionInfo(null); } - }}); + }); } private void setColumnWidths() { @@ -367,6 +378,41 @@ public class DataResultViewerTable extends AbstractDataResultViewer { outlineView.setPropertyColumns(propStrings); } + private synchronized void storeColumnVisibility() { + if (currentRoot == null || propertiesMap.isEmpty()) { + return; + } + if (currentRoot instanceof TableFilterNode) { + TableFilterNode tfn = (TableFilterNode) currentRoot; + final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); + + final ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); + final OutlineModel outlineModel = outline.getOutlineModel(); + + //store the sorting information + int numCols = outlineModel.getColumnCount(); + for (TableColumn tc : Collections.list(columnModel.getColumns())) { + ETableColumn etc = (ETableColumn) tc; + System.out.println(tc.getModelIndex() + etc.getIdentifier().toString()); + } + + for (int i = 0; i < numCols; i++) { + ETableColumn etc = (ETableColumn) columnModel.getColumn(i); + + String columnName = outline.getColumnName(i); + + //store hidden state + boolean columnHidden = columnModel.isColumnHidden(etc); + if (columnHidden) { + preferences.putBoolean(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName), columnHidden); + } else { + preferences.remove(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName)); + } + + } + } + } + /** * Store the current column order and sort information into a preference * file. @@ -380,23 +426,35 @@ public class DataResultViewerTable extends AbstractDataResultViewer { final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); // Store the current order of the columns into settings for (Map.Entry> entry : propertiesMap.entrySet()) { - preferences.put(getColumnPositionKey(tfn.getColumnOrderKey(), entry.getValue().getName()), String.valueOf(entry.getKey())); } - final TableColumnModel columnModel = outline.getColumnModel(); + final ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); //store the sorting information int numCols = columnModel.getColumnCount(); for (int i = 0; i < numCols; i++) { ETableColumn etc = (ETableColumn) columnModel.getColumn(i); + String columnName = outline.getColumnName(i); + //store sort rank and order + final String columnSortOrderKey = getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName); + final String columnSortRankKey = getColumnSortRankKey(tfn.getColumnOrderKey(), columnName); if (etc.isSorted()) { - preferences.put(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.isAscending())); - preferences.put(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.getSortRank())); + preferences.putBoolean(columnSortOrderKey, etc.isAscending()); + preferences.putInt(columnSortRankKey, etc.getSortRank()); } else { - preferences.remove(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName)); - preferences.remove(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName)); + preferences.remove(columnSortOrderKey); + preferences.remove(columnSortRankKey); } + + //store hidden state + boolean columnHidden = columnModel.isColumnHidden(etc); + if (columnHidden) { + preferences.putBoolean(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName), columnHidden); + } else { + preferences.remove(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName)); + } + } } } @@ -433,6 +491,24 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } + private synchronized void loadColumnVisibility() { + if (currentRoot == null || propertiesMap.isEmpty()) { + return; + } + + if (currentRoot instanceof TableFilterNode) { + final String columnKey = ((TableFilterNode) currentRoot).getColumnOrderKey(); + final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); + + ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); + propertiesMap.entrySet().stream().forEach(entry -> { + final String propName = entry.getValue().getName(); + boolean hidden = preferences.getBoolean(getColumnHiddenKey(columnKey, propName), false); + columnModel.setColumnHidden(columnModel.getColumn(entry.getKey()), hidden); + }); + } + } + /** * Gets a list of child properties (columns) in the order persisted in the * preference file. Also initialized the propertiesMap with the column @@ -513,7 +589,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * * @return A generated key for the preference file */ - private String getColumnSortOrderKey(String keyBase, String propName) { + static private String getColumnSortOrderKey(String keyBase, String propName) { return getColumnKeyBase(keyBase, propName) + ".sortOrder"; } @@ -527,10 +603,14 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * * @return A generated key for the preference file */ - private String getColumnSortRankKey(String keyBase, String propName) { + static private String getColumnSortRankKey(String keyBase, String propName) { return getColumnKeyBase(keyBase, propName) + ".sortRank"; } + static private String getColumnHiddenKey(String keyBase, String propName) { + return getColumnKeyBase(keyBase, propName) + ".hidden"; + } + private static String getColumnKeyBase(String keyBase, String propName) { return stripNonAlphanumeric(keyBase) + "." + stripNonAlphanumeric(propName); } @@ -589,6 +669,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { // the column started and where it ended up. private int startColumnIndex = -1; private int endColumnIndex = -1; + private boolean initMode; @Override public void columnMoved(TableColumnModelEvent e) { @@ -669,10 +750,16 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public void columnAdded(TableColumnModelEvent e) { + if (initMode == false) { + storeColumnVisibility(); + } } @Override public void columnRemoved(TableColumnModelEvent e) { + if (initMode == false) { + storeColumnVisibility(); + } } @Override @@ -681,6 +768,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public void columnSelectionChanged(ListSelectionEvent e) { + System.out.println("selection changed"); + } + + private void setInitializationMode(boolean b) { + this.initMode = b; } } From d1b709addd99e2ad9d35f37470020678495ab042 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 1 Jun 2017 18:29:28 +0200 Subject: [PATCH 2/3] persisting hidden columns works! --- .../corecomponents/DataResultViewerTable.java | 200 ++++++++++++------ 1 file changed, 132 insertions(+), 68 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 5366426a54..773eade780 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -30,15 +30,14 @@ import java.beans.PropertyVetoException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -import java.util.function.Consumer; import java.util.logging.Level; import java.util.prefs.Preferences; import java.util.stream.Stream; @@ -54,11 +53,9 @@ import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; -import org.netbeans.swing.etable.TableColumnSelector; import org.netbeans.swing.outline.DefaultOutlineCellRenderer; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; -import org.netbeans.swing.outline.OutlineModel; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; import org.openide.nodes.AbstractNode; @@ -92,7 +89,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @NbBundle.Messages("DataResultViewerTable.pleasewaitNodeDisplayName=Please Wait...") private static final String PLEASEWAIT_NODE_DISPLAY_NAME = Bundle.DataResultViewerTable_pleasewaitNodeDisplayName(); private static final Color TAGGED_COLOR = new Color(200, 210, 220); - /* + /** * The properties map: * * stored value of column index -> property at that index @@ -102,6 +99,14 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * current table view due to its collection of its children's properties. */ private final Map> propertiesMap = new TreeMap<>(); + + /** + * Stores references to the actual table column objects, keyed by column + * name, so that we can check there visibility later in + * storeColumnVisibility(). + */ + private final Map columnMap = new HashMap<>(); + private final PleasewaitNodeListener pleasewaitNodeListener = new PleasewaitNodeListener(); private Node currentRoot; @@ -111,6 +116,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * Convience reference to internal Outline. */ private Outline outline; + + /** + * Listener for table model event and mouse clicks. + */ private TableListener tableListener; /** @@ -243,7 +252,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (oldNode != null) { oldNode.removeNodeListener(pleasewaitNodeListener); } - tableListener.setInitializationMode(true); + if (hasChildren) { currentRoot = selectedNode; pleasewaitNodeListener.reset(); @@ -254,10 +263,16 @@ public class DataResultViewerTable extends AbstractDataResultViewer { Node emptyNode = new AbstractNode(Children.LEAF); em.setRootContext(emptyNode); // make empty node outlineView.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + + /* + * Since we are modifying the columns, we don't want to listen + * to added/removed events as un-hide/hide. + */ + tableListener.listenToVisibilityChanges(false); outlineView.setPropertyColumns(); // set the empty property header } } finally { - tableListener.setInitializationMode(false); + this.setCursor(null); } } @@ -267,6 +282,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * the table. */ private void setupTable() { + /* + * Since we are modifying the columns, we don't want to listen to + * added/removed events as un-hide/hide, until the table setup is done. + */ + tableListener.listenToVisibilityChanges(false); /** * OutlineView makes the first column be the result of @@ -292,9 +312,22 @@ public class DataResultViewerTable extends AbstractDataResultViewer { */ outline.setAutoResizeMode((props.isEmpty()) ? JTable.AUTO_RESIZE_ALL_COLUMNS : JTable.AUTO_RESIZE_OFF); - assignColumns(props); + assignColumns(props); // assign columns to match the properties setColumnWidths(); + //Load column sorting information from preferences file and apply it to columns. loadColumnSorting(); + /* + * Save references to columns before we deal with their visibility. This + * has to happen after the sorting is applied, be cause that actually + * causes the columns to be recreated. It has to happen before + * loadColumnVisibility so we have referenecs to the columns to pass to + * setColumnHidden. + * + * TODO: what about persisting hidden state of sorted columns? + */ + populateColumnMap(); + + //Load column visibility information from preferences file and apply it to columns. loadColumnVisibility(); /** @@ -321,6 +354,23 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } }); + + //the table setup is done, so any added/removed events can now be treated as un-hide/hide. + tableListener.listenToVisibilityChanges(true); + } + + /* + * Populate the map with references to the column objects for use when + * loading/storing the visibility info. + */ + private void populateColumnMap() { + columnMap.clear(); + TableColumnModel columnModel = outline.getColumnModel(); + for (Map.Entry> entry : propertiesMap.entrySet()) { + final String propName = entry.getValue().getName(); + final ETableColumn column = (ETableColumn) columnModel.getColumn(entry.getKey()); + columnMap.put(propName, column); + } } private void setColumnWidths() { @@ -360,7 +410,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } - private void assignColumns(List> props) { + synchronized private void assignColumns(List> props) { // Get the columns setup with respect to names and sortability String[] propStrings = new String[props.size() * 2]; for (int i = 0; i < props.size(); i++) { @@ -378,6 +428,9 @@ public class DataResultViewerTable extends AbstractDataResultViewer { outlineView.setPropertyColumns(propStrings); } + /** + * Store the current column visibility information into a preference file. + */ private synchronized void storeColumnVisibility() { if (currentRoot == null || propertiesMap.isEmpty()) { return; @@ -385,60 +438,61 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (currentRoot instanceof TableFilterNode) { TableFilterNode tfn = (TableFilterNode) currentRoot; final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); - final ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); - final OutlineModel outlineModel = outline.getOutlineModel(); - //store the sorting information - int numCols = outlineModel.getColumnCount(); - for (TableColumn tc : Collections.list(columnModel.getColumns())) { - ETableColumn etc = (ETableColumn) tc; - System.out.println(tc.getModelIndex() + etc.getIdentifier().toString()); - } + //store hidden state + for (Map.Entry entry : columnMap.entrySet()) { - for (int i = 0; i < numCols; i++) { - ETableColumn etc = (ETableColumn) columnModel.getColumn(i); + String columnName = entry.getKey(); + final String columnHiddenKey = getColumnHiddenKey(tfn.getColumnOrderKey(), columnName); + final TableColumn column = entry.getValue(); - String columnName = outline.getColumnName(i); - - //store hidden state - boolean columnHidden = columnModel.isColumnHidden(etc); + boolean columnHidden = columnModel.isColumnHidden(column); if (columnHidden) { - preferences.putBoolean(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName), columnHidden); + preferences.putBoolean(columnHiddenKey, true); } else { - preferences.remove(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName)); + preferences.remove(columnHiddenKey); } - } } } /** - * Store the current column order and sort information into a preference - * file. + * Store the current column order information into a preference file. */ - private synchronized void storeColumnState() { + private synchronized void storeColumnOrder() { if (currentRoot == null || propertiesMap.isEmpty()) { return; } if (currentRoot instanceof TableFilterNode) { TableFilterNode tfn = (TableFilterNode) currentRoot; final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); + // Store the current order of the columns into settings for (Map.Entry> entry : propertiesMap.entrySet()) { - preferences.put(getColumnPositionKey(tfn.getColumnOrderKey(), entry.getValue().getName()), String.valueOf(entry.getKey())); + preferences.putInt(getColumnPositionKey(tfn.getColumnOrderKey(), entry.getValue().getName()), entry.getKey()); } - final ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); + } + } - //store the sorting information - int numCols = columnModel.getColumnCount(); - for (int i = 0; i < numCols; i++) { - ETableColumn etc = (ETableColumn) columnModel.getColumn(i); + /** + * Store the current column sorting information into a preference file. + */ + private synchronized void storeColumnSorting() { + if (currentRoot == null || propertiesMap.isEmpty()) { + return; + } + if (currentRoot instanceof TableFilterNode) { + final String nodeBaseKey = ((TableFilterNode) currentRoot).getColumnOrderKey(); + final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); + + for (Map.Entry entry : columnMap.entrySet()) { + ETableColumn etc = entry.getValue(); + String columnName = entry.getKey(); - String columnName = outline.getColumnName(i); //store sort rank and order - final String columnSortOrderKey = getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName); - final String columnSortRankKey = getColumnSortRankKey(tfn.getColumnOrderKey(), columnName); + final String columnSortOrderKey = getColumnSortOrderKey(nodeBaseKey, columnName); + final String columnSortRankKey = getColumnSortRankKey(nodeBaseKey, columnName); if (etc.isSorted()) { preferences.putBoolean(columnSortOrderKey, etc.isAscending()); preferences.putInt(columnSortRankKey, etc.getSortRank()); @@ -446,23 +500,15 @@ public class DataResultViewerTable extends AbstractDataResultViewer { preferences.remove(columnSortOrderKey); preferences.remove(columnSortRankKey); } - - //store hidden state - boolean columnHidden = columnModel.isColumnHidden(etc); - if (columnHidden) { - preferences.putBoolean(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName), columnHidden); - } else { - preferences.remove(getColumnHiddenKey(tfn.getColumnOrderKey(), columnName)); - } - } + } } /** * Reads and applies the column sorting information persisted to the * preferences file. Must be called after loadColumnOrder() since it depends - * on propertiesMap being initialized, and before assignColumns since it + * on propertiesMap being initialized, and after assignColumns since it * cannot set the sort on columns that have not been added to the table. */ private synchronized void loadColumnSorting() { @@ -479,9 +525,9 @@ public class DataResultViewerTable extends AbstractDataResultViewer { propertiesMap.entrySet().stream().forEach(entry -> { final String propName = entry.getValue().getName(); //if the sort rank is undefined, it will be defaulted to 0 => unsorted. - Integer sortRank = Integer.valueOf(preferences.get(getColumnSortRankKey(columnKey, propName), "0")); + Integer sortRank = preferences.getInt(getColumnSortRankKey(columnKey, propName), 0); //default to true => ascending - Boolean sortOrder = Boolean.valueOf(preferences.get(getColumnSortOrderKey(columnKey, propName), "true")); + Boolean sortOrder = preferences.getBoolean(getColumnSortOrderKey(columnKey, propName), true); treeSet.add(new ColumnSortInfo(entry.getKey(), sortRank, sortOrder)); }); @@ -497,15 +543,16 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } if (currentRoot instanceof TableFilterNode) { - final String columnKey = ((TableFilterNode) currentRoot).getColumnOrderKey(); final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); + final String nodeBaseKey = ((TableFilterNode) currentRoot).getColumnOrderKey(); ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel(); - propertiesMap.entrySet().stream().forEach(entry -> { + for (Map.Entry> entry : propertiesMap.entrySet()) { final String propName = entry.getValue().getName(); - boolean hidden = preferences.getBoolean(getColumnHiddenKey(columnKey, propName), false); - columnModel.setColumnHidden(columnModel.getColumn(entry.getKey()), hidden); - }); + boolean hidden = preferences.getBoolean(getColumnHiddenKey(nodeBaseKey, propName), false); + final TableColumn column = columnMap.get(propName); + columnModel.setColumnHidden(column, hidden); + } } } @@ -543,7 +590,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); for (Property prop : props) { - Integer value = Integer.valueOf(preferences.get(getColumnPositionKey(columnKey, prop.getName()), "-1")); + Integer value = preferences.getInt(getColumnPositionKey(columnKey, prop.getName()), -1); if (value >= 0 && value < offset && !propertiesMap.containsKey(value)) { propertiesMap.put(value, prop); noPreviousSettings = false; @@ -661,7 +708,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /** * Listens to mouse events and table column events and persists column order - * and sorting changes + * sorting, and visibility changes. */ private class TableListener extends MouseAdapter implements TableColumnModelListener { @@ -669,7 +716,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { // the column started and where it ended up. private int startColumnIndex = -1; private int endColumnIndex = -1; - private boolean initMode; + private boolean listenToVisibilitEvents; @Override public void columnMoved(TableColumnModelEvent e) { @@ -721,7 +768,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { propertiesMap.put(range.get(0), movedProp); } - storeColumnState(); + storeColumnOrder(); } @Override @@ -745,20 +792,29 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public void mouseClicked(MouseEvent e) { - storeColumnState(); + //the user clicked a column header + storeColumnSorting(); } @Override public void columnAdded(TableColumnModelEvent e) { - if (initMode == false) { - storeColumnVisibility(); - } + columnAddedOrRemoved(); } @Override public void columnRemoved(TableColumnModelEvent e) { - if (initMode == false) { - storeColumnVisibility(); + columnAddedOrRemoved(); + } + + /** + * Process a columnAdded or columnRemoved event. If we are listening to + * visibilty events the assumption is that added/removed are really + * unhide/hide. If we are not listening do nothing. + */ + private void columnAddedOrRemoved() { + if (listenToVisibilitEvents) { + SwingUtilities.invokeLater(DataResultViewerTable.this::storeColumnVisibility); + } } @@ -768,11 +824,19 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public void columnSelectionChanged(ListSelectionEvent e) { - System.out.println("selection changed"); } - private void setInitializationMode(boolean b) { - this.initMode = b; + /** + * Set the listener to listen or not to visibility changes. When this is + * true, the listener treats all column added/removed events as + * un-hide/hide, and persists the hidden/visible state to the + * preferences file. When false, the listener treats added/removed as + * added/removed (which it ignores). + * + * @param b + */ + private void listenToVisibilityChanges(boolean b) { + this.listenToVisibilitEvents = b; } } From c57fadb75748cc520f6b4fe2b1b17ca12c71a918 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 2 Jun 2017 12:57:51 +0200 Subject: [PATCH 3/3] formatting and comments --- .../autopsy/corecomponents/DataResultViewerTable.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 773eade780..6e7f05655f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -314,17 +314,17 @@ public class DataResultViewerTable extends AbstractDataResultViewer { assignColumns(props); // assign columns to match the properties setColumnWidths(); + //Load column sorting information from preferences file and apply it to columns. loadColumnSorting(); + /* * Save references to columns before we deal with their visibility. This - * has to happen after the sorting is applied, be cause that actually + * has to happen after the sorting is applied, because that actually * causes the columns to be recreated. It has to happen before * loadColumnVisibility so we have referenecs to the columns to pass to * setColumnHidden. - * - * TODO: what about persisting hidden state of sorted columns? - */ + */ populateColumnMap(); //Load column visibility information from preferences file and apply it to columns. @@ -366,6 +366,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private void populateColumnMap() { columnMap.clear(); TableColumnModel columnModel = outline.getColumnModel(); + //for each property get a reference to the column object from the column model. for (Map.Entry> entry : propertiesMap.entrySet()) { final String propName = entry.getValue().getName(); final ETableColumn column = (ETableColumn) columnModel.getColumn(entry.getKey()); @@ -543,6 +544,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } if (currentRoot instanceof TableFilterNode) { + final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); final String nodeBaseKey = ((TableFilterNode) currentRoot).getColumnOrderKey();