home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
MacListUI.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
12KB
|
452 lines
/*
* %W% %E%
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.mac;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
import com.sun.java.swing.plaf.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import com.sun.java.swing.plaf.basic.BasicListUI;
import java.io.Serializable;
/**
* A Mac L&F implementation of ListUI.
*
* To add icons you will need to:
* <ul>
* <li> Create your own CellRenderer class. For an example see the Mac UI for JTree.
* <li> Extend this class and override configureList to create your own CellRenderer.
* </ul>
* Warning: 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 Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.15 10/23/97
* @author Hans Muller
*/
public class MacListUI extends BasicListUI
{
Window parentWindow = null;
MacListAncestorListener anAncestorListener;
boolean activated = false;
//Override so the entire component is not painted with the background color
public void update(Graphics g, JComponent c) {
paint(g, c);
}
/**
* 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)
{
g.setColor(list.getBackground());
Rectangle viewRect = new Rectangle(list.getSize());
Insets i = list.getInsets();
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
g.fillRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
}
/**
* 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
* @see #paintCell
*/
public void paint(Graphics g, JComponent c)
{
maybeUpdateLayoutState();
ListCellRenderer renderer = list.getCellRenderer();
ListModel dataModel = list.getModel();
ListSelectionModel selModel = list.getSelectionModel();
if (renderer == null) {
return;
}
paintBackground(g);
Rectangle rect = list.getBounds();
// list.getBorder().paintBorder(list,g, rect.x, rect.y, rect.width - 1, rect.height -1);
/* Compute the area we're going to paint in terms of the affected
* rows (firstPaintRow, lastPaintRow), and the clip bounds.
*/
Rectangle paintBounds = g.getClipBounds();
int firstPaintRow = convertYToRow(paintBounds.y);
int lastPaintRow = convertYToRow((paintBounds.y + paintBounds.height) - 1);
if (firstPaintRow == -1) {
firstPaintRow = 0;
}
if (lastPaintRow == -1) {
lastPaintRow = dataModel.getSize() - 1;
}
Rectangle rowBounds = getCellBounds(list, firstPaintRow, firstPaintRow);
if (rowBounds == null) {
return;
}
int leadIndex = list.getLeadSelectionIndex();
for(int row = firstPaintRow; row <= lastPaintRow; row++) {
rowBounds.height = getRowHeight(row);
/* Set the clip rect to be the intersection of rowBounds
* and paintBounds and then paint the cell.
*/
g.setClip(rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height);
g.clipRect(paintBounds.x, paintBounds.y, paintBounds.width, paintBounds.height);
paintCell(g, row, rowBounds, renderer, dataModel, selModel, leadIndex);
rowBounds.y += rowBounds.height;
}
}
/**
* Remove the listeners for the JList, its model, and its
* selectionModel. All of the listener fields, are reset to
* null here. This method is called at uninstallUI() time,
* it should be kept in sync with addListListeners.
*
* @see #uninstallUI
* @see #addListListeners
*/
protected void removeListListeners()
{
super.removeListListeners();
list.removeAncestorListener(anAncestorListener);
}
/**
* Initialize JList properties, e.g. font, foreground, and background,
* and add the CellRendererPane. The font, foreground, and background
* properties are only set if their current value is either null
* or a UIResource, other properties are set if the current
* value is null.
*
* @see #unconfigureList
* @see #installUI
* @see CellRendererPane
*/
protected void configureList()
{
if(list.getCellRenderer() == null)
list.setCellRenderer(new MacListCellRenderer());
super.configureList();
list.setBorder(MacBorderFactory.getFocusBorder());
}
/**
* Initializes <code>this.list</code> by calling <code>configureList()</code>,
* <code>addListListeners()</code>, and <code>registerKeyboardActions()</code>
* in order.
*
* @see #configureList
* @see #addListListeners
* @see #registerKeyboardActions
*/
public void installUI(JComponent list)
{
this.list = (JList)list;
configureList();
addListListeners();
registerKeyboardActions();
//set up listener so we know when addNotify and removeNotify are called
anAncestorListener = new MacListAncestorListener();
list.addAncestorListener(anAncestorListener);
}
/**
* Uninitializes <code>this.list</code> by calling <code>removeListListeners()</code>,
* <code>unregisterKeyboardActions()</code>, and <code>unconfigureList()</code>
* in order. Sets this.list to null.
*
* @see #removeListListeners
* @see #unregisterKeyboardActions
* @see #unconfigureList
*/
public void uninstallUI(JComponent c)
{
removeListListeners();
unregisterKeyboardActions();
unconfigureList();
cellWidth = cellHeight = -1;
cellHeights = null;
this.list = null;
}
/**
* Returns a new instance of BasicListUI. BasicListUI delegates are
* allocated one per JList.
*
* @return A new ListUI implementation for the Mac look and feel.
*/
public static ComponentUI createUI(JComponent list) {
return new MacListUI();
}
/**
* @return The bounds of the index'th cell.
* @see ListUI#getCellBounds
*/
public Rectangle getCellBounds(JList list, int index1, int index2) {
maybeUpdateLayoutState();
int minIndex = Math.min(index1, index2);
int maxIndex = Math.max(index1, index2);
int minY = convertRowToY(minIndex);
int maxY = convertRowToY(maxIndex);
if ((minY == -1) || (maxY == -1)) {
return null;
}
maxY += getRowHeight(maxIndex);
Insets i = list.getInsets();
return new Rectangle(i.left, minY, list.getWidth() - i.left - i.right, maxY - minY);
}
/**
* Convert the JList relative coordinate to the row that contains it,
* based on the current layout. If y0 doesn't fall within any row,
* return -1.
*
* @return The row that contains y0, or -1.
* @see #getRowHeight
* @see #updateLayoutState
*/
protected int convertYToRow(int y0)
{
int nrows = list.getModel().getSize();
Dimension dim = list.getSize();
Insets insets = list.getInsets();
//make sure we are in the content area
if((y0 <= insets.top) || (y0 > dim.height - insets.bottom))
return -1;
if (cellHeights == null)
{
int row = (cellHeight == 0) ? 0 : (y0 - insets.top)/cellHeight;
return ((row < 0) || (row >= nrows)) ? -1 : row;
}
else {
int y = insets.top;
int row = 0;
for(int i = 0; i < nrows; i++) {
if ((y0 >= y) && (y0 < y + cellHeights[i])) {
return row;
}
y += cellHeights[i];
row += 1;
}
return -1;
}
}
/**
* Return the JList relative Y coordinate of the origin of the specified
* row or -1 if row isn't valide.
*
* @return The Y coordinate of the origin of row, or -1.
* @see #getRowHeight
* @see #updateLayoutState
*/
protected int convertRowToY(int row)
{
int nrows = list.getModel().getSize();
Insets insets = list.getInsets();
if ((row < 0) || (row > nrows)) {
return -1;
}
if (cellHeights == null) {
return cellHeight * row + insets.top;;
}
else {
int y = insets.top;
for(int i = 0; i < row; i++) {
y += cellHeights[i];
}
return y;
}
}
public void setActivated(boolean activated)
{
this.activated = activated;
}
public boolean isActivated()
{
return activated;
}
public JList getList()
{
return list;
}
class MacListAncestorListener implements com.sun.java.swing.event.AncestorListener
{
ListWindowAdapter aListWindowAdapter;
/**
* Called when the source or one of its ancestors is made visible
* either by setVisible(true) being called or by its being
* added to the component hierarchy. The method is only called
* if the source has actually become visible. For this to be true
* all its parents must be visible and it must be in a hierarchy
* rooted at a Window
*/
public void ancestorAdded(com.sun.java.swing.event.AncestorEvent event)
{
Component parent = null;
JList c = getList();
int hHeight = 0, vWidth = 0;
Object object = event.getSource();
if(object == c )
parent = c.getParent();
while((parent != null) && (!(parent instanceof Window)))
parent = parent.getParent();
if(parent != null)
{
parentWindow = (Window)parent;
aListWindowAdapter = new ListWindowAdapter();
parentWindow.addWindowListener(aListWindowAdapter);
}
}
/**
* Called when the source or one of its ancestors is made invisible
* either by setVisible(false) being called or by its being
* remove from the component hierarchy. The method is only called
* if the source has actually become invisible. For this to be true
* at least one of its parents must by invisible or it is not in
* a hierarchy rooted at a Window
*/
public void ancestorRemoved(com.sun.java.swing.event.AncestorEvent event)
{
if(parentWindow != null)
parentWindow.removeWindowListener(aListWindowAdapter);
}
/**
* Called when either the source or one of its ancestors is moved.
*/
public void ancestorMoved(com.sun.java.swing.event.AncestorEvent event)
{
}
}
class ListWindowAdapter extends java.awt.event.WindowAdapter
{
public void windowDeactivated(java.awt.event.WindowEvent event)
{
Object object = event.getSource();
if (object == parentWindow)
ParentWindow_WindowDeactivated(event);
}
public void windowActivated(java.awt.event.WindowEvent event)
{
Object object = event.getSource();
if (object == parentWindow)
ParentWindow_WindowActivated(event);
}
}
void ParentWindow_WindowActivated(java.awt.event.WindowEvent event)
{
setActivated(true);
if(list != null)
list.repaint();
}
void ParentWindow_WindowDeactivated(java.awt.event.WindowEvent event)
{
setActivated(false);
if(list != null)
list.repaint();
}
}