📄 basiclistui.java
字号:
sm.removeIndexInterval(e.getIndex0(), e.getIndex1()); } /* Repaint the entire list, from the origin of * the first removed cell, to the bottom of the * component. */ redrawList(); } public void contentsChanged(ListDataEvent e) { updateLayoutStateNeeded = modelChanged; redrawList(); } } /** * Creates an instance of ListDataListener that's added to * the JLists by model as needed. Subclasses can override * this method to return a custom ListDataListener, e.g. * <pre> * class MyListUI extends BasicListUI { * protected ListDataListener <b>createListDataListener</b>() { * return new MyListDataListener(); * } * public class MyListDataListener extends ListDataHandler { * public void contentsChanged(ListDataEvent e) { * // do some extra work when the models contents change * super.contentsChange(e); * } * } * } * </pre> * * @see ListDataListener * @see JList#getModel * @see #installUI */ protected ListDataListener createListDataListener() { return new ListDataHandler(); } /** * The PropertyChangeListener that's added to the JList at * installUI time. When the value of a JList property that * affects layout changes, we set a bit in updateLayoutStateNeeded. * If the JLists model changes we additionally remove our listeners * from the old model. Likewise for the JList selectionModel. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @see #maybeUpdateLayoutState * @see #createPropertyChangeListener * @see #installUI */ public class PropertyChangeHandler implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent e) { String propertyName = e.getPropertyName(); /* If the JList.model property changes, remove our listener, * listDataListener from the old model and add it to the new one. */ if (propertyName.equals("model")) { ListModel oldModel = (ListModel)e.getOldValue(); ListModel newModel = (ListModel)e.getNewValue(); if (oldModel != null) { oldModel.removeListDataListener(listDataListener); } if (newModel != null) { newModel.addListDataListener(listDataListener); } updateLayoutStateNeeded |= modelChanged; redrawList(); } /* If the JList.selectionModel property changes, remove our listener, * listSelectionListener from the old selectionModel and add it to the new one. */ else if (propertyName.equals("selectionModel")) { ListSelectionModel oldModel = (ListSelectionModel)e.getOldValue(); ListSelectionModel newModel = (ListSelectionModel)e.getNewValue(); if (oldModel != null) { oldModel.removeListSelectionListener(listSelectionListener); } if (newModel != null) { newModel.addListSelectionListener(listSelectionListener); } updateLayoutStateNeeded |= modelChanged; redrawList(); } else if (propertyName.equals("cellRenderer")) { updateLayoutStateNeeded |= cellRendererChanged; redrawList(); } else if (propertyName.equals("font")) { updateLayoutStateNeeded |= fontChanged; redrawList(); } else if (propertyName.equals("prototypeCellValue")) { updateLayoutStateNeeded |= prototypeCellValueChanged; redrawList(); } else if (propertyName.equals("fixedCellHeight")) { updateLayoutStateNeeded |= fixedCellHeightChanged; redrawList(); } else if (propertyName.equals("fixedCellWidth")) { updateLayoutStateNeeded |= fixedCellWidthChanged; redrawList(); } else if (propertyName.equals("cellRenderer")) { updateLayoutStateNeeded |= cellRendererChanged; redrawList(); } else if (propertyName.equals("selectionForeground")) { list.repaint(); } else if (propertyName.equals("selectionBackground")) { list.repaint(); } else if ("layoutOrientation".equals(propertyName)) { updateLayoutStateNeeded |= layoutOrientationChanged; layoutOrientation = list.getLayoutOrientation(); redrawList(); } else if ("visibleRowCount".equals(propertyName)) { if (layoutOrientation != JList.VERTICAL) { updateLayoutStateNeeded |= layoutOrientationChanged; redrawList(); } } else if ("componentOrientation".equals(propertyName)) { updateLayoutStateNeeded |= componentOrientationChanged; redrawList(); InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, inputMap); } else if ("transferHandler".equals(propertyName)) { DropTarget dropTarget = list.getDropTarget(); if (dropTarget instanceof UIResource) { try { dropTarget.addDropTargetListener(new ListDropTargetListener()); } catch (TooManyListenersException tmle) { // should not happen... swing drop target is multicast } } } } } /** * Creates an instance of PropertyChangeHandler that's added to * the JList by installUI(). Subclasses can override this method * to return a custom PropertyChangeListener, e.g. * <pre> * class MyListUI extends BasicListUI { * protected PropertyChangeListener <b>createPropertyChangeListener</b>() { * return new MyPropertyChangeListener(); * } * public class MyPropertyChangeListener extends PropertyChangeHandler { * public void propertyChange(PropertyChangeEvent e) { * if (e.getPropertyName().equals("model")) { * // do some extra work when the model changes * } * super.propertyChange(e); * } * } * } * </pre> * * @see PropertyChangeListener * @see #installUI */ protected PropertyChangeListener createPropertyChangeListener() { return new PropertyChangeHandler(); } /** * Creates an instance of KeyHandler that's added to * the JList by installUI(). */ private KeyListener createKeyListener() { return new KeyHandler(); } private static class KeyHandler implements KeyListener { private String prefix = ""; private long lastTime = 0L; /** * Invoked when a key has been typed. * * Moves the keyboard focus to the first element * whose first letter matches the alphanumeric key * pressed by the user. Subsequent same key presses * move the keyboard focus to the next object that * starts with the same letter. */ public void keyTyped(KeyEvent e) { JList src = (JList)e.getSource(); ListModel model = src.getModel(); if (model.getSize() == 0 || e.isAltDown() || e.isControlDown() || e.isMetaDown()) { // Nothing to select return; } boolean startingFromSelection = true; char c = e.getKeyChar(); long time = e.getWhen(); int startIndex; if (time - lastTime < 1000L && (prefix.length() != 1 || c != prefix.charAt(0))) { prefix += c; startIndex = src.getSelectedIndex(); } else { prefix = "" + c; startIndex = src.getSelectedIndex() + 1; } lastTime = time; if (startIndex < 0 || startIndex >= model.getSize()) { startingFromSelection = false; startIndex = 0; } int index = src.getNextMatch(prefix, startIndex, Position.Bias.Forward); if (index >= 0) { src.setSelectedIndex(index); } else if (startingFromSelection) { // wrap index = src.getNextMatch(prefix, 0, Position.Bias.Forward); if (index >= 0) { src.setSelectedIndex(index); } } } /** * Invoked when a key has been pressed. */ public void keyPressed(KeyEvent e) { } /** * Invoked when a key has been released. * See the class description for {@link KeyEvent} for a definition of * a key released event. */ public void keyReleased(KeyEvent e) { } } // Keyboard navigation actions. // NOTE: DefaultListSelectionModel.setAnchorSelectionIndex and // DefaultListSelectionModel.setLeadSelectionIndex both force the // new index to be selected. Because of this not all the bindings // could be appropriately implemented. Specifically those that // change the lead/anchor without selecting are not enabled. // Once this has been fixed the following actions will appropriately // work with selectionType == CHANGE_LEAD. /** Used by IncrementLeadSelectionAction. Indicates the action should * change the lead, and not select it. */ private static final int CHANGE_LEAD = 0; /** Used by IncrementLeadSelectionAction. Indicates the action should * change the selection and lead. */ private static final int CHANGE_SELECTION = 1; /** Used by IncrementLeadSelectionAction. Indicates the action should * extend the selection from the anchor to the next index. */ private static final int EXTEND_SELECTION = 2; /** * Action to increment the selection in the list up/down a row at * a type. This also has the option to extend the selection, or * only move the lead. */ private static class IncrementLeadSelectionAction extends AbstractAction { /** Amount to offset, subclasses will define what this means. */ protected int amount; /** One of CHANGE_LEAD, CHANGE_SELECTION or EXTEND_SELECTION. */ protected int selectionType; protected IncrementLeadSelectionAction(String name, int type) { this(name, type, -1); } protected IncrementLeadSelectionAction(String name, int type, int amount) { super(name); this.amount = amount; this.selectionType = type; } /** * Returns the next index to select. This is based on the lead * selected index and the <code>amount</code> ivar. */ protected int getNextIndex(JList list) { int index = list.getLeadSelectionIndex(); int size = list.getModel().getSize(); if (index == -1) { if (size > 0) { if (amount > 0) { index = 0; } else { index = size - 1; } } } else { index += getAmount(list); } return index; } /** * Returns the amount to increment by. */ protected int getAmount(JList list) { if (list.getLayoutOrientation() == JList.HORIZONTAL_WRAP) { ListUI ui = list.getUI(); if (ui instanceof BasicListUI) { return ((BasicListUI)ui).columnCount * amount; } } return amount; } /** * Ensures the particular index is visible. This simply forwards * the method to list. */ protected void ensureIndexIsVisible(JList list, int index) { list.ensureIndexIsVisible(index); } /** * Invokes <code>getNextIndex</code> to determine the next index * to select. If the index is valid (not -1 and < size of the model), * this will either: move the selection to the new index if * the selectionType == CHANGE_SELECTION, move the lead to the * new index if selectionType == CHANGE_LEAD, otherwise the * selection is extend from the anchor to the new index and the * lead is set to the new index. */ public void actionPerformed(ActionEvent e) { JList list = (JList)e.getSource(); int index = getNextIndex(list); if (index >= 0 && index < list.getModel().getSize()) { ListSelectionModel lsm = list.getSelectionModel(); if (selectionType == EXTEND_SELECTION) { /* The following block is supposed to handle the case when the control modifier is used to move the lead without changing the selection. The DefaultListSelectionModel needs a new property here, to change the behavior of "setLeadSelectionIndex" so that it does not adjust the selection. Until then, this cannot be implemented properly and we will remove this code altogether to fix bug #4317662. */ /* int anchor = lsm.getAnchorSelectionIndex(); if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -