Autopsy  4.19.1
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-2021 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;
37 
42 public class JTablePanel<T> extends AbstractLoadableComponent<List<T>> {
43 
44  private static final int EXTRA_ROW_HEIGHT = 4;
45 
50  public static class CellMouseEvent {
51 
52  private final MouseEvent e;
53  private final JTable table;
54  private final int row;
55  private final int col;
56  private final Object cellValue;
57 
67  public CellMouseEvent(MouseEvent e, JTable table, int row, int col, Object cellValue) {
68  this.e = e;
69  this.table = table;
70  this.row = row;
71  this.col = col;
72  this.cellValue = cellValue;
73  }
74 
78  public MouseEvent getMouseEvent() {
79  return e;
80  }
81 
85  public JTable getTable() {
86  return table;
87  }
88 
92  public int getRow() {
93  return row;
94  }
95 
99  public int getCol() {
100  return col;
101  }
102 
106  public Object getCellValue() {
107  return cellValue;
108  }
109  }
110 
114  public interface CellMouseListener {
115 
123  }
124 
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 
161  private static final long serialVersionUID = 1L;
162 
164 
172  public static <T, C extends GuiCellModel> TableColumnModel getTableColumnModel(List<ColumnModel<T, C>> columns) {
173  TableColumnModel tableModel = new DefaultTableColumnModel();
174 
175  for (int i = 0; i < columns.size(); i++) {
176  TableColumn col = new TableColumn(i);
177  ColumnModel<T, C> model = columns.get(i);
178  // if a preferred width is specified in the column definition,
179  // set the underlying TableColumn preferred width.
180  if (model.getWidth() != null && model.getWidth() >= 0) {
181  col.setPreferredWidth(model.getWidth());
182  }
183 
184  // set the title
185  col.setHeaderValue(model.getHeaderTitle());
186 
187  // use the cell model renderer in this instance
188  col.setCellRenderer(DEFAULT_CELL_RENDERER);
189 
190  tableModel.addColumn(col);
191  }
192 
193  return tableModel;
194  }
195 
204  public static <T, C extends GuiCellModel> ListTableModel<T> getTableModel(List<ColumnModel<T, C>> columns) {
205  List<Function<T, ? extends Object>> columnRenderers = columns.stream()
206  .map((colModel) -> colModel.getCellRenderer())
207  .collect(Collectors.toList());
208 
209  return new DefaultListTableModel<>(columnRenderers);
210  }
211 
220  public static <T, C extends GuiCellModel> JTablePanel<T> getJTablePanel(List<ColumnModel<T, C>> columns) {
222  JTablePanel<T> resultTable = new JTablePanel<>(tableModel)
225 
226  return resultTable;
227  }
228 
229  private JScrollPane tableScrollPane;
230  private Overlay overlayLayer;
232  private JTable table;
234  private Function<T, ? extends Object> keyFunction = (rowItem) -> rowItem;
235 
241  public JTablePanel(ListTableModel<T> tableModel) {
242  this();
243  setModel(tableModel);
244  table.setRowHeight(table.getRowHeight() + EXTRA_ROW_HEIGHT);
245  }
246 
250  public JTablePanel() {
251  initComponents();
252  this.table.addMouseListener(new MouseAdapter() {
253 
254  @Override
255  public void mouseClicked(MouseEvent e) {
256  // make sure click event isn't primary button and table is present
257  if (cellListener != null) {
258  int row = table.rowAtPoint(e.getPoint());
259  int col = table.columnAtPoint(e.getPoint());
260 
261  // make sure there is a value at the row,col of click event.
262  if (tableModel != null
263  && row >= 0 && row < tableModel.getRowCount()
264  && col >= 0 && col < tableModel.getColumnCount()) {
265 
266  Object cellValue = tableModel.getValueAt(row, col);
267  cellListener.mouseClicked(new CellMouseEvent(e, table, row, col, cellValue));
268  }
269  }
270  }
271  });
272  table.setGridColor(javax.swing.UIManager.getDefaults().getColor("InternalFrame.borderColor"));
273  }
274 
283  public final JTablePanel<T> setModel(ListTableModel<T> tableModel) {
284  if (tableModel == null) {
285  throw new IllegalArgumentException("Null table model passed to setModel");
286  }
287 
288  this.tableModel = tableModel;
289  table.setModel(tableModel);
290  return this;
291  }
292 
298  return cellListener;
299  }
300 
310  this.cellListener = cellListener;
311  return this;
312  }
313 
317  public TableColumnModel getColumnModel() {
318  return this.table.getColumnModel();
319  }
320 
328  public JTablePanel<T> setColumnModel(TableColumnModel columnModel) {
329  this.table.setColumnModel(columnModel);
330  return this;
331  }
332 
338  public Function<T, ? extends Object> getKeyFunction() {
339  return keyFunction;
340  }
341 
350  public JTablePanel<T> setKeyFunction(Function<T, ? extends Object> keyFunction) {
351  if (keyFunction == null) {
352  throw new IllegalArgumentException("Key function must be non-null");
353  }
354 
355  this.keyFunction = keyFunction;
356  return this;
357  }
358 
364  public List<T> getSelectedItems() {
365  int selectedRow = this.table.getSelectedRow();
366  int count = this.table.getSelectedRowCount();
367  if (selectedRow < 0 || this.tableModel == null || selectedRow + count > this.tableModel.getDataRows().size()) {
368  return null;
369  } else {
370  return this.tableModel.getDataRows().subList(selectedRow, selectedRow + count);
371  }
372  }
373 
374  @Override
375  protected synchronized void setResults(List<T> data) {
376  // get previously selected value
377  int prevSelectedRow = this.table.getSelectedRow();
378  List<T> tableRows = this.tableModel.getDataRows();
379  T prevValue = (tableRows != null && prevSelectedRow >= 0 && prevSelectedRow < tableRows.size())
380  ? this.tableModel.getDataRows().get(prevSelectedRow)
381  : null;
382 
383  Object prevKeyValue = (prevValue == null) ? null : this.keyFunction.apply(prevValue);
384 
385  // set the list of data to be shown as either the data or an empty list
386  // on null.
387  List<T> dataToSet = (data == null) ? Collections.emptyList() : data;
388 
389  // set the underlying table model's data.
390  this.tableModel.setDataRows(dataToSet);
391 
392  // set the row to selected value if the value is found
393  if (prevKeyValue != null) {
394  for (int objIndex = 0; objIndex < dataToSet.size(); objIndex++) {
395  Object thisKey = this.keyFunction.apply(dataToSet.get(objIndex));
396  if (prevKeyValue.equals(thisKey)) {
397  this.table.setRowSelectionInterval(objIndex, objIndex);
398  break;
399  }
400  }
401  }
402 
403  }
404 
405  @Override
406  protected void setMessage(boolean visible, String message) {
407  this.overlayLayer.setVisible(visible);
408  this.overlayLayer.setMessage(message);
409  }
410 
414  private void initComponents() {
415  table = new JTable();
416  table.getTableHeader().setReorderingAllowed(false);
417  overlayLayer = new Overlay();
418  tableScrollPane = new JScrollPane(table);
419  JLayer<JComponent> dualLayer = new JLayer<>(tableScrollPane, overlayLayer);
420  setLayout(new BorderLayout());
421  add(dualLayer, BorderLayout.CENTER);
422  }
423 }
JTablePanel< T > setColumnModel(TableColumnModel columnModel)
static< T, CextendsGuiCellModel > TableColumnModel getTableColumnModel(List< ColumnModel< T, C >> columns)
void setMessage(boolean visible, String message)
static< T, CextendsGuiCellModel > ListTableModel< T > getTableModel(List< ColumnModel< T, C >> columns)
static< T, CextendsGuiCellModel > JTablePanel< T > getJTablePanel(List< ColumnModel< T, C >> columns)
JTablePanel< T > setCellListener(CellMouseListener cellListener)
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: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.