001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. 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 Substance Kirill Grouchnikov 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: package org.jvnet.substance;
031:
032: import java.awt.*;
033: import java.lang.reflect.Method;
034: import java.util.List;
035:
036: import javax.swing.*;
037: import javax.swing.border.EmptyBorder;
038: import javax.swing.plaf.TableHeaderUI;
039: import javax.swing.plaf.UIResource;
040: import javax.swing.table.DefaultTableCellRenderer;
041: import javax.swing.table.JTableHeader;
042:
043: import org.jvnet.lafwidget.animation.FadeKind;
044: import org.jvnet.lafwidget.animation.FadeState;
045: import org.jvnet.lafwidget.utils.LookUtils;
046: import org.jvnet.substance.SubstanceTableUI.TableColumnId;
047: import org.jvnet.substance.theme.SubstanceTheme;
048: import org.jvnet.substance.utils.*;
049:
050: /**
051: * Default renderer for table header cells.
052: *
053: * @author Kirill Grouchnikov
054: */
055: public class SubstanceDefaultTableHeaderCellRenderer extends
056: DefaultTableCellRenderer implements UIResource {
057: // TODO JDK6 - remove
058: private static Method tableGetRowSorterMethod;
059:
060: // TODO JDK6 - remove
061: private static Method rowSorterGetSortKeysMethod;
062:
063: // TODO JDK6 - remove
064: private static Method rowSorterSortKeyGetSortOrderMethod;
065:
066: // TODO JDK6 - remove
067: private static Method rowSorterSortKeyGetColumnMethod;
068:
069: static {
070: // TODO JDK6 - remove
071: if (LookUtils.IS_JAVA_6_OR_LATER) {
072: try {
073: tableGetRowSorterMethod = JTable.class
074: .getDeclaredMethod("getRowSorter", new Class[0]);
075: Class rowSorterClass = Class
076: .forName("javax.swing.RowSorter");
077: if (rowSorterClass != null) {
078: rowSorterGetSortKeysMethod = rowSorterClass
079: .getDeclaredMethod("getSortKeys",
080: new Class[0]);
081: }
082: Class rowSorterSortKeyClass = Class
083: .forName("javax.swing.RowSorter$SortKey");
084: if (rowSorterSortKeyClass != null) {
085: rowSorterSortKeyGetSortOrderMethod = rowSorterSortKeyClass
086: .getDeclaredMethod("getSortOrder",
087: new Class[0]);
088: rowSorterSortKeyGetColumnMethod = rowSorterSortKeyClass
089: .getDeclaredMethod("getColumn",
090: new Class[0]);
091: }
092: } catch (Exception exc) {
093: tableGetRowSorterMethod = null;
094: rowSorterGetSortKeysMethod = null;
095: rowSorterSortKeyGetSortOrderMethod = null;
096: rowSorterSortKeyGetColumnMethod = null;
097: }
098: }
099: }
100:
101: /**
102: * Creates a new cell renderer.
103: */
104: public SubstanceDefaultTableHeaderCellRenderer() {
105: setHorizontalAlignment(JLabel.CENTER);
106: }
107:
108: /*
109: * (non-Javadoc)
110: *
111: * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable,
112: * java.lang.Object, boolean, boolean, int, int)
113: */
114: @Override
115: public Component getTableCellRendererComponent(JTable table,
116: Object value, boolean isSelected, boolean hasFocus,
117: int row, int column) {
118: if (table == null) {
119: setBorder(DefaultTableCellRenderer.noFocusBorder);
120: setValue(value);
121: setOpaque(false);
122: return this ;
123: }
124:
125: if (table.getTableHeader() == null) {
126: return super .getTableCellRendererComponent(table, value,
127: isSelected, hasFocus, row, column);
128: }
129:
130: JTableHeader tableHeader = table.getTableHeader();
131: TableHeaderUI tableHeaderUI = tableHeader.getUI();
132: if (tableHeaderUI instanceof SubstanceTableHeaderUI) {
133: SubstanceTableHeaderUI ui = (SubstanceTableHeaderUI) tableHeaderUI;
134: ComponentState state = ui.getColumnState(column);
135: ComponentState prevState = ui.getPrevColumnState(column);
136: SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
137: tableHeader, state);
138: Color color = SubstanceCoreUtilities
139: .getInterpolatedForegroundColor(tableHeader,
140: column, theme, state, prevState,
141: FadeKind.SELECTION, FadeKind.ROLLOVER);
142:
143: // System.out.println("[column " + column + "] - " +
144: // prevState.name() + ":"
145: // + state.name() + ":" + color + " from "
146: // + theme.getDisplayName());
147:
148: super .setForeground(color);
149: } else {
150: super .setForeground(table.getForeground());
151: }
152:
153: SubstanceCoreUtilities.applyStripedBackground(table, row, this );
154:
155: // fix for issue 319 - using font from the table header
156: if (tableHeader.getFont() != null) {
157: setFont(tableHeader.getFont());
158: } else {
159: setFont(table.getFont());
160: }
161:
162: TableColumnId cellFocusId = new TableColumnId(column);
163: FadeState focusState = SubstanceFadeUtilities.getFadeState(
164: table, cellFocusId, FadeKind.FOCUS);
165: Insets regInsets = SubstanceSizeUtils
166: .getTableCellRendererInsets(SubstanceSizeUtils
167: .getComponentFontSize(table));
168: // if (hasFocus || (focusState != null)) {
169: // SubstanceBorder border = new SubstanceBorder(regInsets);
170: // if (focusState != null) {
171: // border.setAlpha(focusState.getFadePosition() / 10.0f);
172: // }
173: // this.setBorder(border);
174: // } else {
175: this .setBorder(new EmptyBorder(regInsets.top, regInsets.left,
176: regInsets.bottom, regInsets.right));
177: // }
178:
179: this .setValue(value);
180: this .setOpaque(false);
181:
182: this .setEnabled(tableHeader.isEnabled() && table.isEnabled());
183:
184: // fix for defect 242 - not showing sort icon under JDK 6.0
185: // TODO JDK6
186:
187: // the following should be uncommented when Substance moves to JDK 6.0
188: // RowSorter rowSorter = table.getRowSorter();
189: // if (rowSorter != null) {
190: // setHorizontalTextPosition(JLabel.LEADING);
191: // java.util.List<? extends RowSorter.SortKey> sortKeys = rowSorter
192: // .getSortKeys();
193: // Icon sortIcon = null;
194: // int arrowWidth = SubstanceSizeUtils.getArrowIconWidth() - 2;
195: // int arrowHeight = SubstanceSizeUtils.getArrowIconHeight() - 1;
196: // float arrowStrokeWidth = SubstanceSizeUtils.getArrowStrokeWidth();
197: // SubstanceTheme theme = null;
198: // if (tableHeaderUI instanceof SubstanceTableHeaderUI) {
199: // SubstanceTableHeaderUI ui = (SubstanceTableHeaderUI) tableHeaderUI;
200: // ComponentState state = ui.getColumnState(column);
201: // theme = SubstanceCoreUtilities.getTheme(tableHeader, state,
202: // true, true);
203: // } else {
204: // theme = SubstanceCoreUtilities.getTheme(tableHeader, true);
205: // }
206: // if (sortKeys.size() > 0
207: // && sortKeys.get(0).getColumn() == table
208: // .convertColumnIndexToModel(column)) {
209: // switch (sortKeys.get(0).getSortOrder()) {
210: // case ASCENDING:
211: // sortIcon = SubstanceImageCreator.getArrowIcon(arrowWidth,
212: // arrowHeight, arrowStrokeWidth,
213: // SwingConstants.NORTH, theme);
214: // break;
215: // case DESCENDING:
216: // sortIcon = SubstanceImageCreator.getArrowIcon(arrowWidth,
217: // arrowHeight, arrowStrokeWidth,
218: // SwingConstants.SOUTH, theme);
219: // break;
220: // case UNSORTED:
221: // sortIcon = null;
222: // break;
223: // }
224: // this.setIcon(sortIcon);
225: // }
226: // }
227:
228: try {
229: this .setIcon(null);
230: if (LookUtils.IS_JAVA_6_OR_LATER) {
231: Object rowSorter = tableGetRowSorterMethod.invoke(
232: table, new Object[0]);
233: if (rowSorter != null) {
234: setHorizontalTextPosition(JLabel.LEADING);
235: List sortKeys = (List) rowSorterGetSortKeysMethod
236: .invoke(rowSorter, new Object[0]);
237: Icon sortIcon = null;
238: SubstanceTheme theme = null;
239: if (tableHeaderUI instanceof SubstanceTableHeaderUI) {
240: SubstanceTableHeaderUI ui = (SubstanceTableHeaderUI) tableHeaderUI;
241: ComponentState state = ui
242: .getColumnState(column);
243: theme = SubstanceThemeUtilities.getTheme(
244: tableHeader, state);
245: } else {
246: theme = SubstanceThemeUtilities
247: .getTheme(tableHeader);
248: }
249:
250: Object sortKey0 = sortKeys.get(0);
251: int sortColumn = (Integer) rowSorterSortKeyGetColumnMethod
252: .invoke(sortKey0, new Object[0]);
253: if (sortKeys.size() > 0
254: && sortColumn == table
255: .convertColumnIndexToModel(column)) {
256: String sortOrderString = rowSorterSortKeyGetSortOrderMethod
257: .invoke(sortKey0, new Object[0])
258: .toString();
259: if (sortOrderString.indexOf("ASCENDING") >= 0) {
260: sortIcon = SubstanceImageCreator
261: .getArrowIcon(
262: SubstanceSizeUtils
263: .getComponentFontSize(tableHeader),
264: SwingConstants.NORTH, theme);
265: } else {
266: if (sortOrderString.indexOf("DESCENDING") >= 0) {
267: sortIcon = SubstanceImageCreator
268: .getArrowIcon(
269: SubstanceSizeUtils
270: .getComponentFontSize(tableHeader),
271: SwingConstants.SOUTH,
272: theme);
273: }
274: }
275: this .setIcon(sortIcon);
276: }
277: }
278: }
279: } catch (Exception exc) {
280: this .setIcon(null);
281: }
282:
283: return this ;
284: }
285:
286: public static boolean isColumnSorted(JTable table, int columnIndex) {
287: // TODO JDK 6 - use proper APIs.
288: try {
289: if (LookUtils.IS_JAVA_6_OR_LATER) {
290: Object rowSorter = tableGetRowSorterMethod.invoke(
291: table, new Object[0]);
292: if (rowSorter != null) {
293: List sortKeys = (List) rowSorterGetSortKeysMethod
294: .invoke(rowSorter, new Object[0]);
295: Object sortKey0 = sortKeys.get(0);
296: int sortColumn = (Integer) rowSorterSortKeyGetColumnMethod
297: .invoke(sortKey0, new Object[0]);
298: if (sortKeys.size() > 0
299: && sortColumn == table
300: .convertColumnIndexToModel(columnIndex)) {
301: String sortOrderString = rowSorterSortKeyGetSortOrderMethod
302: .invoke(sortKey0, new Object[0])
303: .toString();
304: if (sortOrderString.indexOf("ASCENDING") >= 0) {
305: return true;
306: } else {
307: return true;
308: }
309: }
310: }
311: }
312: return false;
313: } catch (Exception exc) {
314: return false;
315: }
316:
317: }
318: }
|