📄 basiclistui.java
字号:
/* * @(#)BasicListUI.java 1.93 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.*;import javax.swing.event.*;import javax.swing.plaf.*;import javax.swing.text.Position;import java.awt.*;import java.awt.event.*;import java.awt.datatransfer.Transferable;import java.awt.dnd.*;import java.util.ArrayList;import java.util.TooManyListenersException;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;/** * A Windows L&F implementation of ListUI. * <p> * * @version 1.93 01/23/03 * @author Hans Muller * @author Philip Milne */public class BasicListUI extends ListUI{ protected JList list = null; protected CellRendererPane rendererPane; // Listeners that this UI attaches to the JList protected FocusListener focusListener; protected MouseInputListener mouseInputListener; protected ListSelectionListener listSelectionListener; protected ListDataListener listDataListener; protected PropertyChangeListener propertyChangeListener; private KeyListener keyListener; // PENDING(hmuller) need a doc pointer to #getRowHeight, #maybeUpdateLayoutState protected int[] cellHeights = null; protected int cellHeight = -1; protected int cellWidth = -1; protected int updateLayoutStateNeeded = modelChanged; /** * Height of the list. When asked to paint, if the current size of * the list differs, this will update the layout state. */ private int listHeight; /** * Width of the list. When asked to paint, if the current size of * the list differs, this will update the layout state. */ private int listWidth; /** * The layout orientation of the list. */ private int layoutOrientation; // Following ivars are used if the list is laying out horizontally /** * Number of columns to create. */ private int columnCount; /** * Preferred height to make the list, this is only used if the * the list is layed out horizontally. */ private int preferredHeight; /** * Number of rows per column. This is only used if the row height is * fixed. */ private int rowsPerColumn; /* The bits below define JList property changes that affect layout. * When one of these properties changes we set a bit in * updateLayoutStateNeeded. The change is dealt with lazily, see * maybeUpdateLayoutState. Changes to the JLists model, e.g. the * models length changed, are handled similarly, see DataListener. */ protected final static int modelChanged = 1 << 0; protected final static int selectionModelChanged = 1 << 1; protected final static int fontChanged = 1 << 2; protected final static int fixedCellWidthChanged = 1 << 3; protected final static int fixedCellHeightChanged = 1 << 4; protected final static int prototypeCellValueChanged = 1 << 5; protected final static int cellRendererChanged = 1 << 6; private final static int layoutOrientationChanged = 1 << 7; private final static int heightChanged = 1 << 8; private final static int widthChanged = 1 << 9; private final static int componentOrientationChanged = 1 << 10; /** * Paint one List cell: compute the relevant state, get the "rubber stamp" * cell renderer component, and then use the CellRendererPane to paint it. * Subclasses may want to override this method rather than paint(). * * @see #paint */ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRenderer cellRenderer, ListModel dataModel, ListSelectionModel selModel, int leadIndex) { Object value = dataModel.getElementAt(row); boolean cellHasFocus = list.hasFocus() && (row == leadIndex); boolean isSelected = selModel.isSelectedIndex(row); Component rendererComponent = cellRenderer.getListCellRendererComponent(list, value, row, isSelected, cellHasFocus); int cx = rowBounds.x; int cy = rowBounds.y; int cw = rowBounds.width; int ch = rowBounds.height; rendererPane.paintComponent(g, rendererComponent, list, cx, cy, cw, ch, true); } /** * Paint the rows that intersect the Graphics objects clipRect. This * method calls paintCell as necessary. Subclasses * may want to override these methods. * * @see #paintCell */ public void paint(Graphics g, JComponent c) { switch (layoutOrientation) { case JList.VERTICAL_WRAP: if (list.getHeight() != listHeight) { updateLayoutStateNeeded |= heightChanged; redrawList(); } break; case JList.HORIZONTAL_WRAP: if (list.getWidth() != listWidth) { updateLayoutStateNeeded |= widthChanged; redrawList(); } break; default: break; } maybeUpdateLayoutState(); ListCellRenderer renderer = list.getCellRenderer(); ListModel dataModel = list.getModel(); ListSelectionModel selModel = list.getSelectionModel(); int size; if ((renderer == null) || (size = dataModel.getSize()) == 0) { return; } // Determine how many columns we need to paint Rectangle paintBounds = g.getClipBounds(); int startColumn, endColumn; if (c.getComponentOrientation().isLeftToRight()) { startColumn = convertLocationToColumn(paintBounds.x, paintBounds.y); endColumn = convertLocationToColumn(paintBounds.x + paintBounds.width, paintBounds.y); } else { startColumn = convertLocationToColumn(paintBounds.x + paintBounds.width, paintBounds.y); endColumn = convertLocationToColumn(paintBounds.x, paintBounds.y); } int maxY = paintBounds.y + paintBounds.height; int leadIndex = list.getLeadSelectionIndex(); int rowIncrement = (layoutOrientation == JList.HORIZONTAL_WRAP) ? columnCount : 1; for (int colCounter = startColumn; colCounter <= endColumn; colCounter++) { // And then how many rows in this columnn int row = convertLocationToRowInColumn(paintBounds.y, colCounter); int rowCount = getRowCount(colCounter); int index = getModelIndex(colCounter, row); Rectangle rowBounds = getCellBounds(list, index, index); if (rowBounds == null) { // Not valid, bail! return; } while (row < rowCount && rowBounds.y < maxY && index < size) { rowBounds.height = getHeight(colCounter, row); g.setClip(rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height); g.clipRect(paintBounds.x, paintBounds.y, paintBounds.width, paintBounds.height); paintCell(g, index, rowBounds, renderer, dataModel, selModel, leadIndex); rowBounds.y += rowBounds.height; index += rowIncrement; row++; } } } /** * The preferredSize of the list depends upon the layout orientation. * <table summary="Describes the preferred size for each layout orientation"> * <tr><th>Layout Orientation</th><th>Preferred Size</th></tr> * <tr> * <td>JList.VERTICAL * <td>The preferredSize of the list is total height of the rows * and the maximum width of the cells. If JList.fixedCellHeight * is specified then the total height of the rows is just * (cellVerticalMargins + fixedCellHeight) * model.getSize() where * rowVerticalMargins is the space we allocate for drawing * the yellow focus outline. Similarly if fixedCellWidth is * specified then we just use that. * </td> * <tr> * <td>JList.VERTICAL_WRAP * <td>If the visible row count is greater than zero, the preferredHeight * is the maximum cell height * visibleRowCount. If the visible row * count is <= 0, the preferred height is either the current height * of the list, or the maximum cell height, whichever is * bigger. The preferred width is than the maximum cell width * * number of columns needed. Where the number of columns needs is * list.height / max cell height. Max cell height is either the fixed * cell height, or is determined by iterating through all the cells * to find the maximum height from the ListCellRenderer. * <tr> * <td>JList.HORIZONTAL_WRAP * <td>If the visible row count is greater than zero, the preferredHeight * is the maximum cell height * adjustedRowCount. Where * visibleRowCount is used to determine the number of columns. * Because this lays out horizontally the number of rows is * then determined from the column count. For example, lets say * you have a model with 10 items and the visible row count is 8. * The number of columns needed to display this is 2, but you no * longer need 8 rows to display this, you only need 5, thus * the adjustedRowCount is 5. * <p>If the visible row * count is <= 0, the preferred height is dictated by the * number of columns, which will be as many as can fit in the width * of the <code>JList</code> (width / max cell width), with at * least one column. The preferred height then becomes the * model size / number of columns * maximum cell height. * Max cell height is either the fixed * cell height, or is determined by iterating through all the cells * to find the maximum height from the ListCellRenderer. * </table> * The above specifies the raw preferred width and height. The resulting * preferred width is the above width + insets.left + insets.right and * the resulting preferred height is the above height + insets.top + * insets.bottom. Where the <code>Insets</code> are determined from * <code>list.getInsets()</code>. * * @param c The JList component. * @return The total size of the list. */ public Dimension getPreferredSize(JComponent c) { maybeUpdateLayoutState(); int lastRow = list.getModel().getSize() - 1; if (lastRow < 0) { return new Dimension(0, 0); } Insets insets = list.getInsets(); int width = cellWidth * columnCount + insets.left + insets.right; int height; if (layoutOrientation != JList.VERTICAL) { height = preferredHeight; } else { Rectangle bounds = getCellBounds(list, lastRow); if (bounds != null) { height = bounds.y + bounds.height + insets.bottom; } else { height = 0; } } return new Dimension(width, height); } /** * @return the preferred size * @see #getPreferredSize */ public Dimension getMinimumSize(JComponent c) { return getPreferredSize(c); } /** * @return the preferred size * @see #getPreferredSize */ public Dimension getMaximumSize(JComponent c) { return getPreferredSize(c); } /** * Selected the previous row and force it to be visible. * * @see JList#ensureIndexIsVisible */ protected void selectPreviousIndex() { int s = list.getSelectedIndex(); if(s > 0) { s -= 1; list.setSelectedIndex(s); list.ensureIndexIsVisible(s); } } /** * Selected the previous row and force it to be visible. * * @see JList#ensureIndexIsVisible */ protected void selectNextIndex() { int s = list.getSelectedIndex(); if((s + 1) < list.getModel().getSize()) { s += 1; list.setSelectedIndex(s); list.ensureIndexIsVisible(s); } } /** * Registers the keyboard bindings on the <code>JList</code> that the * <code>BasicListUI</code> is associated with. This method is called at * installUI() time. * * @see #installUI */ protected void installKeyboardActions() { InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, inputMap); ActionMap map = getActionMap(); if (map != null) { SwingUtilities.replaceUIActionMap(list, map); } } InputMap getInputMap(int condition) { if (condition == JComponent.WHEN_FOCUSED) { InputMap keyMap = (InputMap)UIManager.get("List.focusInputMap"); InputMap rtlKeyMap; if (list.getComponentOrientation().isLeftToRight() || ((rtlKeyMap = (InputMap)UIManager.get("List.focusInputMap.RightToLeft")) == null)) { return keyMap; } else { rtlKeyMap.setParent(keyMap); return rtlKeyMap; } } return null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -