alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.awt;

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.*;


/** ListPane. This component is derived from JList component and enables
 * list objects in several columns.
 *
 * @author   Petr Hamernik, Ian Formanek, Jaroslav Tulach
 * @deprecated This class does nothing interesting which cannot be
 * done in a more reliable, scalable way with a JTable.
 */
public class ListPane extends JList {
    /** generated Serialized Version UID */
    static final long serialVersionUID = 3828318151121500783L;
    
    private int fixedCellWidth = 100;
    private int fixedCellHeight = 100;
    private int visibleRowCount = 6;
    private int visibleColumnCount = 4;
    
    private int realRowCount = 1;
    private int realColumnCount = 1;
    
    
    ListDataListener dataL;
    PropertyChangeListener propertyL;
    InputListener inputL;
    ListSelectionListener selectionL;
    
    boolean updateLayoutStateNeeded = true;
    
    /**
     * Construct a JList that displays the elements in the specified,
     * non-null model.  All JList constructors delegate to this one.
     */
    public ListPane(ListModel dataModel) {
        super (dataModel);
        
        addListListeners();
    }
    
    /**
     * Construct a JList that displays the elements in the specified
     * array.  This constructor just delegates to the ListModel
     * constructor.
     */
    public ListPane(final Object[] listData) {
        this (new AbstractListModel() {
            public int getSize() { return listData.length; }
            public Object getElementAt(int i) { return listData[i]; }
        });
    }
    
    /**
     * Construct a JList that displays the elements in the specified
     * Vector.  This constructor just delegates to the ListModel
     * constructor.
     */
    public ListPane(final Vector listData) {
        this (new AbstractListModel() {
            public int getSize() { return listData.size(); }
            public Object getElementAt(int i) { return listData.elementAt(i); }
        });
    }
    
    /**
     * Constructs a JList with an empty model.
     */
    public ListPane() {
        this (new AbstractListModel() {
            public int getSize() { return 0; }
            public Object getElementAt(int i) { return null; }
        });
    }
    
    /**
     * JList components are always opaque.
     * @return true
     */
    public boolean isOpaque() {
        return true;
    }
    
    /**
     * Return the value of the visibleRowCount property.
     * @see #setVisibleRowCount
     */
    public int getVisibleColumnCount() {
        return visibleColumnCount;
    }
    
    /**
     * Set the preferred number of rows in the list that are visible within
     * the nearest JViewport ancestor, if any.  The value of this property
     * only affects the value of the JLists preferredScrollableViewportSize.
     * 

* The default value of this property is 8. *

* This is a JavaBeans bound property. * * @see #getVisibleRowCount * @see JComponent#getVisibleRect */ public void setVisibleColumnCount(int visibleColumnCount) { int oldValue = this.visibleColumnCount; this.visibleColumnCount = Math.max(0, visibleColumnCount); firePropertyChange("visibleColumnCount", oldValue, visibleColumnCount); // NOI18N } /** * If this JList is being displayed withing a JViewport and the * specified cell isn't completely visible, scroll the viewport. * * @param index The index of the cell to make visible * @see JComponent#scrollRectToVisible * @see #getVisibleRect */ public void ensureIndexIsVisible(int index) { Point first = indexToLocation(index); if (first != null) { Rectangle cellBounds = new Rectangle(first.x, first.y, fixedCellWidth, fixedCellHeight); scrollRectToVisible(cellBounds); } } /** * Convert a point in JList coordinates to the index * of the cell at that location. Returns -1 if there's no * cell the specified location. * * @param location The JList relative coordinates of the cell * @return The index of the cell at location, or -1. */ public int locationToIndex(Point location) { int x = location.x / fixedCellWidth; if (x >= realColumnCount) return -1; int y = location.y / fixedCellHeight; if (y >= realRowCount) return -1; int ret = y * realColumnCount + x; return (ret >= getModel ().getSize()) ? -1 : ret; } /** * Returns the origin of the specified item in JList * coordinates, null if index isn't valid. * * @param index The index of the JList cell. * @return The origin of the index'th cell. */ public Point indexToLocation(int index) { if (index >= getModel ().getSize()) return null; int y = index / realColumnCount; int x = index % realColumnCount; return new Point(x * fixedCellWidth, y * fixedCellHeight); } /** * Returns the bounds of the specified item in JList * coordinates, null if index isn't valid. * * @param index1 start index of the JList cell. * @param index2 end index of the JList cell. * @return The bounds of the index'th cell. */ public Rectangle getCellBounds(int index1, int index2) { /* int minIndex = Math.min(index1, index2); int maxIndex = Math.max(index1, index2); */ Point p1 = indexToLocation(index1); Point p2 = indexToLocation(index2); int x1 = p1.x; int y1 = p1.y; int x2 = p2.x + fixedCellWidth; int y2 = p2.y + fixedCellHeight; if (p1.y != p2.y) { x1 = 0; x2 = fixedCellWidth * realColumnCount; } return new Rectangle(x1, y1, x2 - x1, y2 - y1); } /** * --- The Scrollable Implementation --- */ // @see #setPrototypeCellValue /** * Compute the size of the viewport needed to display visibleRowCount * rows. This is trivial if fixedCellWidth and fixedCellHeight * were specified. Note that they can specified implicitly with * the prototypeCellValue property. If fixedCellWidth wasn't specified, * it's computed by finding the widest list element. If fixedCellHeight * wasn't specified then we resort to heuristics: *

    *
  • * If the model isn't empty we just multiply the height of the first row * by visibleRowCount. *
  • * If the model is empty, i.e. JList.getModel().getSize() == 0, then * we just allocate 16 pixels per visible row, and 100 pixels * for the width (unless fixedCellWidth was set), and hope for the best. *
* * @see #getPreferredScrollableViewportSize */ public Dimension getPreferredScrollableViewportSize() { Insets insets = getInsets(); int w = insets.left + insets.right + visibleColumnCount * fixedCellWidth; int h = insets.top + insets.bottom + visibleRowCount * fixedCellHeight; Dimension dim = new Dimension(w, h); return dim; } /** * If we're scrolling downwards (direction is * greater than 0), and the first row is completely visible with respect * to visibleRect, then return its height. If * we're scrolling downwards and the first row is only partially visible, * return the height of the visible part of the first row. Similarly * if we're scrolling upwards we return the height of the row above * the first row, unless the first row is partially visible. * * @return The distance to scroll to expose the next or previous row. * @see Scrollable#getScrollableUnitIncrement */ public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { if (orientation == SwingConstants.HORIZONTAL) { return 1; } else { int row = getFirstVisibleIndex(); if (row == -1) return 0; else { /* Scroll Down */ if (direction > 0) { Rectangle r = getCellBounds(row, row); return (r == null) ? 0 : r.height - (visibleRect.y - r.y); } /* Scroll Up */ else { Rectangle r = getCellBounds(row, row); /* The first row is completely visible and it's row 0. * We're done. */ if ((r.y == visibleRect.y) && (row == 0)) { return 0; } /* The first row is completely visible, return the * height of the previous row. */ else if (r.y == visibleRect.y) { Rectangle prevR = getCellBounds(row - 1, row - 1); return (prevR== null) ? 0 : prevR.height; } /* The first row is partially visible, return the * height of hidden part. */ else { return visibleRect.y - r.y; } } } } } /** * @return The visibleRect.height or visibleRect.width per the orientation. * @see Scrollable#getScrollableUnitIncrement */ public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width; } /** * If this JList is displayed in a JViewport, don't change its width * when the viewports width changes. This allows horizontal * scrolling if the JViewport is itself embedded in a JScrollPane. * * @return False - don't track the viewports width. * @see Scrollable#getScrollableTracksViewportWidth */ public boolean getScrollableTracksViewportWidth() { return true; } /** * If this JList is displayed in a JViewport, don't change its height * when the viewports height changes. This allows vertical * scrolling if the JViewport is itself embedded in a JScrollPane. * * @return False - don't track the viewports width. * @see Scrollable#getScrollableTracksViewportWidth */ public boolean getScrollableTracksViewportHeight() { return false; } /** * If the list is opaque, paint its background. * Subclasses may want to override this method rather than paint(). * * @see #paint */ protected void paintBackground(Graphics g) { if (isOpaque()) { Color backup = g.getColor(); g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(backup); } } /** * 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 */ private void paintCell(Graphics g, int index) { Object value = getModel ().getElementAt(index); boolean cellHasFocus = hasFocus () && (index == getSelectionModel().getLeadSelectionIndex()); boolean isSelected = getSelectionModel ().isSelectedIndex(index); Component renderer = getCellRenderer ().getListCellRendererComponent( this, value, index, isSelected, cellHasFocus ); renderer.setSize(fixedCellWidth, fixedCellHeight); renderer.paint(g); } /** * Paint the rows that intersect the Graphics objects clipRect. This * method calls paintBackground and paintCell as necessary. Subclasses * may want to override these methods. * * @see #paintBackground */ protected void paintComponent (Graphics g) { updateLayoutState(); if (getCellRenderer () == null) return; paintBackground(g); int last = getModel().getSize(); int dx, dy; for (int i = 0; i < last; i++) { //Point p = indexToLocation(i); paintCell(g, i); if (((i+1) % realColumnCount) == 0) { dx = - fixedCellWidth * (realColumnCount - 1); dy = fixedCellHeight; } else { dx = fixedCellWidth; dy = 0; } g.translate(dx, dy); } } /** Recalculates the value of variables realRowCount and * realColumnCount. If the view needs update calls * revalidate. */ private void updateLayoutState() { Dimension d = getSize(); int x = d.width / fixedCellWidth; if (x < 1) x = 1; if (x != realColumnCount) { realColumnCount = x; updateLayoutStateNeeded = true; } int y = d.height / fixedCellHeight; if (y != realRowCount) { realRowCount = y; updateLayoutStateNeeded = true; } while (realRowCount * realColumnCount < getModel().getSize()) { realRowCount++; } locationToIndex(getVisibleRect().getLocation()); if (updateLayoutStateNeeded) { updateLayoutStateNeeded = false; revalidate(); } } /** * The preferredSize of a 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 JListfixedCellWidth is * specified then we just use that plus the horizontal margins. * * @return The total size of the */ public Dimension getPreferredSize() { Insets insets = getInsets(); /* int dx = insets.left + insets.right; int dy = insets.top + insets.bottom; */ int max = getModel().getSize() - 1; if (max <= 0) { return new Dimension(fixedCellWidth, fixedCellHeight); } int y = max / realColumnCount + 1; int x = ((max < realColumnCount) ? max+1 : realColumnCount); int xParent = getParent().getSize().width; int yParent = getParent().getSize().height; int xRes = Math.max(xParent, x * fixedCellWidth); int yRes = Math.max(yParent, y * fixedCellHeight); Dimension d = new Dimension(xRes, yRes); return d; } /** * @return the size of one cell */ public Dimension getMinimumSize() { return new Dimension(fixedCellWidth, fixedCellHeight); } /** * Create and install the listeners for the JList, its model, and its * selectionModel. This method is called at creation time. */ private void addListListeners() { inputL = createInputListener(); addMouseListener(inputL); addKeyListener(inputL); addFocusListener(inputL); /* When a property changes that effects layout we set * updateLayoutStateNeeded to the appropriate code. We also * add/remove List data model listeners when the "model" * property changes. */ propertyL = createPropertyListener(); addPropertyChangeListener(propertyL); dataL = createDataListener(); ListModel model = getModel(); if (model != null) model.addListDataListener(dataL); if (selectionL == null) { selectionL = new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { repaint (); } }; ListSelectionModel selectionModel = getSelectionModel(); if (selectionModel != null) selectionModel.addListSelectionListener(selectionL); } } // // ========== Listener inner classes =============== // private InputListener createInputListener() { return new InputListener(); } private ListDataListener createDataListener() { return new DataListener(); } // protected ListSelectionListener createSelectionListener() { // return new SelectionListener(); // } private PropertyChangeListener createPropertyListener() { return new PropertyListener(); } /** */ private void mySetSelectionInterval(int anchor, int lead) { super.setSelectionInterval(anchor, lead); } /** Sets the selection to be the union of the specified interval with current */ private void myAddSelectionInterval(int anchor, int lead) { super.addSelectionInterval(anchor, lead); } /** Sets the selection to be the set difference of the specified interval */ private void myRemoveSelectionInterval(int index0, int index1) { super.removeSelectionInterval(index0, index1); } public void setSelectionInterval(int anchor, int lead) { // super.setSelectionInterval(anchor, lead); } public void addSelectionInterval(int anchor, int lead) { // super.addSelectionInterval(anchor, lead); } public void removeSelectionInterval(int index0, int index1) { // super.removeSelectionInterval(index0, index1); } // // ------- Input Listener ------------ // /** * Mouse input, and focus handling for JList. An instance of this * class is added to the appropriate java.awt.Component lists * at creation time. Note keyboard input is handled with JComponent * KeyboardActions, see registerKeyboardActions(). * See createInputListener and registerKeyboardActions. */ private class InputListener extends MouseAdapter implements FocusListener, KeyListener, Serializable { static final long serialVersionUID =-7907848327510962576L; transient int dragFirstIndex = -1; transient int dragLastIndex = -1; InputListener() {} // ==== Mouse methods ===== public void mousePressed(MouseEvent e) { updateSelection(locationToIndex(e.getPoint()), e); if (!hasFocus ()) requestFocus(); } // ==== Focus methods ===== public void focusGained(FocusEvent e) { repaintCellFocus(); } public void focusLost(FocusEvent e) { repaintCellFocus(); } protected void repaintCellFocus() { repaint(); } // ==== Key methods ===== public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { int s = getLeadSelectionIndex(); if (s < 0) { if (getModel().getSize() > 0) s = 0; else return; } else { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: s -= 1; break; case KeyEvent.VK_RIGHT: s += 1; break; case KeyEvent.VK_UP: s -= realColumnCount; break; case KeyEvent.VK_DOWN: s += realColumnCount; break; case KeyEvent.VK_HOME: s = 0; break; case KeyEvent.VK_END: s = getModel().getSize() - 1; break; case KeyEvent.VK_PAGE_UP: s -= realColumnCount * realRowCount; break; case KeyEvent.VK_PAGE_DOWN: s += realColumnCount * realRowCount; break; default: return; } } if (s < 0) s = 0; if (s > getModel().getSize() - 1) s = getModel().getSize() - 1; if(s >= 0) { updateSelection(s, e); } } public void keyReleased(KeyEvent e) { } // ==== Update selection ===== protected void updateSelection(int index, InputEvent e) { ListSelectionModel sm = getSelectionModel(); if (index != -1) { setValueIsAdjusting(true); if (e.isShiftDown()) { if (e.isControlDown()) { if (dragFirstIndex == -1) { myAddSelectionInterval(index, index); } else { if (dragLastIndex == -1) { myAddSelectionInterval(dragFirstIndex, index); } else { myRemoveSelectionInterval(dragFirstIndex, dragLastIndex); myAddSelectionInterval(dragFirstIndex, index); } } } else { if (dragFirstIndex == -1) { myAddSelectionInterval(index, index); } else { mySetSelectionInterval(dragFirstIndex, index); } } if (dragFirstIndex == -1) { dragFirstIndex = index; dragLastIndex = -1; } else { dragLastIndex = index; } } else { if (e.isControlDown()) { if (isSelectedIndex(index)) { myRemoveSelectionInterval(index, index); } else { myAddSelectionInterval(index, index); } } else { mySetSelectionInterval(index, index); } dragFirstIndex = index; dragLastIndex = -1; } setValueIsAdjusting(false); } else { sm.clearSelection(); } } } // // ------- Data Listener ------------ // /** * The ListDataListener that's added to the JLists model at * creation time, and whenever the JList.model property changes. * See createDataListener. * * @see JList#getModel */ private class DataListener implements ListDataListener, Serializable { static final long serialVersionUID =-2252515707418441L; DataListener() {} public void intervalAdded(ListDataEvent e) { updateLayoutStateNeeded = true; int minIndex = Math.min(e.getIndex0(), e.getIndex1()); int maxIndex = Math.max(e.getIndex0(), e.getIndex1()); /* Sync the SelectionModel with the DataModel. */ ListSelectionModel sm = getSelectionModel(); if (sm != null) sm.insertIndexInterval(minIndex, maxIndex - minIndex, true); } public void intervalRemoved(ListDataEvent e) { updateLayoutStateNeeded = true; /* Sync the SelectionModel with the DataModel. */ ListSelectionModel sm = getSelectionModel(); if (sm != null) { sm.removeIndexInterval(e.getIndex0(), e.getIndex1()); } } public void contentsChanged(ListDataEvent e) { updateLayoutStateNeeded = true; } } // // ------- Property Listener ------------ // /** * The PropertyChangeListener that's added to the JList at * creation 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. * See createPropertyListener. */ private class PropertyListener implements PropertyChangeListener, Serializable { static final long serialVersionUID =-6765578311995604737L; PropertyListener() {} public void propertyChange(PropertyChangeEvent e) { String propertyName = e.getPropertyName(); if (propertyName.equals("model")) { // NOI18N ListModel oldModel = (ListModel)e.getOldValue(); ListModel newModel = (ListModel)e.getNewValue(); if (oldModel != null) oldModel.removeListDataListener(dataL); if (newModel != null) { newModel.addListDataListener(dataL); updateLayoutStateNeeded = true; repaint(); } } else if (propertyName.equals("selectionModel")) { // NOI18N ListSelectionModel oldModelS = (ListSelectionModel)e.getOldValue(); ListSelectionModel newModelS = (ListSelectionModel)e.getNewValue(); if (oldModelS != null) oldModelS.removeListSelectionListener(selectionL); if (newModelS != null) newModelS.addListSelectionListener(selectionL); updateLayoutStateNeeded = true; repaint(); } else if (propertyName.equals("cellRenderer") || // NOI18N propertyName.equals("font") || // NOI18N propertyName.equals("fixedCellHeight") || // NOI18N propertyName.equals("fixedCellWidth")) {// NOI18N updateLayoutStateNeeded = true; repaint(); } } } }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.