Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
JTablePanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datasourcesummary.uiutils;
20 
21 import java.awt.BorderLayout;
22 import java.awt.Graphics;
23 import java.awt.event.MouseAdapter;
24 import java.awt.event.MouseEvent;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.function.Function;
28 import java.util.stream.Collectors;
29 import javax.swing.JComponent;
30 import javax.swing.JLayer;
31 import javax.swing.JScrollPane;
32 import javax.swing.JTable;
33 import javax.swing.plaf.LayerUI;
34 import javax.swing.table.DefaultTableColumnModel;
35 import javax.swing.table.TableColumn;
36 import javax.swing.table.TableColumnModel;
38 
43 public class JTablePanel<T> extends AbstractLoadableComponent<List<T>> {
44 
49  public static class CellMouseEvent {
50 
51  private final MouseEvent e;
52  private final JTable table;
53  private final int row;
54  private final int col;
55  private final Object cellValue;
56 
66  public CellMouseEvent(MouseEvent e, JTable table, int row, int col, Object cellValue) {
67  this.e = e;
68  this.table = table;
69  this.row = row;
70  this.col = col;
71  this.cellValue = cellValue;
72  }
73 
77  public MouseEvent getMouseEvent() {
78  return e;
79  }
80 
84  public JTable getTable() {
85  return table;
86  }
87 
91  public int getRow() {
92  return row;
93  }
94 
98  public int getCol() {
99  return col;
100  }
101 
105  public Object getCellValue() {
106  return cellValue;
107  }
108  }
109 
113  public interface CellMouseListener {
114 
122  }
123 
130  private static class Overlay extends LayerUI<JComponent> {
131 
132  private static final long serialVersionUID = 1L;
134 
141  void setVisible(boolean visible) {
142  overlayDelegate.setVisible(visible);
143  }
144 
150  void setMessage(String message) {
151  overlayDelegate.setMessage(message);
152  }
153 
154  @Override
155  public void paint(Graphics g, JComponent c) {
156  super.paint(g, c);
157  overlayDelegate.paintOverlay(g, c.getWidth(), c.getHeight());
158  }
159  }
160 
166  public static class ColumnModel<T> {
167 
168  private final String headerTitle;
170  private final Integer width;
171 
179  public ColumnModel(String headerTitle, Function<T, CellModelTableCellRenderer.CellModel> cellRenderer) {
180  this(headerTitle, cellRenderer, null);
181  }
182 
191  public ColumnModel(String headerTitle, Function<T, CellModelTableCellRenderer.CellModel> cellRenderer, Integer width) {
192  this.headerTitle = headerTitle;
193  this.cellRenderer = cellRenderer;
194  this.width = width;
195  }
196 
200  public String getHeaderTitle() {
201  return headerTitle;
202  }
203 
208  public Function<T, CellModel> getCellRenderer() {
209  return cellRenderer;
210  }
211 
215  public Integer getWidth() {
216  return width;
217  }
218  }
219 
220  private static final long serialVersionUID = 1L;
221 
223 
231  public static <T> TableColumnModel getTableColumnModel(List<ColumnModel<T>> columns) {
232  TableColumnModel tableModel = new DefaultTableColumnModel();
233 
234  for (int i = 0; i < columns.size(); i++) {
235  TableColumn col = new TableColumn(i);
236  ColumnModel<T> model = columns.get(i);
237  // if a preferred width is specified in the column definition,
238  // set the underlying TableColumn preferred width.
239  if (model.getWidth() != null && model.getWidth() >= 0) {
240  col.setPreferredWidth(model.getWidth());
241  }
242 
243  // set the title
244  col.setHeaderValue(model.getHeaderTitle());
245 
246  // use the cell model renderer in this instance
247  col.setCellRenderer(DEFAULT_CELL_RENDERER);
248 
249  tableModel.addColumn(col);
250  }
251 
252  return tableModel;
253  }
254 
263  public static <T> ListTableModel<T> getTableModel(List<ColumnModel<T>> columns) {
264  List<Function<T, ? extends Object>> columnRenderers = columns.stream()
265  .map((colModel) -> colModel.getCellRenderer())
266  .collect(Collectors.toList());
267 
268  return new DefaultListTableModel<T>(columnRenderers);
269  }
270 
279  public static <T> JTablePanel<T> getJTablePanel(List<ColumnModel<T>> columns) {
281  JTablePanel<T> resultTable = new JTablePanel<>(tableModel)
284 
285  return resultTable;
286  }
287 
288  private JScrollPane tableScrollPane;
289  private Overlay overlayLayer;
291  private JTable table;
293  private Function<T, ? extends Object> keyFunction = (rowItem) -> rowItem;
294 
300  public JTablePanel(ListTableModel<T> tableModel) {
301  this();
302  setModel(tableModel);
303  }
304 
308  public JTablePanel() {
309  initComponents();
310  this.table.addMouseListener(new MouseAdapter() {
311 
312  @Override
313  public void mouseClicked(MouseEvent e) {
314  // make sure click event isn't primary button and table is present
315  if (cellListener != null) {
316  int row = table.rowAtPoint(e.getPoint());
317  int col = table.columnAtPoint(e.getPoint());
318 
319  // make sure there is a value at the row,col of click event.
320  if (tableModel != null
321  && row >= 0 && row < tableModel.getRowCount()
322  && col >= 0 && col < tableModel.getColumnCount()) {
323 
324  Object cellValue = tableModel.getValueAt(row, col);
325  cellListener.mouseClicked(new CellMouseEvent(e, table, row, col, cellValue));
326  }
327  }
328  }
329  });
330  }
331 
340  public final JTablePanel<T> setModel(ListTableModel<T> tableModel) {
341  if (tableModel == null) {
342  throw new IllegalArgumentException("Null table model passed to setModel");
343  }
344 
345  this.tableModel = tableModel;
346  table.setModel(tableModel);
347  return this;
348  }
349 
355  return cellListener;
356  }
357 
366  this.cellListener = cellListener;
367  return this;
368  }
369 
373  public TableColumnModel getColumnModel() {
374  return this.table.getColumnModel();
375  }
376 
384  public JTablePanel<T> setColumnModel(TableColumnModel columnModel) {
385  this.table.setColumnModel(columnModel);
386  return this;
387  }
388 
393  public Function<T, ? extends Object> getKeyFunction() {
394  return keyFunction;
395  }
396 
405  public JTablePanel<T> setKeyFunction(Function<T, ? extends Object> keyFunction) {
406  if (keyFunction == null) {
407  throw new IllegalArgumentException("Key function must be non-null");
408  }
409 
410  this.keyFunction = keyFunction;
411  return this;
412  }
413 
414  @Override
415  protected synchronized void setResults(List<T> data) {
416  // get previously selected value
417  int prevSelectedRow = this.table.getSelectedRow();
418  List<T> tableRows = this.tableModel.getDataRows();
419  T prevValue = (tableRows != null && prevSelectedRow >= 0 && prevSelectedRow < tableRows.size())
420  ? this.tableModel.getDataRows().get(prevSelectedRow)
421  : null;
422 
423  Object prevKeyValue = (prevValue == null) ? null : this.keyFunction.apply(prevValue);
424 
425  // set the list of data to be shown as either the data or an empty list
426  // on null.
427  List<T> dataToSet = (data == null) ? Collections.emptyList() : data;
428 
429  // set the underlying table model's data.
430  this.tableModel.setDataRows(dataToSet);
431 
432  // set the row to selected value if the value is found
433  if (prevKeyValue != null) {
434  for (int objIndex = 0; objIndex < dataToSet.size(); objIndex++) {
435  Object thisKey = this.keyFunction.apply(dataToSet.get(objIndex));
436  if (prevKeyValue.equals(thisKey)) {
437  this.table.setRowSelectionInterval(objIndex, objIndex);
438  break;
439  }
440  }
441  }
442 
443  }
444 
445  @Override
446  protected void setMessage(boolean visible, String message) {
447  this.overlayLayer.setVisible(visible);
448  this.overlayLayer.setMessage(message);
449  }
450 
454  private void initComponents() {
455  table = new JTable();
456  table.getTableHeader().setReorderingAllowed(false);
457  overlayLayer = new Overlay();
458  tableScrollPane = new JScrollPane(table);
459  JLayer<JComponent> dualLayer = new JLayer<>(tableScrollPane, overlayLayer);
460  setLayout(new BorderLayout());
461  add(dualLayer, BorderLayout.CENTER);
462  }
463 }
JTablePanel< T > setColumnModel(TableColumnModel columnModel)
void setMessage(boolean visible, String message)
ColumnModel(String headerTitle, Function< T, CellModelTableCellRenderer.CellModel > cellRenderer)
ColumnModel(String headerTitle, Function< T, CellModelTableCellRenderer.CellModel > cellRenderer, Integer width)
JTablePanel< T > setCellListener(CellMouseListener cellListener)
static< T > JTablePanel< T > getJTablePanel(List< ColumnModel< T >> columns)
static< T > TableColumnModel getTableColumnModel(List< ColumnModel< T >> columns)
static< T > ListTableModel< T > getTableModel(List< ColumnModel< T >> columns)
final Function< T, CellModelTableCellRenderer.CellModel > cellRenderer
CellMouseEvent(MouseEvent e, JTable table, int row, int col, Object cellValue)
final JTablePanel< T > setModel(ListTableModel< T > tableModel)
static final CellModelTableCellRenderer DEFAULT_CELL_RENDERER
JTablePanel< T > setKeyFunction(Function< T,?extends Object > keyFunction)

Copyright © 2012-2021 Basis Technology. Generated on: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.