/*
* Copyright 2011 MH-Software-Entwicklung. All rights reserved.
* Use is subject to license terms.
*/
package com.jtattoo.plaf;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Enumeration;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
*
* @author Michael Hagen
*/
public class BaseTableHeaderUI extends BasicTableHeaderUI {
private TableCellRenderer originalHeaderRenderer;
protected MouseAdapter myMouseAdapter = null;
protected MouseMotionAdapter myMouseMotionAdapter = null;
protected int rolloverCol = -1;
public static ComponentUI createUI(JComponent h) {
return new BaseTableHeaderUI();
}
public void installUI(JComponent c) {
super.installUI(c);
originalHeaderRenderer = header.getDefaultRenderer();
if ((originalHeaderRenderer != null)
&& "sun.swing.table.DefaultTableCellHeaderRenderer".equals(originalHeaderRenderer.getClass().getName())) {
header.setDefaultRenderer(new BaseDefaultHeaderRenderer());
}
}
public void uninstallUI(JComponent c) {
if (header.getDefaultRenderer() instanceof BaseDefaultHeaderRenderer) {
header.setDefaultRenderer(originalHeaderRenderer);
}
super.uninstallUI(c);
}
public void installListeners() {
super.installListeners();
myMouseAdapter = new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
boolean sortingAllowed = false;
if (JTattooUtilities.getJavaVersion() >= 1.6) {
sortingAllowed = header.getTable().getRowSorter() != null;
}
if (sortingAllowed || header.getReorderingAllowed()) {
if (header.getBounds().contains(e.getPoint())) {
int oldRolloverCol = rolloverCol;
rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX());
updateRolloverColumn(oldRolloverCol, rolloverCol);
} else {
int oldRolloverCol = rolloverCol;
rolloverCol = -1;
updateRolloverColumn(oldRolloverCol, rolloverCol);
}
}
}
public void mouseEntered(MouseEvent e) {
boolean sortingAllowed = false;
if (JTattooUtilities.getJavaVersion() >= 1.6) {
sortingAllowed = header.getTable().getRowSorter() != null;
}
if (sortingAllowed || header.getReorderingAllowed()) {
int oldRolloverCol = rolloverCol;
rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX());
updateRolloverColumn(oldRolloverCol, rolloverCol);
}
}
public void mouseExited(MouseEvent e) {
boolean sortingAllowed = false;
if (JTattooUtilities.getJavaVersion() >= 1.6) {
sortingAllowed = header.getTable().getRowSorter() != null;
}
if (sortingAllowed || header.getReorderingAllowed()) {
int oldRolloverCol = rolloverCol;
rolloverCol = -1;
updateRolloverColumn(oldRolloverCol, rolloverCol);
}
}
};
myMouseMotionAdapter = new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
boolean sortingAllowed = false;
if (JTattooUtilities.getJavaVersion() >= 1.6) {
sortingAllowed = header.getTable().getRowSorter() != null;
}
if (sortingAllowed || header.getReorderingAllowed()) {
if (header.getDraggedColumn() == null) {
int oldRolloverCol = rolloverCol;
rolloverCol = header.getColumnModel().getColumnIndexAtX(e.getX());
updateRolloverColumn(oldRolloverCol, rolloverCol);
}
}
}
public void mouseDragged(MouseEvent e) {
boolean sortingAllowed = false;
if (JTattooUtilities.getJavaVersion() >= 1.6) {
sortingAllowed = header.getTable().getRowSorter() != null;
}
if (sortingAllowed || header.getReorderingAllowed()) {
if (header.getDraggedColumn() != null && header.getDraggedColumn().getIdentifier() != null) {
rolloverCol = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier());
} else if (header.getResizingColumn() != null) {
rolloverCol = -1;
}
}
}
};
header.addMouseListener(myMouseAdapter);
header.addMouseMotionListener(myMouseMotionAdapter);
}
public void uninstallListeners() {
header.removeMouseListener(myMouseAdapter);
header.removeMouseMotionListener(myMouseMotionAdapter);
super.uninstallListeners();
}
protected boolean drawAllwaysActive() {
return false;
}
protected boolean drawRolloverBar() {
return false;
}
protected Component getHeaderRenderer(int col) {
TableColumn tabCol = header.getColumnModel().getColumn(col);
TableCellRenderer renderer = tabCol.getHeaderRenderer();
if (renderer == null) {
renderer = header.getDefaultRenderer();
}
return renderer.getTableCellRendererComponent(header.getTable(), tabCol.getHeaderValue(), false, false, -1, col);
}
private int getHeaderHeight() {
int height = 0;
boolean accomodatedDefault = false;
TableColumnModel columnModel = header.getColumnModel();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
TableColumn aColumn = columnModel.getColumn(column);
boolean isDefault = (aColumn.getHeaderRenderer() == null);
if (!isDefault || !accomodatedDefault) {
Component comp = getHeaderRenderer(column);
int rendererHeight = comp.getPreferredSize().height;
height = Math.max(height, rendererHeight);
// Configuring the header renderer to calculate its preferred size
// is expensive. Optimise this by assuming the default renderer
// always has the same height as the first non-zero height that
// it returns for a non-null/non-empty value.
if (isDefault && rendererHeight > 0) {
Object headerValue = aColumn.getHeaderValue();
if (headerValue != null) {
headerValue = headerValue.toString();
if (headerValue != null && !headerValue.equals("")) {
accomodatedDefault = true;
}
}
}
}
}
return height + 2;
}
/**
* Return the preferred size of the header. The preferred height is the
* maximum of the preferred heights of all of the components provided
* by the header renderers. The preferred width is the sum of the
* preferred widths of each column (plus inter-cell spacing).
*/
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn) enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
if (width > Integer.MAX_VALUE) {
width = Integer.MAX_VALUE;
}
return new Dimension((int) width, getHeaderHeight());
}
protected void updateRolloverColumn(int oldColumn, int newColumn) {
header.repaint(header.getHeaderRect(oldColumn));
header.repaint(header.getHeaderRect(newColumn));
}
protected void rolloverColumnUpdated(int oldColumn, int newColumn) {
// Empty to avoid multiple paints
}
public void paint(Graphics g, JComponent c) {
if (header.getColumnModel().getColumnCount() <= 0) {
return;
}
boolean ltr = header.getComponentOrientation().isLeftToRight();
Rectangle clip = g.getClipBounds();
Point left = clip.getLocation();
Point right = new Point(clip.x + clip.width - 1, clip.y);
TableColumnModel cm = header.getColumnModel();
int cMin = header.columnAtPoint(ltr ? left : right);
int cMax = header.columnAtPoint(ltr ? right : left);
// This should never happen.
if (cMin == -1) {
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if (cMax == -1) {
cMax = cm.getColumnCount() - 1;
}
TableColumn draggedColumn = header.getDraggedColumn();
Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax);
int columnWidth;
TableColumn aColumn;
if (ltr) {
for (int column = cMin; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth;
if (aColumn != draggedColumn) {
paintCell(g, cellRect, column);
}
cellRect.x += columnWidth;
}
} else {
for (int column = cMax; column >= cMin; column--) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth;
if (aColumn != draggedColumn) {
paintCell(g, cellRect, column);
}
cellRect.x += columnWidth;
}
}
// Paint the dragged column if we are dragging.
if (draggedColumn != null) {
int draggedColumnIndex = viewIndexForColumn(draggedColumn);
Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex);
// Draw a gray well in place of the moving column.
g.setColor(header.getParent().getBackground());
g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height);
draggedCellRect.x += header.getDraggedDistance();
// Fill the background.
g.setColor(header.getBackground());
g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height);
paintCell(g, draggedCellRect, draggedColumnIndex);
}
// Remove all components in the rendererPane.
rendererPane.removeAll();
}
protected void paintBackground(Graphics g, Rectangle cellRect, int col) {
Component component = getHeaderRenderer(col);
int x = cellRect.x;
int y = cellRect.y;
int w = cellRect.width;
int h = cellRect.height;
if (col == rolloverCol && component.isEnabled()) {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), x, y, w, h);
} else if (JTattooUtilities.isFrameActive(header)) {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), x, y, w, h);
} else {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), x, y, w, h);
}
}
protected void paintCell(Graphics g, Rectangle cellRect, int col) {
Component component = getHeaderRenderer(col);
if (!(component instanceof BaseDefaultHeaderRenderer)) {
paintBackground(g, cellRect, col);
}
rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true);
}
private int viewIndexForColumn(TableColumn aColumn) {
TableColumnModel cm = header.getColumnModel();
for (int column = 0; column < cm.getColumnCount(); column++) {
if (cm.getColumn(column) == aColumn) {
return column;
}
}
return -1;
}
//----------------------------------------------------------------------------------------------------------------------
// inner classes
//----------------------------------------------------------------------------------------------------------------------
private class BaseDefaultHeaderRenderer extends DefaultTableCellRenderer {
public BaseDefaultHeaderRenderer() {
super();
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return new MyRenderComponent(table, value, isSelected, hasFocus, row, column);
}
}
private class MyRenderComponent extends JLabel {
private JTable table = null;
private int col = 0;
private int gv = 0;
public MyRenderComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
super();
this.table = table;
this.col = col;
if (value != null) {
setText(value.toString());
} else {
setText("");
}
setOpaque(false);
setForeground(UIManager.getColor("TableHeader.foreground"));
setHorizontalAlignment(JLabel.CENTER);
setHorizontalTextPosition(SwingConstants.LEADING);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
if (JTattooUtilities.getJavaVersion() >= 1.6) {
RowSorter rowSorter = table == null ? null : table.getRowSorter();
List keyList = rowSorter == null ? null : rowSorter.getSortKeys();
if ((keyList != null) && (keyList.size() > 0)) {
RowSorter.SortKey sortKey = (RowSorter.SortKey) keyList.get(0);
if (sortKey.getColumn() == table.convertColumnIndexToModel(col)) {
AbstractIconFactory iconFactory = ((AbstractLookAndFeel) UIManager.getLookAndFeel()).getIconFactory();
if (sortKey.getSortOrder().equals(SortOrder.ASCENDING)) {
setIcon(iconFactory.getUpArrowIcon());
} else if (sortKey.getSortOrder().equals(SortOrder.DESCENDING)) {
setIcon(iconFactory.getDownArrowIcon());
}
}
}
}
gv = ColorHelper.getGrayValue(AbstractLookAndFeel.getTheme().getRolloverColor());
}
protected void paintBackground(Graphics g) {
int draggedColumn = -1;
if (header.getDraggedColumn() != null) {
draggedColumn = header.getColumnModel().getColumnIndex(header.getDraggedColumn().getIdentifier());
}
if (table.isEnabled() && (col == rolloverCol || col == draggedColumn)) {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getRolloverColors(), 0, 0, getWidth(), getHeight());
if (drawRolloverBar()) {
g.setColor(AbstractLookAndFeel.getFocusColor());
g.drawLine(0, 0, getWidth() - 1, 0);
g.drawLine(0, 1, getWidth() - 1, 1);
g.drawLine(0, 2, getWidth() - 1, 2);
}
} else if (drawAllwaysActive() || JTattooUtilities.isFrameActive(header)) {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getColHeaderColors(), 0, 0, getWidth(), getHeight());
} else {
JTattooUtilities.fillHorGradient(g, AbstractLookAndFeel.getTheme().getInActiveColors(), 0, 0, getWidth(), getHeight());
}
}
public void paint(Graphics g) {
paintBackground(g);
if (rolloverCol == col) {
if (gv > 128) {
setForeground(Color.black);
} else {
setForeground(Color.white);
}
}
super.paint(g);
}
}
}