📄 exacttable.java
字号:
/**
* Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package jmt.gui.exact.table;
import jmt.gui.common.resources.ImageLoader;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.UIResource;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.StringTokenizer;
/**
* @author alyf (Andrea Conti)
* Date: 15-set-2003
* Time: 20.39.53
*/
/**
* a table with some improvements:
* <li>has a click-aware header
* <li>has a click-aware row header
* <li>"more rows" and "more columns" warning icons
* <li>clipboard transfer of cell values (support depends on the underlying data model) - CTRL+C, CTRL+X, CTRL+V
* <li>can clear selected cells - DELETE
* <li>can fill cells with the value from a cell (if using an ExactTableModel) - CTRL+F
*/
public class ExactTable extends JTable {
private static final boolean DEBUG = false;
protected RowHeader rowHeader;
protected int rowHeaderWidth = 80;
protected JButton selectAllButton;
protected JLabel moreColumnsLabel, moreRowsLabel;
protected boolean displaysScrollLabels = true;
protected boolean selectAllEnabled = true;
protected boolean clipboardTransferEnabled = false;
protected boolean fillCellsEnabled = true;
protected TableSelectionListener selectionListener;
protected MouseHandler mouseHandler;
protected boolean mouseMenuEnabled = true;
protected Clipboard clip;
StringSelection stsel;
boolean canPaste = false;
protected String selectAllTooltip;//"Click to select the whole table";
protected String moreColumnsTooltip;//"Scroll right to see more columns...";
protected String moreRowsTooltip;//"Scroll down to see more rows...";
protected AbstractAction selectAction = new AbstractAction() {
{
if (getRowSelectionAllowed() || getColumnSelectionAllowed()) {
putValue(Action.SHORT_DESCRIPTION, selectAllTooltip);
putValue(Action.NAME, "*");
} else {
putValue(Action.SHORT_DESCRIPTION, null);
putValue(Action.NAME, " ");
}
}
public void actionPerformed(ActionEvent e) {
stopEditing();
selectAll();
requestFocus();
}
};
/**
* updates the label state when the table is scrolled
*/
private ChangeListener scrollListener = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (displaysScrollLabels) {
updateScrollLabels();
}
}
};
public ExactTable(TableModel dm) {
super(dm);
/* apply default settings */
setDefaultRenderer(Object.class, new ExactCellRenderer());
setDefaultEditor(Object.class, new ExactCellEditor());
/* try to resize the columns in a not-so-stupid way */
sizeColumns();
moreColumnsLabel = new JLabel();
moreRowsLabel = new JLabel();
selectAllButton = new JButton(selectAction);
rowHeader = new RowHeader(dataModel);
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
columnModel.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
setColumnSelectionAllowed(true);
setRowSelectionAllowed(true);
//Dall'Orso 20/12/2004
//BEGIN
setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
//END
installKeyboard();
installMouse();
selectionListener = new TableSelectionListener() {
protected void selectionChanged(JTable table, ListSelectionEvent e, int type) {
updateActions();
}
};
selectionListener.install(this);
clip = Toolkit.getDefaultToolkit().getSystemClipboard();
}
protected void installKeyboard() {
InputMap im = getInputMap();
ActionMap am = getActionMap();
installKeyboardAction(im, am, COPY_ACTION);
installKeyboardAction(im, am, CUT_ACTION);
installKeyboardAction(im, am, PASTE_ACTION);
installKeyboardAction(im, am, FILL_ACTION);
installKeyboardAction(im, am, CLEAR_ACTION);
}
protected void installKeyboardAction(Action a) {
installKeyboardAction(getInputMap(), getActionMap(), a);
}
protected void installKeyboardAction(InputMap im, ActionMap am, Action a) {
Object name = a.getValue(Action.NAME);
KeyStroke key = (KeyStroke) a.getValue(Action.ACCELERATOR_KEY);
im.put(key, name);
am.put(name, a);
}
protected void installMouse() {
mouseHandler = new MouseHandler(makeMouseMenu());
mouseHandler.install();
}
protected JPopupMenu makeMouseMenu() {
JPopupMenu menu = new JPopupMenu();
menu.add(COPY_ACTION);
menu.add(CUT_ACTION);
menu.add(PASTE_ACTION);
menu.add(CLEAR_ACTION);
menu.add(FILL_ACTION);
return menu;
}
/**
* Overridden to make sure column sizes are mantained
*/
public void tableChanged(TableModelEvent e) {
super.tableChanged(e);
if ((e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW)) {
sizeColumns();
}
}
private void sizeColumns() {
/* try and resize columns according to their header and (if available) prototype width*/
/* taken from Sun's JTable tutorial, with some added features */
int colnum = dataModel.getColumnCount();
TableColumn col;
Component comp;
PrototypedTableModel ptm = null;
boolean hasPrototypes = false;
int autoWidth;
if (dataModel instanceof PrototypedTableModel) {
hasPrototypes = true;
ptm = (PrototypedTableModel) dataModel;
}
if (tableHeader == null) return; // hack: skip column sizing until we actually have a header
for (int i = 0; i < colnum; i++) {
col = columnModel.getColumn(i);
comp = tableHeader.getDefaultRenderer().
getTableCellRendererComponent(
null, col.getHeaderValue(),
false, false, 0, i);
autoWidth = comp.getPreferredSize().width;
if (hasPrototypes) {
/* comp = getDefaultRenderer(dataModel.getColumnClass(i)).
getTableCellRendererComponent(
this, ptm.getPrototype(i),
false, false, 0, i);
*/ comp = getDefaultRenderer(Object.class).
getTableCellRendererComponent(
this, ptm.getPrototype(i),
false, false, 0, i);
autoWidth = Math.max(autoWidth, comp.getPreferredSize().width);
}
col.setPreferredWidth(autoWidth);
}
}
public void setColumnSelectionAllowed(boolean allowed) {
super.setColumnSelectionAllowed(allowed);
allowed = getColumnSelectionAllowed();
if (tableHeader instanceof ClickableTableHeader) ((ClickableTableHeader) tableHeader).setAllowsClickColumnSelection(allowed);
setSelectAllStatus(allowed || getRowSelectionAllowed());
}
public void setRowSelectionAllowed(boolean allowed) {
super.setRowSelectionAllowed(allowed);
allowed = getRowSelectionAllowed();
if (rowHeader != null) rowHeader.setAllowsClickRowSelection(allowed);
setSelectAllStatus(allowed || getColumnSelectionAllowed());
}
public void setSelectAllStatus(boolean allowed) {
if (allowed && !selectAllEnabled) {
if (selectAction != null) {
selectAction.setEnabled(true);
selectAction.putValue(Action.NAME, "*");
selectAction.putValue(Action.SHORT_DESCRIPTION, selectAllTooltip);
}
selectAllEnabled = true;
} else if (!allowed && selectAllEnabled) {
if (selectAction != null) {
selectAction.setEnabled(false);
selectAction.putValue(Action.NAME, " ");
selectAction.putValue(Action.SHORT_DESCRIPTION, null);
}
selectAllEnabled = false;
}
}
/**
* Overridden to return our nifty header
*/
protected JTableHeader createDefaultTableHeader() {
return new ClickableTableHeader(columnModel);
}
/**
* duplicated to avoid repeating the same checks multiple times
*/
protected void configureEnclosingScrollPane() {
Container p = getParent();
if (p instanceof JViewport) {
Container gp = p.getParent();
if (gp instanceof JScrollPane) {
JScrollPane scrollPane = (JScrollPane) gp;
// Make certain we are the viewPort's view and not, for
// example, the rowHeaderView of the scrollPane -
// an implementor of fixed columns might do this.
JViewport viewport = scrollPane.getViewport();
if (viewport == null || viewport.getView() != this) {
return;
}
scrollPane.setColumnHeaderView(getTableHeader());
Border border = scrollPane.getBorder();
if (border == null || border instanceof UIResource) {
scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
}
//rowHeader=new RowHeader(dataModel);
rowHeader.install(this, scrollPane);
installLabels(scrollPane);
installSelectAllButton(scrollPane);
viewport.addChangeListener(scrollListener);
}
}
}
protected void unconfigureEnclosingScrollPane() {
Container p = getParent();
if (p instanceof JViewport) {
Container gp = p.getParent();
if (gp instanceof JScrollPane) {
JScrollPane scrollPane = (JScrollPane) gp;
// Make certain we are the viewPort's view and not, for
// example, the rowHeaderView of the scrollPane -
// an implementor of fixed columns might do this.
JViewport viewport = scrollPane.getViewport();
if (viewport == null || viewport.getView() != this) {
return;
}
scrollPane.setColumnHeaderView(null);
scrollPane.setRowHeaderView(null);
viewport.removeChangeListener(scrollListener);
rowHeader.uninstall();
}
}
}
private void installSelectAllButton(JScrollPane scrollPane) {
selectAllButton.setFocusable(false);
selectAllButton.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, selectAllButton);
}
private void installLabels(JScrollPane scrollPane) {
moreColumnsLabel.setIcon(ImageLoader.loadImage("table_rightarrow"));
moreColumnsLabel.setHorizontalAlignment(SwingConstants.CENTER);
moreColumnsLabel.setToolTipText(moreColumnsTooltip);
moreColumnsLabel.setVisible(false);
moreRowsLabel.setIcon(ImageLoader.loadImage("table_downarrow"));
moreRowsLabel.setHorizontalAlignment(SwingConstants.CENTER);
moreRowsLabel.setToolTipText(moreRowsTooltip);
moreRowsLabel.setVisible(false);
scrollPane.setCorner(JScrollPane.UPPER_RIGHT_CORNER, moreColumnsLabel);
scrollPane.setCorner(JScrollPane.LOWER_LEFT_CORNER, moreRowsLabel);
if (displaysScrollLabels) updateScrollLabels();
}
/**
* Make sure we're not editing a cell. NOTE: requires the editor to honor stopCellEditing() or
* cancelCellEditing() calls.
*/
public void stopEditing() {
if (cellEditor != null) {
if (!cellEditor.stopCellEditing()) cellEditor.cancelCellEditing();
}
}
/**
* selects a cell
*/
public void setSelectedCell(int row, int col) {
setColumnSelectionInterval(col, col);
setRowSelectionInterval(row, row);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -