| Method from javax.swing.plaf.basic.BasicListUI Detail: |
protected int convertRowToY(int row) {
int y = 0;
for (int i = 0; i < row; ++i)
{
int h = getRowHeight(i);
if (h == -1)
return -1;
y += h;
}
return y;
}
Calculate the Y coordinate of the upper edge of a particular row,
considering the Y coordinate 0 to occur at the top of the
list. |
protected int convertYToRow(int y0) {
if (list.getModel().getSize() == 0)
return -1;
// When y0 < 0, then the JDK returns the maximum row index of the list. So
// do we.
if (y0 < 0)
return list.getModel().getSize() - 1;
// Update the layout if necessary.
maybeUpdateLayoutState();
int index = list.getModel().getSize() - 1;
// If a fixed cell height is set, then we can work more efficient.
if (cellHeight > 0)
index = Math.min(y0 / cellHeight, index);
// If we have no fixed cell height, we must add up each cell height up
// to y0.
else
{
int h = 0;
for (int row = 0; row < cellHeights.length; ++row)
{
h += cellHeights[row];
if (y0 < h)
{
index = row;
break;
}
}
}
return index;
}
Calculate the row number containing a particular Y coordinate,
considering the Y coodrinate 0 to occur at the top of the
list. |
protected FocusListener createFocusListener() {
return new FocusHandler();
}
Creates and returns the focus listener for this UI. |
protected ListDataListener createListDataListener() {
return new ListDataHandler();
}
Creates and returns the list data listener for this UI. |
protected ListSelectionListener createListSelectionListener() {
return new ListSelectionHandler();
}
Creates and returns the list selection listener for this UI. |
protected MouseInputListener createMouseInputListener() {
return new MouseInputHandler();
}
Creates and returns the mouse input listener for this UI. |
protected PropertyChangeListener createPropertyChangeListener() {
return new PropertyChangeHandler();
}
Creates and returns the property change listener for this UI. |
public static ComponentUI createUI(JComponent c) {
return new BasicListUI();
}
Creates a new BasicListUI for the component. |
public Rectangle getCellBounds(JList l,
int index1,
int index2) {
maybeUpdateLayoutState();
if (l != list || cellWidth == -1)
return null;
int minIndex = Math.min(index1, index2);
int maxIndex = Math.max(index1, index2);
Point loc = indexToLocation(list, minIndex);
// When the layoutOrientation is VERTICAL, then the width == the list
// width. Otherwise the cellWidth field is used.
int width = cellWidth;
if (l.getLayoutOrientation() == JList.VERTICAL)
width = l.getWidth();
Rectangle bounds = new Rectangle(loc.x, loc.y, width,
getCellHeight(minIndex));
for (int i = minIndex + 1; i < = maxIndex; i++)
{
Point hiLoc = indexToLocation(list, i);
bounds = SwingUtilities.computeUnion(hiLoc.x, hiLoc.y, width,
getCellHeight(i), bounds);
}
return bounds;
}
Calculate the bounds of a particular cell, considering the upper left
corner of the list as the origin position (0,0). |
public Dimension getPreferredSize(JComponent c) {
maybeUpdateLayoutState();
int size = list.getModel().getSize();
int visibleRows = list.getVisibleRowCount();
int layoutOrientation = list.getLayoutOrientation();
int h;
int w;
int maxCellHeight = cellHeight;
if (maxCellHeight < = 0)
{
for (int i = 0; i < cellHeights.length; i++)
maxCellHeight = Math.max(maxCellHeight, cellHeights[i]);
}
if (layoutOrientation == JList.HORIZONTAL_WRAP)
{
if (visibleRows > 0)
{
// We cast to double here to force double divisions.
double modelSize = size;
int neededColumns = (int) Math.ceil(modelSize / visibleRows);
int adjustedRows = (int) Math.ceil(modelSize / neededColumns);
h = maxCellHeight * adjustedRows;
w = cellWidth * neededColumns;
}
else
{
int neededColumns = Math.min(1, list.getWidth() / cellWidth);
h = size / neededColumns * maxCellHeight;
w = neededColumns * cellWidth;
}
}
else if (layoutOrientation == JList.VERTICAL_WRAP)
{
if (visibleRows > 0)
h = visibleRows * maxCellHeight;
else
h = Math.max(list.getHeight(), maxCellHeight);
int neededColumns = h / maxCellHeight;
w = cellWidth * neededColumns;
}
else
{
if (list.getFixedCellWidth() > 0)
w = list.getFixedCellWidth();
else
w = cellWidth;
if (list.getFixedCellHeight() > 0)
// FIXME: We need to add some cellVerticalMargins here, according
// to the specs.
h = list.getFixedCellHeight() * size;
else
h = maxCellHeight * size;
}
Insets insets = list.getInsets();
Dimension retVal = new Dimension(w + insets.left + insets.right,
h + insets.top + insets.bottom);
return retVal;
}
Gets the size this list would prefer to assume. This is calculated by
calling #getCellBounds over the entire list. |
protected int getRowHeight(int row) {
int height;
if (cellHeights == null)
height = cellHeight;
else
{
if (row < 0 || row >= cellHeights.length)
height = -1;
else
height = cellHeights[row];
}
return height;
}
Calculate the height of a particular row. If there is a fixed #cellHeight , return it; otherwise return the specific row height
requested from the #cellHeights array. If the requested row
is invalid, return -1. |
public Point indexToLocation(JList l,
int index) {
int layoutOrientation = list.getLayoutOrientation();
Point loc = null;
switch (layoutOrientation)
{
case JList.VERTICAL:
loc = new Point(0, convertRowToY(index));
break;
case JList.HORIZONTAL_WRAP:
// determine visible rows and cells per row
int maxCellHeight = getCellHeight(0);
int visibleRows = list.getHeight() / maxCellHeight;
int numberOfCellsPerRow = -1;
int numberOfItems = list.getModel().getSize();
numberOfCellsPerRow = numberOfItems / visibleRows + 1;
// compute coordinates inside the grid
int gridX = index % numberOfCellsPerRow;
int gridY = index / numberOfCellsPerRow;
int locX = gridX * cellWidth;
int locY;
locY = gridY * maxCellHeight;
loc = new Point(locX, locY);
break;
case JList.VERTICAL_WRAP:
// determine visible rows and cells per column
int maxCellHeight2 = getCellHeight(0);
int visibleRows2 = list.getHeight() / maxCellHeight2;
// compute coordinates inside the grid
if (visibleRows2 > 0)
{
int gridY2 = index % visibleRows2;
int gridX2 = index / visibleRows2;
int locX2 = gridX2 * cellWidth;
int locY2 = gridY2 * maxCellHeight2;
loc = new Point(locX2, locY2);
}
else
loc = new Point(0, convertRowToY(index));
break;
}
return loc;
}
|
protected void installDefaults() {
LookAndFeel.installColorsAndFont(list, "List.background",
"List.foreground", "List.font");
list.setSelectionForeground(UIManager.getColor("List.selectionForeground"));
list.setSelectionBackground(UIManager.getColor("List.selectionBackground"));
list.setOpaque(true);
}
Installs various default settings (mostly colors) from the UIDefaults into the JList |
protected void installKeyboardActions() {
InputMap focusInputMap = (InputMap) UIManager.get("List.focusInputMap");
InputMapUIResource parentInputMap = new InputMapUIResource();
// FIXME: The JDK uses a LazyActionMap for parentActionMap
ActionMap parentActionMap = new ActionMapUIResource();
action = new ListAction();
Object keys[] = focusInputMap.allKeys();
// Register key bindings in the UI InputMap-ActionMap pair
for (int i = 0; i < keys.length; i++)
{
KeyStroke stroke = (KeyStroke)keys[i];
String actionString = (String) focusInputMap.get(stroke);
parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
stroke.getModifiers()),
actionString);
parentActionMap.put (actionString,
new ActionListenerProxy(action, actionString));
}
// Register the new InputMap-ActionMap as the parents of the list's
// InputMap and ActionMap
parentInputMap.setParent(list.getInputMap().getParent());
parentActionMap.setParent(list.getActionMap().getParent());
list.getInputMap().setParent(parentInputMap);
list.getActionMap().setParent(parentActionMap);
}
Installs keyboard actions for this UI in the JList . |
protected void installListeners() {
if (focusListener == null)
focusListener = createFocusListener();
list.addFocusListener(focusListener);
if (listDataListener == null)
listDataListener = createListDataListener();
list.getModel().addListDataListener(listDataListener);
if (listSelectionListener == null)
listSelectionListener = createListSelectionListener();
list.addListSelectionListener(listSelectionListener);
if (mouseInputListener == null)
mouseInputListener = createMouseInputListener();
list.addMouseListener(mouseInputListener);
list.addMouseMotionListener(mouseInputListener);
if (propertyChangeListener == null)
propertyChangeListener = createPropertyChangeListener();
list.addPropertyChangeListener(propertyChangeListener);
}
Attaches all the listeners we have in the UI class to the JList , its model and its selection model. |
public void installUI(JComponent c) {
super.installUI(c);
list = (JList) c;
installDefaults();
installListeners();
installKeyboardActions();
maybeUpdateLayoutState();
}
|
public int locationToIndex(JList l,
Point location) {
int layoutOrientation = list.getLayoutOrientation();
int index = -1;
switch (layoutOrientation)
{
case JList.VERTICAL:
index = convertYToRow(location.y);
break;
case JList.HORIZONTAL_WRAP:
// determine visible rows and cells per row
int maxCellHeight = getCellHeight(0);
int visibleRows = list.getHeight() / maxCellHeight;
int cellsPerRow = -1;
int numberOfItems = list.getModel().getSize();
cellsPerRow = numberOfItems / visibleRows + 1;
// determine index for the given location
int cellsPerColumn = numberOfItems / cellsPerRow + 1;
int gridX = Math.min(location.x / cellWidth, cellsPerRow - 1);
int gridY = Math.min(location.y / maxCellHeight, cellsPerColumn);
index = gridX + gridY * cellsPerRow;
break;
case JList.VERTICAL_WRAP:
// determine visible rows and cells per column
int maxCellHeight2 = getCellHeight(0);
int visibleRows2 = list.getHeight() / maxCellHeight2;
int numberOfItems2 = list.getModel().getSize();
int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1;
int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1);
int gridY2 = Math.min(location.y / maxCellHeight2, visibleRows2);
index = gridY2 + gridX2 * visibleRows2;
break;
}
return index;
}
Computes the index of a list cell given a point within the list. If the
location lies outside the bounds of the list, the greatest index in the
list model is returned. |
protected void maybeUpdateLayoutState() {
if (updateLayoutStateNeeded != 0)
{
updateLayoutState();
updateLayoutStateNeeded = 0;
}
}
|
public void paint(Graphics g,
JComponent c) {
int nrows = list.getModel().getSize();
if (nrows == 0)
return;
maybeUpdateLayoutState();
ListCellRenderer render = list.getCellRenderer();
ListModel model = list.getModel();
ListSelectionModel sel = list.getSelectionModel();
int lead = sel.getLeadSelectionIndex();
Rectangle clip = g.getClipBounds();
int startIndex = locationToIndex(list, new Point(clip.x, clip.y));
int endIndex = locationToIndex(list, new Point(clip.x + clip.width,
clip.y + clip.height));
for (int row = startIndex; row < = endIndex; ++row)
{
Rectangle bounds = getCellBounds(list, row, row);
if (bounds != null && bounds.intersects(clip))
paintCell(g, row, bounds, render, model, sel, lead);
}
}
Paints the list by repeatedly calling #paintCell for each visible
cell in the list. |
protected void paintCell(Graphics g,
int row,
Rectangle bounds,
ListCellRenderer rend,
ListModel data,
ListSelectionModel sel,
int lead) {
boolean isSel = list.isSelectedIndex(row);
boolean hasFocus = (list.getLeadSelectionIndex() == row) && BasicListUI.this.list.hasFocus();
Component comp = rend.getListCellRendererComponent(list,
data.getElementAt(row),
0, isSel, hasFocus);
rendererPane.paintComponent(g, comp, list, bounds);
}
Paints a single cell in the list. |
protected void selectNextIndex() {
int index = list.getSelectionModel().getLeadSelectionIndex();
if (index < list.getModel().getSize() - 1)
{
index++;
list.setSelectedIndex(index);
}
list.ensureIndexIsVisible(index);
}
Selects the next list item and force it to be visible. |
protected void selectPreviousIndex() {
int index = list.getSelectionModel().getLeadSelectionIndex();
if (index > 0)
{
index--;
list.setSelectedIndex(index);
}
list.ensureIndexIsVisible(index);
}
Selects the previous list item and force it to be visible. |
protected void uninstallDefaults() {
list.setForeground(null);
list.setBackground(null);
list.setSelectionForeground(null);
list.setSelectionBackground(null);
}
|
protected void uninstallKeyboardActions() throws NotImplementedException {
// TODO: Implement this properly.
}
Uninstalls keyboard actions for this UI in the JList . |
protected void uninstallListeners() {
list.removeFocusListener(focusListener);
list.getModel().removeListDataListener(listDataListener);
list.removeListSelectionListener(listSelectionListener);
list.removeMouseListener(mouseInputListener);
list.removeMouseMotionListener(mouseInputListener);
list.removePropertyChangeListener(propertyChangeListener);
}
|
public void uninstallUI(JComponent c) {
uninstallKeyboardActions();
uninstallListeners();
uninstallDefaults();
list = null;
}
Uninstalls all the aspects of the UI which were installed in #installUI . When finished uninstalling, drops the saved reference to
the JList . |
protected void updateLayoutState() {
int nrows = list.getModel().getSize();
cellHeight = -1;
cellWidth = -1;
if (cellHeights == null || cellHeights.length != nrows)
cellHeights = new int[nrows];
ListCellRenderer rend = list.getCellRenderer();
// Update the cellHeight(s) fields.
int fixedCellHeight = list.getFixedCellHeight();
if (fixedCellHeight > 0)
{
cellHeight = fixedCellHeight;
cellHeights = null;
}
else
{
cellHeight = -1;
for (int i = 0; i < nrows; ++i)
{
Component flyweight =
rend.getListCellRendererComponent(list,
list.getModel().getElementAt(i),
i, list.isSelectedIndex(i),
list.getSelectionModel().getAnchorSelectionIndex() == i);
Dimension dim = flyweight.getPreferredSize();
cellHeights[i] = dim.height;
}
}
// Update the cellWidth field.
int fixedCellWidth = list.getFixedCellWidth();
if (fixedCellWidth > 0)
cellWidth = fixedCellWidth;
else
{
for (int i = 0; i < nrows; ++i)
{
Component flyweight =
rend.getListCellRendererComponent(list,
list.getModel().getElementAt(i),
i, list.isSelectedIndex(i),
list.getSelectionModel().getAnchorSelectionIndex() == i);
Dimension dim = flyweight.getPreferredSize();
cellWidth = Math.max(cellWidth, dim.width);
}
}
}
|