Complete new documentation of core result viewers

This commit is contained in:
Richard Cordovano 2018-04-23 17:11:39 -04:00
parent b188d76cb8
commit 21bb53b223
4 changed files with 262 additions and 245 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-17 Basis Technology Corp.
* Copyright 2012-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,76 +22,117 @@ import java.awt.Component;
import org.openide.nodes.Node;
/**
* Interface for the different viewers that show a set of nodes in the
* DataResult area. AbstractDataResultViewer has default implementations for the
* action handlers.
* An interface for result viewers. A result viewer uses a Swing component to
* provide a view of the application data represented by a given NetBeans node.
* Result viewers typically appear in a result view (a DataResultTopComponent)
* docked into the upper right hand side of the main application window.
*
* Typically, a result viewer is a JPanel that displays the child nodes of the
* given node using a NetBeans explorer view as a child component. Such a result
* viewer should use the explorer manager of the ancestor top component to
* connect the lookups of the nodes displayed in the NetBeans explorer view to
* the actions global context. It is strongly recommended that this type of
* result viewer extends the abstract base class AbstractDataResultViewer, which
* will handle some key aspects of working with the ancestor top component's
* explorer manager.
*
* This interface is an extension point, so classes that implement it should
* provide an appropriate ServiceProvider annotation.
*
*/
public interface DataResultViewer {
/**
* Set the root node to display in this viewer. When called with null, must
* clear all references to previous nodes.
*/
public void setNode(Node selectedNode);
/**
* Gets the title of this viewer
*/
public String getTitle();
/**
* Get a new instance of DataResultViewer
* Creates a new instance of this result viewer, which allows the
* application to use the capability provided by this result viewer in more
* than one result view. This is done by using the default instance of this
* result viewer as a "factory" for creating other instances.
*/
public DataResultViewer createInstance();
/**
* Get the Swing component (i.e. JPanel) for this viewer
* Indicates whether this result viewer is able to provide a meaningful view
* of the application data represented by a given node. Typically, indicates
* whether or not this result viewer can use the given node as the root node
* of its child explorer view component.
*
* @param node The node.
*
* @return True or false.
*/
public boolean isSupported(Node node);
/**
* Sets the node for which this result viewer should provide a view of the
* underlying application data. Typically, this means using the given node
* as the root node of this result viewer's child explorer view component.
*
* @param node The node, may be null. If null, the call to this method is
* equivalent to a call to resetComponent.
*/
public void setNode(Node node);
/**
* Requests selection of the given child nodes of the node passed to
* setNode. This method should be implemented as a no-op for result viewers
* that do not display the child nodes of a given root node using a NetBeans
* explorer view set up to use a given explorer manager.
*
* @param selectedNodes The child nodes to select.
*/
default public void setSelectedNodes(Node[] selectedNodes) {
}
/**
* Gets the title of this result viewer.
*
* @return The title.
*/
public String getTitle();
/**
* Gets the Swing component for this viewer.
*
* @return The component.
*/
public Component getComponent();
/**
* Resets the viewer.
* Resets the state of the Swing component for this viewer to its default
* state.
*/
public void resetComponent();
default public void resetComponent() {
}
/**
* Frees the objects that have been allocated by this viewer, in preparation
* for permanently disposing of it.
* Frees any resources tha have been allocated by this result viewer, in
* preparation for permanently disposing of it.
*/
public void clearComponent();
default public void clearComponent() {
}
/**
* Expand node, if supported by the viewed
* Sets the node for which this result viewer should provide a view of the
* underlying application data model object, and expands the node.
*
* @param n Node to expand
*/
public void expandNode(Node n);
/**
* Select the given node array
*/
public void setSelectedNodes(Node[] selected);
/**
* Checks whether the currently selected root node is supported by this
* viewer
* @param node The node.
*
* @param selectedNode the selected node
*
* @return True if supported, else false
*/
public boolean isSupported(Node selectedNode);
/**
* Set a custom content viewer to respond to selection events from this
* result viewer. If not set, the default content viewer is used
*
* @param contentViewer content viewer to respond to selection events from
* this viewer
*
* @deprecated All implementations of this in the standard DataResultViewers are now no-ops.
* @deprecated This API is not used by the application.
*/
@Deprecated
public void setContentViewer(DataContent contentViewer);
default public void expandNode(Node node) {
}
/**
* Sets a custom content viewer to which nodes selected in this result
* viewer should be pushed via DataContent.setNode.
*
* @param contentViewer The content viewer.
*
* @deprecated This API is not used by the application.
*/
@Deprecated
default public void setContentViewer(DataContent contentViewer) {
}
}

