📄 basictableui.java
字号:
/* * @(#)BasicTableUI.java 1.123 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package javax.swing.plaf.basic;import javax.swing.table.*;import javax.swing.*;import javax.swing.event.*;import java.util.Enumeration;import java.util.Hashtable;import java.util.TooManyListenersException;import java.awt.event.*;import java.awt.*;import java.awt.datatransfer.*;import java.awt.dnd.*;import javax.swing.plaf.*;import java.util.EventObject;import javax.swing.text.*;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;/** * BasicTableUI implementation * * @version 1.117 08/27/01 * @author Philip Milne */public class BasicTableUI extends TableUI{//// Instance Variables// // The JTable that is delegating the painting to this UI. protected JTable table; protected CellRendererPane rendererPane; // Listeners that are attached to the JTable protected KeyListener keyListener; protected FocusListener focusListener; protected MouseInputListener mouseInputListener; private PropertyChangeListener propertyChangeListener;//// Helper class for keyboard actions// private static class NavigationalAction extends AbstractAction { protected int dx; protected int dy; protected boolean toggle; protected boolean extend; protected boolean inSelection; protected int anchorRow; protected int anchorColumn; protected int leadRow; protected int leadColumn; protected NavigationalAction(int dx, int dy, boolean toggle, boolean extend, boolean inSelection) { this.dx = dx; this.dy = dy; this.toggle = toggle; this.extend = extend; this.inSelection = inSelection; } private int clipToRange(int i, int a, int b) { return Math.min(Math.max(i, a), b-1); } private void moveWithinTableRange(JTable table, int dx, int dy, boolean changeLead) { if (changeLead) { leadRow = clipToRange(leadRow+dy, 0, table.getRowCount()); leadColumn = clipToRange(leadColumn+dx, 0, table.getColumnCount()); } else { anchorRow = clipToRange(anchorRow+dy, 0, table.getRowCount()); anchorColumn = clipToRange(anchorColumn+dx, 0, table.getColumnCount()); } } private int selectionSpan(ListSelectionModel sm) { return sm.getMaxSelectionIndex() - sm.getMinSelectionIndex() + 1; } private int compare(int i, ListSelectionModel sm) { return compare(i, sm.getMinSelectionIndex(), sm.getMaxSelectionIndex()+1); } private int compare(int i, int a, int b) { return (i < a) ? -1 : (i >= b) ? 1 : 0 ; } private boolean moveWithinSelectedRange(JTable table, int dx, int dy, boolean ignoreCarry) { ListSelectionModel rsm = table.getSelectionModel(); ListSelectionModel csm = table.getColumnModel().getSelectionModel(); int newAnchorRow = anchorRow + dy; int newAnchorColumn = anchorColumn + dx; int rowSgn; int colSgn; int rowCount = selectionSpan(rsm); int columnCount = selectionSpan(csm); boolean canStayInSelection = (rowCount * columnCount > 1); if (canStayInSelection) { rowSgn = compare(newAnchorRow, rsm); colSgn = compare(newAnchorColumn, csm); } else { // If there is only one selected cell, there is no point // in trying to stay within the selected area. Move outside // the selection, wrapping at the table boundaries. rowCount = table.getRowCount(); columnCount = table.getColumnCount(); rowSgn = compare(newAnchorRow, 0, rowCount); colSgn = compare(newAnchorColumn, 0, columnCount); } anchorRow = newAnchorRow - rowCount * rowSgn; anchorColumn = newAnchorColumn - columnCount * colSgn; if (!ignoreCarry) { return moveWithinSelectedRange(table, rowSgn, colSgn, true); } return canStayInSelection; } public void actionPerformed(ActionEvent e) { JTable table = (JTable)e.getSource(); ListSelectionModel rsm = table.getSelectionModel(); anchorRow = rsm.getAnchorSelectionIndex(); leadRow = rsm.getLeadSelectionIndex(); ListSelectionModel csm = table.getColumnModel().getSelectionModel(); anchorColumn = csm.getAnchorSelectionIndex(); leadColumn = csm.getLeadSelectionIndex(); int oldAnchorRow = anchorRow; int oldAnchorColumn = anchorColumn; if (table.isEditing() && !table.getCellEditor().stopCellEditing()) { return; } // Unfortunately, this strategy introduces bugs because // of the asynchronous nature of requestFocus() call below. // Introducing a delay with invokeLater() makes this work // in the typical case though race conditions then allow // focus to disappear altogether. The right solution appears // to be to fix requestFocus() so that it queues a request // for the focus regardless of who owns the focus at the // time the call to requestFocus() is made. The optimisation // to ignore the call to requestFocus() when the component // already has focus may ligitimately be made as the // request focus event is dequeued, not before. // boolean wasEditingWithFocus = table.isEditing() && table.getEditorComponent().isFocusOwner(); if (!inSelection) { moveWithinTableRange(table, dx, dy, extend); if (!extend) { table.changeSelection(anchorRow, anchorColumn, false, extend); } else { table.changeSelection(leadRow, leadColumn, false, extend); } } else { if (moveWithinSelectedRange(table, dx, dy, false)) { table.changeSelection(anchorRow, anchorColumn, true, true); } else { table.changeSelection(anchorRow, anchorColumn, false, false); } } /* if (wasEditingWithFocus) { table.editCellAt(anchorRow, anchorColumn); final Component editorComp = table.getEditorComponent(); if (editorComp != null) { SwingUtilities.invokeLater(new Runnable() { public void run() { editorComp.requestFocus(); } }); } } */ } } private static class PagingAction extends NavigationalAction { private boolean forwards; private boolean vertically; private boolean toLimit; private PagingAction(boolean extend, boolean forwards, boolean vertically, boolean toLimit) { super(0, 0, false, extend, false); this.forwards = forwards; this.vertically = vertically; this.toLimit = toLimit; } public void actionPerformed(ActionEvent e) { JTable table = (JTable)e.getSource(); if (toLimit) { if (vertically) { int rowCount = table.getRowCount(); this.dx = 0; this.dy = forwards ? rowCount : -rowCount; } else { int colCount = table.getColumnCount(); this.dx = forwards ? colCount : -colCount; this.dy = 0; } } else { if (!(table.getParent().getParent() instanceof JScrollPane)) { return; } Dimension delta = table.getParent().getSize(); ListSelectionModel sm = (vertically) ? table.getSelectionModel() : table.getColumnModel().getSelectionModel(); int start = (extend) ? sm.getLeadSelectionIndex() : sm.getAnchorSelectionIndex(); if (vertically) { Rectangle r = table.getCellRect(start, 0, true); r.y += forwards ? delta.height : -delta.height; this.dx = 0; int newRow = table.rowAtPoint(r.getLocation()); if (newRow == -1 && forwards) { newRow = table.getRowCount(); } this.dy = newRow - start; } else { Rectangle r = table.getCellRect(0, start, true); r.x += forwards ? delta.width : -delta.width; int newColumn = table.columnAtPoint(r.getLocation()); if (newColumn == -1 && forwards) { newColumn = table.getColumnCount(); } this.dx = newColumn - start; this.dy = 0; } } super.actionPerformed(e); } } /** * Action to invoke <code>selectAll</code> on the table. */ private static class SelectAllAction extends AbstractAction { public void actionPerformed(ActionEvent e) { JTable table = (JTable)e.getSource(); table.selectAll(); } } /** * Action to invoke <code>removeEditor</code> on the table. */ private static class CancelEditingAction extends AbstractAction { public void actionPerformed(ActionEvent e) { JTable table = (JTable)e.getSource(); table.removeEditor(); } } /** * Action to start editing, and pass focus to the editor. */ private static class StartEditingAction extends AbstractAction { public void actionPerformed(ActionEvent e) { JTable table = (JTable)e.getSource(); if (!table.hasFocus()) { CellEditor cellEditor = table.getCellEditor(); if (cellEditor != null && !cellEditor.stopCellEditing()) { return; } table.requestFocus(); return; } ListSelectionModel rsm = table.getSelectionModel(); int anchorRow = rsm.getAnchorSelectionIndex(); ListSelectionModel csm = table.getColumnModel().getSelectionModel(); int anchorColumn = csm.getAnchorSelectionIndex(); table.editCellAt(anchorRow, anchorColumn); Component editorComp = table.getEditorComponent(); if (editorComp != null) { editorComp.requestFocus(); } } }//// The Table's Key listener// /** * This inner class is marked "public" due to a compiler bug. * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTableUI. * <p>As of Java 2 platform v1.3 this class is no longer used. * Instead <code>JTable</code> * overrides <code>processKeyBinding</code> to dispatch the event to * the current <code>TableCellEditor</code>. */ public class KeyHandler implements KeyListener { public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { KeyStroke keyStroke = KeyStroke.getKeyStroke(e.getKeyChar(), e.getModifiers()); // We register all actions using ANCESTOR_OF_FOCUSED_COMPONENT // which means that we might perform the appropriate action // in the table and then forward it to the editor if the editor // had focus. Make sure this doesn't happen by checking our // InputMaps. InputMap map = table.getInputMap(JComponent.WHEN_FOCUSED); if (map != null && map.get(keyStroke) != null) { return; } map = table.getInputMap(JComponent. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); if (map != null && map.get(keyStroke) != null) { return; } keyStroke = KeyStroke.getKeyStrokeForEvent(e); // The AWT seems to generate an unconsumed \r event when // ENTER (\n) is pressed. if (e.getKeyChar() == '\r') { return; } int anchorRow = table.getSelectionModel().getAnchorSelectionIndex(); int anchorColumn = table.getColumnModel().getSelectionModel().getAnchorSelectionIndex(); if (anchorRow != -1 && anchorColumn != -1 && !table.isEditing()) { if (!table.editCellAt(anchorRow, anchorColumn)) { return; } } // Forwarding events this way seems to put the component // in a state where it believes it has focus. In reality // the table retains focus - though it is difficult for // a user to tell, since the caret is visible and flashing. // Calling table.requestFocus() here, to get the focus back to // the table, seems to have no effect. Component editorComp = table.getEditorComponent(); if (table.isEditing() && editorComp != null) { if (editorComp instanceof JComponent) { JComponent component = (JComponent)editorComp; map = component.getInputMap(JComponent.WHEN_FOCUSED); Object binding = (map != null) ? map.get(keyStroke) : null; if (binding == null) { map = component.getInputMap(JComponent. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); binding = (map != null) ? map.get(keyStroke) : null; } if (binding != null) { ActionMap am = component.getActionMap(); Action action = (am != null) ? am.get(binding) : null; if (action != null && SwingUtilities. notifyAction(action, keyStroke, e, component, e.getModifiers())) { e.consume(); } } } } } }//// The Table's focus listener// /** * This inner class is marked "public" due to a compiler bug. * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTableUI. */ public class FocusHandler implements FocusListener { private void repaintAnchorCell( ) { int rc = table.getRowCount(); int cc = table.getColumnCount(); int ar = table.getSelectionModel().getAnchorSelectionIndex(); int ac = table.getColumnModel().getSelectionModel().getAnchorSelectionIndex(); if (ar < 0 || ar >= rc || ac < 0 || ac >= cc) { return; } Rectangle dirtyRect = table.getCellRect(ar, ac, false); table.repaint(dirtyRect); } public void focusGained(FocusEvent e) { repaintAnchorCell(); } public void focusLost(FocusEvent e) { repaintAnchorCell(); } }//// The Table's mouse and mouse motion listeners// /** * This inner class is marked "public" due to a compiler bug. * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of BasicTableUI. */ public class MouseInputHandler implements MouseInputListener { // Component receiving mouse events during editing. // May not be editorComponent. private Component dispatchComponent; private boolean selectedOnPress;// The Table's mouse listener methods.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -