home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
BasicTableHeaderUI.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
16KB
|
526 lines
/*
* @(#)BasicTableHeaderUI.java 1.30 98/02/10
*
* 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.basic;
import com.sun.java.swing.table.*;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
import java.util.Enumeration;
import java.awt.event.*;
import java.awt.*;
import com.sun.java.swing.plaf.*;
import java.io.Serializable;
/**
* BasicTableHeaderUI implementation
* <p>
* 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.30 02/10/98
* @author Alan Chung
* @author Philip Milne
*/
public class BasicTableHeaderUI extends TableHeaderUI implements MouseListener,
MouseMotionListener, FocusListener, Serializable
{
//
// Instance Variables
//
/** The JTableHeader this UI is hooked up to */
protected JTableHeader header;
// cache vars
protected CellRendererPane rendererPane = new CellRendererPane();
transient protected int hitColumnIndex;
transient protected TableColumn hitColumn;
transient protected boolean isResizing;
transient protected int originalWidth;
transient protected int widthDelta;
transient protected int lastMouseX;
transient protected int realDraggedDistance;
transient protected boolean isReordering;
transient protected boolean okToReorder;
transient protected boolean fireAction;
transient protected boolean hasPress = false;
//
// Install/Deinstall UI
//
public static ComponentUI createUI(JComponent h) {
return new BasicTableHeaderUI();
}
public void installUI(JComponent c) {
header = (JTableHeader)c;
header.add(rendererPane);
c.addMouseListener(this);
c.addMouseMotionListener(this);
c.addFocusListener(this);
LookAndFeel.installColorsAndFont(header, "TableHeader.background",
"TableHeader.foreground", "TableHeader.font");
}
public void uninstallUI(JComponent c) {
header.remove(rendererPane);
header = null;
c.removeMouseListener(this);
c.removeMouseMotionListener(this);
c.removeFocusListener(this);
/*c.resetKeyboardActions();*/
}
//
// MouseListener, MouseMotionListener, FocusListener Methods
//
public void focusGained(FocusEvent e) {}
public void focusLost(FocusEvent e) {}
static final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
static final Cursor resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
public void mouseMoved(MouseEvent e) {
if (getResizingColumn(e.getPoint()) != -1) {
if (header.getCursor() != resizeCursor)
header.setCursor(resizeCursor);
}
else {
if (header.getCursor() != defaultCursor)
header.setCursor(defaultCursor);
}
}
public void mouseDragged(MouseEvent e) {
fireAction = false;
int mouseX = e.getX();
if (mouseX == lastMouseX)
return;
if (isResizing) {
widthDelta += mouseX - lastMouseX;
int newWidth = originalWidth + widthDelta;
hitColumn.setWidth(newWidth);
header.revalidate();
header.repaint();
if (header.getUpdateTableInRealTime()) {
JTable table = header.getTable();
table.revalidate();
table.repaint();
}
}
else if (okToReorder || isReordering) {
isReordering = true;
move(e);
}
else {
// Doing a simple drag selection
}
lastMouseX = mouseX;
}
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {
// PENDING(alan): For some reason if you do a click drag on the
// header cell and the cursor moves out of the window mousePressed
// is called again. So we check and prevent second entry
if (hasPress)
return;
hasPress = true;
TableColumnModel columnModel = header.getColumnModel();
Rectangle headerRect;
int index = 0;
// Init cache vars
isReordering = false;
isResizing = false;
fireAction = true;
hitColumnIndex = -1;
hitColumn = null;
Point p = e.getPoint();
// First find which header cell was hit
if ((index = columnModel.getColumnIndexAtX(p.x)) != -1) {
headerRect = header.getHeaderRect(index);
// The last 3 pixels + 3 pixels of next column are for resizing
int resizeIndex = getResizingColumn(p);
if (header.getResizingAllowed() && (resizeIndex != -1)) {
hitColumn = columnModel.getColumn(resizeIndex);
if (hitColumn.getResizable()) {
// Resize it!
isResizing = true;
fireAction = false;
hitColumnIndex = resizeIndex;
originalWidth = hitColumn.getWidth();
widthDelta = 0;
header.setResizingColumn(hitColumn);
lastMouseX = p.x;
hitColumn.disableResizedPosting();
}
else
hitColumn = null;
}
else {
boolean controlKeyDown = e.isControlDown();
if (header.getReorderingAllowed() && headerRect.contains(p)) {
// Can't move if we are the only column in the table
okToReorder = (columnModel.getColumnCount() > 1);
// If the control key is down then we don't want to
// start a reorder operation
if (controlKeyDown) {
okToReorder = false;
fireAction = false;
}
}
JTable table = header.getTable();
// Handle Selection
if (columnModel.getColumnSelectionAllowed() &&
headerRect.contains(p) && table != null) {
// PENDING(alan): do the alt selection thing
if (controlKeyDown) {
if (table.isColumnSelected(index)) {
// Control down, and the hit column is ready selected
// we will deselect
table.removeColumnSelectionInterval(index,index);
}
else {
table.addColumnSelectionInterval(index, index);
}
}
else {
table.setColumnSelectionInterval(index, index);
}
}
// Set up cache vars
hitColumnIndex = index;
header.setDraggedColumn(hitColumn);
header.setDraggedDistance(0);
lastMouseX = p.x;
realDraggedDistance = 0;
}
}
}
public void mouseReleased(MouseEvent e) {
hasPress = false;
if (isResizing) {
isResizing = false;
originalWidth = 0;
header.setResizingColumn(null);
// We have to set the column's width back to the original
// pre-resize width, reenable resize notification posting,
// then set the width to the new width. This way when
// the resize notification is posted to the column's listeners
// it will have the correct original size, rather than the
// last incremental change.
int newWidth = hitColumn.getWidth();
hitColumn.setWidth(originalWidth);
hitColumn.enableResizedPosting();
hitColumn.setWidth(newWidth);
}
else if (isReordering) {
isReordering = false;
originalWidth = widthDelta = 0;
realDraggedDistance = 0;
//PENDING(alan)
// hitColumn.enableResizedPosting();
}
else if (fireAction) {
fireAction = false;
}
header.setDraggedColumn(null);
header.setDraggedDistance(0);
// Repaint to finish cleaning up
header.repaint();
JTable table = header.getTable();
if (table != null)
table.repaint();
// Reset local state
okToReorder = false;
hitColumnIndex = -1;
hitColumn = null;
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
//
// Paint Methods and support
//
public void paint(Graphics g, JComponent c) {
JTableHeader header = (JTableHeader) c;
Rectangle paintBounds = g.getClipBounds(), intersection;
Dimension size = header.getSize();
Component component = null;
if (header.getColumnModel() == null)
// Can't draw if I don't have a columnModel
return;
// Paint the background first
Color bColor = header.getBackground();
if(bColor != null) {
g.setColor(bColor);
g.fillRect(paintBounds.x, paintBounds.y, paintBounds.width,
paintBounds.height);
}
// Calculate the inset for cell rect
Rectangle cellRect = new Rectangle(0,0,size.width,size.height);
/*Insets i = getInsets(header);
cellRect.x += i.left;
cellRect.y += i.top;
cellRect.width -= (i.right + cellRect.x);
cellRect.height -= (i.bottom + cellRect.y);*/
// Paint the non-dragged header cells first
int column = 0;
boolean drawn = false;
Rectangle draggedCellRect = null;
TableColumn aColumn, draggedColumnObject = null;
TableCellRenderer renderer;
int columnMargin = header.getColumnModel().getColumnMargin();
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
aColumn = (TableColumn)enumeration.nextElement();
cellRect.width = aColumn.getWidth() + columnMargin;
// Note: The header cellRect includes columnMargin so the
// drawing of header cells will not have any gaps.
if (cellRect.intersects(paintBounds)) {
drawn = true;
if (aColumn != header.getDraggedColumn()) {
renderer = aColumn.getHeaderRenderer();
component = renderer.getTableCellRendererComponent(
header.getTable(), aColumn.getHeaderValue(),
// header.getColumnModel().isColumnSelected(column),
false, false, // Don't do header selection.
-1, column);
rendererPane.add(component);
rendererPane.paintComponent(g,component, header, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
else {
// Draw a gray well in place of the moving column
g.setColor(header.getParent().getBackground());
g.fillRect(cellRect.x, cellRect.y,
cellRect.width, cellRect.height);
draggedCellRect = new Rectangle(cellRect);
// draggedColumnObject = aColumn;
}
}
else {
if (drawn)
// Don't need to iterate through the rest
break;
}
cellRect.x += cellRect.width;
column++;
}
// draw the dragged cell if we are dragging
draggedColumnObject = header.getDraggedColumn();
if (draggedColumnObject != null && draggedCellRect != null) {
renderer = draggedColumnObject.getHeaderRenderer();
component = renderer.getTableCellRendererComponent(
header.getTable(), draggedColumnObject.getHeaderValue(),
// header.getColumnModel().isColumnSelected(column),
false, false, // Don't do header selection.
-1, column);
draggedCellRect.x += header.getDraggedDistance();
SwingUtilities.paintComponent(g, component,header,draggedCellRect);
}
}
//
// Size Methods
//
public Dimension getMinimumSize(JComponent c) {
return getPreferredSize(c);
}
public Dimension getPreferredSize(JComponent c) {
JTableHeader header = (JTableHeader)c;
JTable table = header.getTable();
// The preffered width of the header is the preferred width of the table.
Dimension tableSize = table.getPreferredSize();
Dimension size = new Dimension();
size.width = tableSize.width;
// Now compute the height.
int column = 0;
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
// Compute the height
TableCellRenderer renderer = aColumn.getHeaderRenderer();
Component comp = renderer.getTableCellRendererComponent(header.getTable(),
aColumn.getHeaderValue(), false, false,
-1, column);
size.height = Math.max(size.height, comp.getPreferredSize().height);
column++;
}
return size;
}
public Dimension getMaximumSize(JComponent c) {
return getPreferredSize(c);
}
//
// Protected & Private Methods
//
private void move(MouseEvent e) {
TableColumnModel columnModel = header.getColumnModel();
int width;
int lastColumn = columnModel.getColumnCount() - 1;
// Compute how much we are moving and the total redraw rect
Rectangle redrawRect = header.getHeaderRect(hitColumnIndex); // where I was
redrawRect.x += header.getDraggedDistance();
int delta = e.getX() - lastMouseX;
realDraggedDistance += delta;
Rectangle redrawRect2 = header.getHeaderRect(hitColumnIndex); // where I'm now
redrawRect2.x += realDraggedDistance;
redrawRect = redrawRect.union(redrawRect2); // Union the 2 rects
// Now check if we have moved enough to do a swap
if ((realDraggedDistance < 0) && (hitColumnIndex != 0)) {
// Moving left; check prevColumn
width = columnModel.getColumnMargin() +
columnModel.getColumn(hitColumnIndex-1).getWidth();
if (-realDraggedDistance > (width / 2)) {
// Swap me
columnModel.moveColumn(hitColumnIndex, hitColumnIndex-1);
realDraggedDistance = width + realDraggedDistance;
hitColumnIndex--;
}
}
else if ((realDraggedDistance > 0) && (hitColumnIndex != lastColumn)) {
// Moving right; check nextColumn
width = columnModel.getColumnMargin() +
columnModel.getColumn(hitColumnIndex+1).getWidth();
if (realDraggedDistance > (width / 2)) {
// Swap me
columnModel.moveColumn(hitColumnIndex, hitColumnIndex+1);
realDraggedDistance = -(width - realDraggedDistance);
hitColumnIndex++;
}
}
// Set the draggedDistance before display
int draggedDistance = realDraggedDistance;
if (hitColumnIndex == 0) {
// I'm the left most column, so we can't have a negative
// draggedDistance
if (draggedDistance < 0)
draggedDistance = 0;
}
else if (hitColumnIndex == lastColumn) {
if (draggedDistance > 0)
draggedDistance = 0;
}
header.setDraggedColumn(columnModel.getColumn(hitColumnIndex));
header.setDraggedDistance(draggedDistance);
// Redraw
header.repaint(redrawRect.x, 0, redrawRect.width, redrawRect.height);
if (header.getUpdateTableInRealTime()) {
JTable table = header.getTable();
if (table != null)
table.repaint(redrawRect.x, 0, redrawRect.width,
(table.getRowHeight() +
table.getIntercellSpacing().height)
* table.getRowCount());
}
}
private int getResizingColumn(Point p) {
int column = 0;
Rectangle resizeRect = new Rectangle(-3,0,6,header.getSize().height);
int columnMargin = header.getColumnModel().getColumnMargin();
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
resizeRect.x += aColumn.getWidth() + columnMargin;
if (resizeRect.x > p.x) {
// Don't have to check the rest, we already gone past p
break;
}
if (resizeRect.contains(p))
return column;
column++;
}
return -1;
}
} // End of Class BasicTableHeaderUI