001: /*
002: * Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.looks.windows;
032:
033: import java.awt.Component;
034: import java.awt.Graphics;
035: import java.awt.Point;
036: import java.awt.Rectangle;
037:
038: import javax.swing.JComponent;
039: import javax.swing.JTable;
040: import javax.swing.plaf.ComponentUI;
041: import javax.swing.table.TableCellRenderer;
042: import javax.swing.table.TableColumn;
043: import javax.swing.table.TableColumnModel;
044:
045: import com.sun.java.swing.plaf.windows.WindowsTableHeaderUI;
046:
047: /**
048: * The JGoodies Windows L&F implementation of <code>TableHeaderUI</code>.
049: * A Windows table header that honors the XP header style even if the user
050: * uses custom non-opaque renderers. The renderers should be a subclass of
051: * <code>JComponent</code> because we need to replace the border by the one
052: * specified in the XP style.
053: *
054: * @author Andrej Golovnin
055: * @version $Revision: 1.4 $
056: */
057: public final class WindowsXPTableHeaderUI extends WindowsTableHeaderUI {
058:
059: private TableCellRenderer xpRenderer;
060:
061: public static ComponentUI createUI(JComponent h) {
062: return new WindowsXPTableHeaderUI();
063: }
064:
065: public void installUI(JComponent c) {
066: super .installUI(c);
067: xpRenderer = header.getDefaultRenderer();
068: }
069:
070: public void uninstallUI(JComponent c) {
071: xpRenderer = null;
072: super .uninstallUI(c);
073: }
074:
075: public void paint(Graphics g, JComponent c) {
076: TableColumnModel cm = header.getColumnModel();
077: if (cm.getColumnCount() <= 0) {
078: return;
079: }
080: boolean ltr = header.getComponentOrientation().isLeftToRight();
081:
082: Rectangle clip = g.getClipBounds();
083: Point left = clip.getLocation();
084: Point right = new Point(clip.x + clip.width - 1, clip.y);
085: int cMin = header.columnAtPoint(ltr ? left : right);
086: int cMax = header.columnAtPoint(ltr ? right : left);
087: // This should never happen.
088: if (cMin == -1) {
089: cMin = 0;
090: }
091: // If the table does not have enough columns to fill the view we'll get
092: // -1.
093: // Replace this with the index of the last column.
094: if (cMax == -1) {
095: cMax = cm.getColumnCount() - 1;
096: }
097:
098: TableColumn draggedColumn = header.getDraggedColumn();
099: int columnWidth;
100: Rectangle cellRect = header.getHeaderRect(cMin);
101: TableColumn aColumn;
102: if (ltr) {
103: for (int column = cMin; column <= cMax; column++) {
104: aColumn = cm.getColumn(column);
105: columnWidth = aColumn.getWidth();
106: cellRect.width = columnWidth;
107: if (aColumn != draggedColumn) {
108: paintCell(g, cellRect, column);
109: }
110: cellRect.x += columnWidth;
111: }
112: } else {
113: for (int column = cMax; column >= cMin; column--) {
114: aColumn = cm.getColumn(column);
115: columnWidth = aColumn.getWidth();
116: cellRect.width = columnWidth;
117: if (aColumn != draggedColumn) {
118: paintCell(g, cellRect, column);
119: }
120: cellRect.x += columnWidth;
121: }
122: }
123:
124: // Paint the dragged column if we are dragging.
125: if (draggedColumn != null) {
126: int draggedColumnIndex = viewIndexForColumn(draggedColumn);
127: Rectangle draggedCellRect = header
128: .getHeaderRect(draggedColumnIndex);
129:
130: // Draw a gray well in place of the moving column.
131: g.setColor(header.getParent().getBackground());
132: g.fillRect(draggedCellRect.x, draggedCellRect.y,
133: draggedCellRect.width, draggedCellRect.height);
134:
135: draggedCellRect.x += header.getDraggedDistance();
136:
137: // Fill the background.
138: g.setColor(header.getBackground());
139: g.fillRect(draggedCellRect.x, draggedCellRect.y,
140: draggedCellRect.width, draggedCellRect.height);
141:
142: paintCell(g, draggedCellRect, draggedColumnIndex);
143: }
144:
145: // Remove all components in the rendererPane.
146: rendererPane.removeAll();
147: }
148:
149: private void paintCell(Graphics g, Rectangle cellRect,
150: int columnIndex) {
151: TableColumn aColumn = header.getColumnModel().getColumn(
152: columnIndex);
153: TableCellRenderer renderer = aColumn.getHeaderRenderer();
154: if (renderer == null) {
155: renderer = header.getDefaultRenderer();
156: }
157:
158: JTable table = header.getTable();
159: Component background = xpRenderer
160: .getTableCellRendererComponent(table, null, false,
161: false, -1, columnIndex);
162: Component c = renderer
163: .getTableCellRendererComponent(table, aColumn
164: .getHeaderValue(), false, false, -1,
165: columnIndex);
166:
167: if (c != background) {
168: // The DefaultTableCellRenderer is used in the most cases as
169: // the base class for all header renderers. And due to
170: // the optimizations in its #isOpaque method, we have to add
171: // the component to the renderer pane to determine its
172: // non-opaqueness.
173: rendererPane.add(c);
174: if (!c.isOpaque()) {
175: rendererPane.paintComponent(g, background, header,
176: cellRect.x, cellRect.y, cellRect.width,
177: cellRect.height, true);
178:
179: // All custom header renderers will use TableHeader.cellBorder
180: // returned by UIManager#getBorder. But this one does not
181: // comply with the Windows XP style. It is the one used by
182: // Windows Classis L&F. So replace the border of the custom
183: // renderers component by the one which comply with XP style.
184: if ((c instanceof JComponent)
185: && (background instanceof JComponent)) {
186: ((JComponent) c)
187: .setBorder(((JComponent) background)
188: .getBorder());
189: }
190: }
191: }
192:
193: rendererPane.paintComponent(g, c, header, cellRect.x,
194: cellRect.y, cellRect.width, cellRect.height, true);
195: }
196:
197: private int viewIndexForColumn(TableColumn aColumn) {
198: TableColumnModel cm = header.getColumnModel();
199: for (int column = cm.getColumnCount() - 1; column >= 0; column--) {
200: if (cm.getColumn(column) == aColumn) {
201: return column;
202: }
203: }
204: return -1;
205: }
206:
207: }
|