View File

@ -23,65 +23,49 @@ import java.beans.PropertyVetoException;
import java.util.logging.Level;
import javax.swing.JPanel;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerManager.Provider;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Provides a JPanel base class that provides a default implementation of the
* ExplorerManager.Provider interface and selected methods of
* theDataResultViewer interface. The ExplorerManager.Provider interface is
* implemented to supply an explorer manager to subclasses and their child
* components. The explorer manager is expected to be the explorer manager of a
* top component that exposes a lookup maintained by the explorer manager to the
* actions global context. This connects the nodes displayed in the result
* viewer to the actions global context. The explorer manager may be either
* supplied during construction or discovered at runtime.
* An abstract base class for an implementation of the result viewer interface
* that is a JPanel that displays the child nodes of a given node using a
* NetBeans explorer view as a child component. Such a result viewer should use
* the explorer manager of an ancestor top component to connect the lookups of
* the nodes displayed in the NetBeans explorer view to the actions global
* context. This class handles some key aspects of working with the ancestor top
* component's explorer manager.
*
* Instances of this class can be supplied with the top component's explorer
* manager during construction, but the typical use case is for the result
* viewer to find the ancestor top component's explorer manager at runtime.
*
* IMPORTANT: If the result viewer is going to find the ancestor top component's
* explorer manager at runtime, the first call to the getExplorerManager method
* of this class must be made AFTER the component hierarchy is fully
* constructed.
*
*/
abstract class AbstractDataResultViewer extends JPanel implements DataResultViewer, Provider {
public abstract class AbstractDataResultViewer extends JPanel implements DataResultViewer, ExplorerManager.Provider {
private static final Logger logger = Logger.getLogger(AbstractDataResultViewer.class.getName());
private transient ExplorerManager explorerManager;
/**
* Constructs a JPanel base class instance that provides a default
* implementation of selected methods of the DataResultViewer and
* ExplorerManager.Provider interfaces. The explorer manager of this viewer
* will be discovered at runtime.
*/
AbstractDataResultViewer() {
}
/**
* Constructs a JPanel base class instance that provides a default
* implementation of selected methods of the DataResultViewer and
* ExplorerManager.Provider interfaces.
* Constructs an abstract base class for an implementation of the result
* viewer interface that is a JPanel that displays the child nodes of the
* given node using a NetBeans explorer view as a child component.
*
* @param explorerManager
* @param explorerManager The explorer manager to use in the NetBeans
* explorer view child component of this result
* viewer, may be null. If null, the explorer manager
* will be discovered the first time
* getExplorerManager is called.
*/
AbstractDataResultViewer(ExplorerManager explorerManager) {
public AbstractDataResultViewer(ExplorerManager explorerManager) {
this.explorerManager = explorerManager;
}
@Override
public void clearComponent() {
}
@Override
public void expandNode(Node n) {
}
@Override
public void resetComponent() {
}
@Override
public Component getComponent() {
return this;
}
@Override
public ExplorerManager getExplorerManager() {
if (this.explorerManager == null) {
@ -95,13 +79,13 @@ abstract class AbstractDataResultViewer extends JPanel implements DataResultView
try {
this.getExplorerManager().setSelectedNodes(selected);
} catch (PropertyVetoException ex) {
logger.log(Level.WARNING, "Couldn't set selected nodes.", ex); //NON-NLS
logger.log(Level.SEVERE, "Couldn't set selected nodes", ex); //NON-NLS
}
}
@Deprecated
@Override
public void setContentViewer(DataContent contentViewer) {
public Component getComponent() {
return this;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 - 2018 Basis Technology Corp.
* Copyright 2012-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -67,8 +67,14 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
/**
* A tabular results viewer that displays the children of a given root node
* A tabular result viewer that displays the children of the given root node
* using an OutlineView.
*
* Instances of this class should use the explorer manager of an ancestor top
* component to connect the lookups of the nodes displayed in the OutlineView to
* the actions global context. The explorer manager can be supplied during
* construction, but the typical use case is for the result viewer to find the
* ancestor top component's explorer manager at runtime.
*/
@ServiceProvider(service = DataResultViewer.class)
public final class DataResultViewerTable extends AbstractDataResultViewer {
@ -79,56 +85,52 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
static private final Color TAGGED_ROW_COLOR = new Color(255, 255, 195);
private static final Logger logger = Logger.getLogger(DataResultViewerTable.class.getName());
private final String title;
private Outline outline;
private TableListener outlineViewListener;
private Node currentRootNode;
private final Map<String, ETableColumn> columnMap = new HashMap<>();
private final Map<Integer, Property<?>> propertiesMap = new TreeMap<>();
private final Map<String, ETableColumn> columnMap;
private final Map<Integer, Property<?>> propertiesMap;
private final Outline outline;
private final TableListener outlineViewListener;
private Node rootNode;
/**
* Constructs a tabular results viewer that displays the children of a given
* root node using an OutlineView.
* Constructs a tabular result viewer that displays the children of the
* given root node using an OutlineView. The viewer should have an ancestor
* top component to connect the lookups of the nodes displayed in the
* OutlineView to the actions global context. The explorer manager will be
* discovered at runtime.
*/
public DataResultViewerTable() {
super();
this.title = Bundle.DataResultViewerTable_title();
initialize();
this(null, Bundle.DataResultViewerTable_title());
}
/**
* Constructs a tabular results viewer that displays the children of a given
* root node using an OutlineView, with a given explorer manager.
* Constructs a tabular result viewer that displays the children of a given
* root node using an OutlineView. The viewer should have an ancestor top
* component to connect the lookups of the nodes displayed in the
* OutlineView to the actions global context.
*
* @param explorerManager The explorer manager.
* @param explorerManager The explorer manager of the ancestor top
* component.
*/
public DataResultViewerTable(ExplorerManager explorerManager) {
this(explorerManager, Bundle.DataResultViewerTable_title());
}
/**
* Constructs a tabular results viewer that displays the children of a given
* root node using an OutlineView, with a given explorer manager, and a
* custom title.
* Constructs a tabular result viewer that displays the children of a given
* root node using an OutlineView with a given title. The viewer should have
* an ancestor top component to connect the lookups of the nodes displayed
* in the OutlineView to the actions global context.
*
* @param explorerManager The explorer manager.
* @param title The custom title.
* @param explorerManager The explorer manager of the ancestor top
* component.
* @param title The title.
*/
public DataResultViewerTable(ExplorerManager explorerManager, String title) {
super(explorerManager);
this.title = title;
initialize();
}
this.columnMap = new HashMap<>();
this.propertiesMap = new TreeMap<>();
// @Override
// public void addNotify() {
// super.addNotify();
// initialize();
// }
/*
* Initializes this tabular results viewer.
*/
private void initialize() {
/*
* Execute the code generated by the GUI builder.
*/
@ -159,13 +161,13 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
}
/**
* Creates a new instance of a tabular results viewer that displays the
* Creates a new instance of a tabular result viewer that displays the
* children of a given root node using an OutlineView. This method exists to
* make it possible to use the default service provider instance of this
* class in the "main" results view of the application, while using distinct
* instances in other places in the UI.
*
* @return A new instance of a tabular results viewer,
* @return A new instance of a tabular result viewer,
*/
@Override
public DataResultViewer createInstance() {
@ -173,7 +175,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
}
/**
* Gets the title of this tabular results viewer.
* Gets the title of this tabular result viewer.
*/
@Override
@NbBundle.Messages("DataResultViewerTable.title=Table")
@ -195,7 +197,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
}
/**
* Sets the current root node of this tabular results viewer.
* Sets the current root node of this tabular result viewer.
*
* @param rootNode The node to set as the current root node, possibly null.
*/
@ -225,8 +227,8 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* case database round trips.
*/
if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) {
currentRootNode = rootNode;
this.getExplorerManager().setRootContext(currentRootNode);
this.rootNode = rootNode;
this.getExplorerManager().setRootContext(this.rootNode);
setupTable();
} else {
Node emptyNode = new AbstractNode(Children.LEAF);
@ -241,7 +243,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
}
/**
* Sets up the Outline view of this tabular results viewer by creating
* Sets up the Outline view of this tabular result viewer by creating
* column headers based on the children of the current root node. The
* persisted column order, sorting and visibility is used.
*/
@ -310,10 +312,10 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* it.
*/
SwingUtilities.invokeLater(() -> {
if (currentRootNode instanceof TableFilterNode) {
NodeSelectionInfo selectedChildInfo = ((TableFilterNode) currentRootNode).getChildNodeSelectionInfo();
if (rootNode instanceof TableFilterNode) {
NodeSelectionInfo selectedChildInfo = ((TableFilterNode) rootNode).getChildNodeSelectionInfo();
if (null != selectedChildInfo) {
Node[] childNodes = currentRootNode.getChildren().getNodes(true);
Node[] childNodes = rootNode.getChildren().getNodes(true);
for (int i = 0; i < childNodes.length; ++i) {
Node childNode = childNodes[i];
if (selectedChildInfo.matches(childNode)) {
@ -325,7 +327,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
break;
}
}
((TableFilterNode) currentRootNode).setChildNodeSelectionInfo(null);
((TableFilterNode) rootNode).setChildNodeSelectionInfo(null);
}
}
});
@ -339,7 +341,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
/*
* Populates the column map for the child OutlineView of this tabular
* results viewer with references to the column objects for use when
* result viewer with references to the column objects for use when
* loading/storing the visibility info.
*/
private void populateColumnMap() {
@ -361,7 +363,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* viewer.
*/
private void setColumnWidths() {
if (currentRootNode.getChildren().getNodesCount() != 0) {
if (rootNode.getChildren().getNodesCount() != 0) {
final Graphics graphics = outlineView.getGraphics();
if (graphics != null) {
final FontMetrics metrics = graphics.getFontMetrics();
@ -419,14 +421,14 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
/**
* Persists the current column visibility information for the child
* OutlineView of this tabular results viewer using a preferences file.
* OutlineView of this tabular result viewer using a preferences file.
*/
private synchronized void storeColumnVisibility() {
if (currentRootNode == null || propertiesMap.isEmpty()) {
if (rootNode == null || propertiesMap.isEmpty()) {
return;
}
if (currentRootNode instanceof TableFilterNode) {
TableFilterNode tfn = (TableFilterNode) currentRootNode;
if (rootNode instanceof TableFilterNode) {
TableFilterNode tfn = (TableFilterNode) rootNode;
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
final ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel();
for (Map.Entry<String, ETableColumn> entry : columnMap.entrySet()) {
@ -445,14 +447,14 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
/**
* Persists the current column ordering for the child OutlineView of this
* tabular results viewer using a preferences file.
* tabular result viewer using a preferences file.
*/
private synchronized void storeColumnOrder() {
if (currentRootNode == null || propertiesMap.isEmpty()) {
if (rootNode == null || propertiesMap.isEmpty()) {
return;
}
if (currentRootNode instanceof TableFilterNode) {
TableFilterNode tfn = (TableFilterNode) currentRootNode;
if (rootNode instanceof TableFilterNode) {
TableFilterNode tfn = (TableFilterNode) rootNode;
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
// Store the current order of the columns into settings
for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) {
@ -465,11 +467,11 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* Persists the current column sorting information using a preferences file.
*/
private synchronized void storeColumnSorting() {
if (currentRootNode == null || propertiesMap.isEmpty()) {
if (rootNode == null || propertiesMap.isEmpty()) {
return;
}
if (currentRootNode instanceof TableFilterNode) {
final TableFilterNode tfn = ((TableFilterNode) currentRootNode);
if (rootNode instanceof TableFilterNode) {
final TableFilterNode tfn = ((TableFilterNode) rootNode);
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel();
for (Map.Entry<String, ETableColumn> entry : columnMap.entrySet()) {
@ -497,11 +499,11 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* it cannot set the sort on columns that have not been added to the table.
*/
private synchronized void loadColumnSorting() {
if (currentRootNode == null || propertiesMap.isEmpty()) {
if (rootNode == null || propertiesMap.isEmpty()) {
return;
}
if (currentRootNode instanceof TableFilterNode) {
final TableFilterNode tfn = (TableFilterNode) currentRootNode;
if (rootNode instanceof TableFilterNode) {
final TableFilterNode tfn = (TableFilterNode) rootNode;
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
//organize property sorting information, sorted by rank
TreeSet<ColumnSortInfo> sortInfos = new TreeSet<>(Comparator.comparing(ColumnSortInfo::getRank));
@ -523,12 +525,12 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
* preferences file.
*/
private synchronized void loadColumnVisibility() {
if (currentRootNode == null || propertiesMap.isEmpty()) {
if (rootNode == null || propertiesMap.isEmpty()) {
return;
}
if (currentRootNode instanceof TableFilterNode) {
if (rootNode instanceof TableFilterNode) {
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
final TableFilterNode tfn = ((TableFilterNode) currentRootNode);
final TableFilterNode tfn = ((TableFilterNode) rootNode);
ETableColumnModel columnModel = (ETableColumnModel) outline.getColumnModel();
for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) {
final String propName = entry.getValue().getName();
@ -549,14 +551,14 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
*/
private synchronized List<Node.Property<?>> loadColumnOrder() {
List<Property<?>> props = ResultViewerPersistence.getAllChildProperties(currentRootNode, 100);
List<Property<?>> props = ResultViewerPersistence.getAllChildProperties(rootNode, 100);
// If node is not table filter node, use default order for columns
if (!(currentRootNode instanceof TableFilterNode)) {
if (!(rootNode instanceof TableFilterNode)) {
return props;
}
final TableFilterNode tfn = ((TableFilterNode) currentRootNode);
final TableFilterNode tfn = ((TableFilterNode) rootNode);
propertiesMap.clear();
/*
@ -593,16 +595,6 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
return new ArrayList<>(propertiesMap.values());
}
/**
* Expands a given child node of the current root node.
*
* @param node Node to expand
*/
@Override
public void expandNode(Node node) {
outlineView.expandNode(node);
}
/**
* Frees the resources that have been allocated by this tabular results
* viewer, in preparation for permanently disposing of it.
@ -782,8 +774,8 @@ public final class DataResultViewerTable extends AbstractDataResultViewer {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
// only override the color if a node is not selected
if (currentRootNode != null && !isSelected) {
Node node = currentRootNode.getChildren().getNodeAt(table.convertRowIndexToModel(row));
if (rootNode != null && !isSelected) {
Node node = rootNode.getChildren().getNodeAt(table.convertRowIndexToModel(row));
boolean tagFound = false;
if (node != null) {
Node.PropertySet[] propSets = node.getPropertySets();

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Copyright 2012-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -60,66 +60,67 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A thumbnail viewer for the results view, with paging support.
* A thumbnail result viewer, with paging support, that displays the children of
* the given root node using an IconView. The paging is intended to reduce
* memory footprint by loading no more than two humdred images at a time.
*
* The paging is intended to reduce memory footprint by load only up to
* (currently) 200 images at a time. This works whether or not the underlying
* content nodes are being lazy loaded or not.
*
* TODO (JIRA-2658): Fix DataResultViewer extension point. When this is done,
* restore implementation of DataResultViewerTable as a DataResultViewer service
* provider.
* Instances of this class should use the explorer manager of an ancestor top
* component to connect the lookups of the nodes displayed in the IconView to
* the actions global context. The explorer manager can be supplied during
* construction, but the typical use case is for the result viewer to find the
* ancestor top component's explorer manager at runtime.
*/
@ServiceProvider(service = DataResultViewer.class)
public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
private int curPage;
private int totalPages;
private int curPageImages;
private int thumbSize = ImageUtils.ICON_SIZE_MEDIUM;
private final PageUpdater pageUpdater = new PageUpdater();
private TableFilterNode tfn;
private ThumbnailViewChildren tvc;
private TableFilterNode rootNode;
private ThumbnailViewChildren rootNodeChildren;
private NodeSelectionListener selectionListener;
private int currentPage;
private int totalPages;
private int currentPageImages;
private int thumbSize = ImageUtils.ICON_SIZE_MEDIUM;
/**
* Constructs a thumbnail viewer for the results view, with paging support,
* that is NOT compatible with node multiple selection actions.
* Constructs a thumbnail result viewer, with paging support, that displays
* the children of the given root node using an IconView. The viewer should
* have an ancestor top component to connect the lookups of the nodes
* displayed in the IconView to the actions global context. The explorer
* manager will be discovered at runtime.
*/
public DataResultViewerThumbnail() {
super();
initialize();
this(null);
}
/**
* Constructs a thumbnail viewer for the results view, with paging support,
* that is compatible with node multiple selection actions.
* Constructs a thumbnail result viewer, with paging support, that displays
* the children of the given root node using an IconView. The viewer should
* have an ancestor top component to connect the lookups of the nodes
* displayed in the IconView to the actions global context.
*
* @param explorerManager The shared ExplorerManager for the result viewers.
* @param explorerManager The explorer manager of the ancestor top
* component.
*/
public DataResultViewerThumbnail(ExplorerManager explorerManager) {
super(explorerManager);
initialize();
}
@NbBundle.Messages({"DataResultViewerThumbnail.thumbnailSizeComboBox.small=Small Thumbnails",
@NbBundle.Messages({
"DataResultViewerThumbnail.thumbnailSizeComboBox.small=Small Thumbnails",
"DataResultViewerThumbnail.thumbnailSizeComboBox.medium=Medium Thumbnails",
"DataResultViewerThumbnail.thumbnailSizeComboBox.large=Large Thumbnails"
})
private void initialize() {
public DataResultViewerThumbnail(ExplorerManager explorerManager) {
super(explorerManager);
initComponents();
iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// this.getExplorerManager().addPropertyChangeListener(new ExplorerManagerNodeSelectionListener());
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(
new String[]{Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large()}));
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large()}));
thumbnailSizeComboBox.setSelectedIndex(1);
curPage = -1;
currentPage = -1;
totalPages = 0;
curPageImages = 0;
currentPageImages = 0;
}
/**
@ -315,7 +316,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private void sortButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortButtonActionPerformed
List<Node.Property<?>> childProperties = ResultViewerPersistence.getAllChildProperties(this.getExplorerManager().getRootContext(), 100);
SortChooser sortChooser = new SortChooser(childProperties, ResultViewerPersistence.loadSortCriteria(tfn));
SortChooser sortChooser = new SortChooser(childProperties, ResultViewerPersistence.loadSortCriteria(rootNode));
DialogDescriptor dialogDescriptor = new DialogDescriptor(sortChooser, sortChooser.getDialogTitle());
Dialog createDialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
createDialog.setVisible(true);
@ -336,8 +337,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
Node.Property<?> prop = childProperties.get(i);
String propName = prop.getName();
SortCriterion criterion = criteriaMap.get(prop);
final String columnSortOrderKey = ResultViewerPersistence.getColumnSortOrderKey(tfn, propName);
final String columnSortRankKey = ResultViewerPersistence.getColumnSortRankKey(tfn, propName);
final String columnSortOrderKey = ResultViewerPersistence.getColumnSortOrderKey(rootNode, propName);
final String columnSortRankKey = ResultViewerPersistence.getColumnSortRankKey(rootNode, propName);
if (criterion != null) {
preferences.putBoolean(columnSortOrderKey, criterion.getSortOrder() == SortOrder.ASCENDING);
@ -347,7 +348,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
preferences.remove(columnSortRankKey);
}
}
setNode(tfn); //this is just to force a refresh
setNode(rootNode); //this is just to force a refresh
}
}//GEN-LAST:event_sortButtonActionPerformed
@ -383,26 +384,26 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
if (selectionListener == null) {
this.getExplorerManager().addPropertyChangeListener(new NodeSelectionListener()); // RJCTODO: remove listener on cleanup
}
if (tvc != null) {
tvc.cancelLoadingThumbnails();
if (rootNodeChildren != null) {
rootNodeChildren.cancelLoadingThumbnails();
}
try {
if (givenNode != null) {
tfn = (TableFilterNode) givenNode;
rootNode = (TableFilterNode) givenNode;
/*
* Wrap the given node in a ThumbnailViewChildren that will
* produce ThumbnailPageNodes with ThumbnailViewNode children
* from the child nodes of the given node.
*/
tvc = new ThumbnailViewChildren(givenNode, thumbSize);
final Node root = new AbstractNode(tvc);
rootNodeChildren = new ThumbnailViewChildren(givenNode, thumbSize);
final Node root = new AbstractNode(rootNodeChildren);
pageUpdater.setRoot(root);
root.addNodeListener(pageUpdater);
this.getExplorerManager().setRootContext(root);
} else {
tfn = null;
tvc = null;
rootNode = null;
rootNodeChildren = null;
Node emptyNode = new AbstractNode(Children.LEAF);
this.getExplorerManager().setRootContext(emptyNode);
iconView.setBackground(Color.BLACK);
@ -426,8 +427,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
public void resetComponent() {
super.resetComponent();
this.totalPages = 0;
this.curPage = -1;
curPageImages = 0;
this.currentPage = -1;
currentPageImages = 0;
updateControls();
}
@ -439,15 +440,15 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
}
private void nextPage() {
if (curPage < totalPages) {
curPage++;
if (currentPage < totalPages) {
currentPage++;
switchPage();
}
}
private void previousPage() {
if (curPage > 1) {
curPage--;
if (currentPage > 1) {
currentPage--;
switchPage();
}
}
@ -469,7 +470,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
return;
}
curPage = newPage;
currentPage = newPage;
switchPage();
}
@ -494,9 +495,9 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
progress.switchToIndeterminate();
ExplorerManager explorerManager = DataResultViewerThumbnail.this.getExplorerManager();
Node root = explorerManager.getRootContext();
Node pageNode = root.getChildren().getNodeAt(curPage - 1);
Node pageNode = root.getChildren().getNodeAt(currentPage - 1);
explorerManager.setExploredContext(pageNode);
curPageImages = pageNode.getChildren().getNodesCount();
currentPageImages = pageNode.getChildren().getNodesCount();
return null;
}
@ -539,20 +540,19 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
sortLabel.setText(DataResultViewerThumbnail_sortLabel_text());
} else {
pageNumLabel.setText(
NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
Integer.toString(curPage), Integer.toString(totalPages)));
final int imagesFrom = (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
final int imagesTo = curPageImages + (curPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
pageNumLabel.setText(NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
Integer.toString(currentPage), Integer.toString(totalPages)));
final int imagesFrom = (currentPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE + 1;
final int imagesTo = currentPageImages + (currentPage - 1) * ThumbnailViewChildren.IMAGES_PER_PAGE;
imagesRangeLabel.setText(imagesFrom + "-" + imagesTo);
pageNextButton.setEnabled(!(curPage == totalPages));
pagePrevButton.setEnabled(!(curPage == 1));
pageNextButton.setEnabled(!(currentPage == totalPages));
pagePrevButton.setEnabled(!(currentPage == 1));
goToPageField.setEnabled(totalPages > 1);
sortButton.setEnabled(true);
thumbnailSizeComboBox.setEnabled(true);
if (tfn != null) {
String sortString = ResultViewerPersistence.loadSortCriteria(tfn).stream()
if (rootNode != null) {
String sortString = ResultViewerPersistence.loadSortCriteria(rootNode).stream()
.map(SortCriterion::toString)
.collect(Collectors.joining(" "));
sortString = StringUtils.defaultIfBlank(sortString, "---");
@ -583,30 +583,30 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
totalPages = root.getChildren().getNodesCount();
if (totalPages == 0) {
curPage = -1;
currentPage = -1;
updateControls();
return;
}
if (curPage == -1 || curPage > totalPages) {
curPage = 1;
if (currentPage == -1 || currentPage > totalPages) {
currentPage = 1;
}
//force load the curPage node
final Node pageNode = root.getChildren().getNodeAt(curPage - 1);
final Node pageNode = root.getChildren().getNodeAt(currentPage - 1);
//em.setSelectedNodes(new Node[]{pageNode});
if (pageNode != null) {
pageNode.addNodeListener(new NodeListener() {
@Override
public void childrenAdded(NodeMemberEvent nme) {
curPageImages = pageNode.getChildren().getNodesCount();
currentPageImages = pageNode.getChildren().getNodesCount();
updateControls();
}
@Override
public void childrenRemoved(NodeMemberEvent nme) {
curPageImages = 0;
currentPageImages = 0;
updateControls();
}
@ -632,7 +632,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
@Override
public void childrenRemoved(NodeMemberEvent nme) {
totalPages = 0;
curPage = -1;
currentPage = -1;
updateControls();
}