Skip to content

Commit 6673b20

Browse files
authored
Merge pull request #63 from tferr/table-fixes
JTable: Fix absence of horizontal scrollbar and add popup menu actions
2 parents 7a0bc52 + 7cca674 commit 6673b20

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

src/main/java/org/scijava/ui/swing/viewer/table/SwingTableDisplayPanel.java

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,25 @@
2929

3030
package org.scijava.ui.swing.viewer.table;
3131

32+
import java.awt.Component;
33+
import java.awt.Toolkit;
34+
import java.awt.event.ActionEvent;
35+
import java.awt.event.ComponentAdapter;
36+
import java.awt.event.ComponentEvent;
37+
import java.awt.event.KeyEvent;
38+
import java.util.Arrays;
39+
40+
import javax.swing.AbstractAction;
41+
import javax.swing.Action;
42+
import javax.swing.JComponent;
43+
import javax.swing.JMenuItem;
44+
import javax.swing.JPopupMenu;
3245
import javax.swing.JScrollPane;
3346
import javax.swing.JTable;
47+
import javax.swing.KeyStroke;
3448
import javax.swing.table.AbstractTableModel;
49+
import javax.swing.table.TableCellRenderer;
50+
import javax.swing.table.TableColumn;
3551

3652
import org.scijava.table.Table;
3753
import org.scijava.table.TableDisplay;
@@ -65,9 +81,25 @@ public SwingTableDisplayPanel(final TableDisplay display,
6581
this.window = window;
6682
nullModel = new NullTableModel();
6783
table = makeTable();
84+
6885
table.setAutoCreateRowSorter(true);
86+
table.setRowSelectionAllowed(true);
87+
new TablePopupMenu().install();
88+
89+
//table.setPreferredScrollableViewportSize(getPreferredSize());
90+
addComponentListener(new ComponentAdapter() {
91+
@Override
92+
public void componentResized(final ComponentEvent e) {
93+
if (table.getPreferredSize().width < getWidth()) {
94+
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
95+
} else {
96+
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
97+
}
98+
}
99+
});
69100
setViewportView(table);
70101
window.setContent(this);
102+
71103
}
72104

73105
// -- TableDisplayPanel methods --
@@ -133,6 +165,7 @@ private JTable makeTable() {
133165

134166
// -- Helper classes --
135167

168+
@SuppressWarnings("serial")
136169
public static class NullTableModel extends AbstractTableModel {
137170

138171
@Override
@@ -209,6 +242,14 @@ public void setValueAt(final Object value, final int row, final int col) {
209242
fireTableCellUpdated(row, col);
210243
}
211244

245+
public void removeRows(int[] indices) {
246+
Arrays.sort(indices);
247+
for (int i = indices.length - 1; i >= 0; i--) {
248+
tab.removeRow(indices[i]);
249+
fireTableRowsDeleted(indices[i], indices[i]);
250+
}
251+
}
252+
212253
// -- Helper methods --
213254

214255
private <T> void set(final Table<?, T> table,
@@ -221,4 +262,91 @@ private <T> void set(final Table<?, T> table,
221262

222263
}
223264

265+
@SuppressWarnings("serial")
266+
class TablePopupMenu extends JPopupMenu {
267+
public TablePopupMenu() {
268+
super();
269+
JMenuItem mi;
270+
mi= new JMenuItem(new ActionMapAction("Copy", table, "copy"));
271+
final int MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
272+
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, MASK));
273+
add(mi);
274+
mi = new JMenuItem(new ActionMapAction("Select All", table, "selectAll"));
275+
mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, MASK));
276+
add(mi);
277+
addSeparator();
278+
mi = new JMenuItem("Delete Selected Row(s)");
279+
mi.addActionListener(e -> {
280+
final int[] selectedRows = table.getSelectedRows();
281+
if (selectedRows.length > 0)
282+
((TableModel) table.getModel()).removeRows(selectedRows);
283+
});
284+
add(mi);
285+
mi = new JMenuItem("Resize Column Widths");
286+
mi.addActionListener(e -> resizeColumns());
287+
add(mi);
288+
}
289+
290+
private void resizeColumns() {
291+
// https://stackoverflow.com/a/30355804
292+
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
293+
table.getTableHeader();
294+
for (int column = 0; column < table.getColumnCount(); column++) {
295+
final TableColumn tableColumn = table.getColumnModel().getColumn(column);
296+
int preferredWidth = Math.max(tableColumn.getMinWidth(), getColumnHeaderWidth(tableColumn, column));
297+
final int maxWidth = tableColumn.getMaxWidth();
298+
for (int row = 0; row < table.getRowCount(); row++) {
299+
final TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
300+
final Component c = table.prepareRenderer(cellRenderer, row, column);
301+
final int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
302+
preferredWidth = Math.max(preferredWidth, width);
303+
if (preferredWidth >= maxWidth) {
304+
preferredWidth = maxWidth;
305+
break;
306+
}
307+
}
308+
tableColumn.setPreferredWidth(preferredWidth);
309+
}
310+
}
311+
312+
private int getColumnHeaderWidth(final TableColumn tableColumn, final int column) {
313+
final Object value = tableColumn.getHeaderValue();
314+
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
315+
if (renderer == null) {
316+
renderer = table.getTableHeader().getDefaultRenderer();
317+
}
318+
final Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column);
319+
return c.getPreferredSize().width;
320+
}
321+
322+
void install() {
323+
table.setComponentPopupMenu(this);
324+
SwingTableDisplayPanel.this.setComponentPopupMenu(this);
325+
}
326+
327+
}
328+
329+
@SuppressWarnings("serial")
330+
private class ActionMapAction extends AbstractAction {
331+
332+
private final Action originalAction;
333+
private final JComponent component;
334+
private final String actionCommand = "";
335+
336+
ActionMapAction(final String name, final JComponent component, final String actionKey) {
337+
super(name);
338+
originalAction = component.getActionMap().get(actionKey);
339+
if (originalAction == null) {
340+
throw new IllegalArgumentException("No Action for action key: " + actionKey);
341+
}
342+
this.component = component;
343+
}
344+
345+
@Override
346+
public void actionPerformed(ActionEvent e) {
347+
e = new ActionEvent(component, ActionEvent.ACTION_PERFORMED, actionCommand, e.getWhen(), e.getModifiers());
348+
originalAction.actionPerformed(e);
349+
}
350+
351+
}
224352
}

0 commit comments

Comments
 (0)