1 /*
2  * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package sun.swing.table;
26 
27 import sun.swing.DefaultLookup;
28 
29 import java.awt.Component;
30 import java.awt.Color;
31 import java.awt.FontMetrics;
32 import java.awt.Graphics;
33 import java.awt.Insets;
34 import java.awt.Point;
35 import java.awt.Rectangle;
36 import java.io.Serializable;
37 import javax.swing.*;
38 import javax.swing.plaf.UIResource;
39 import javax.swing.border.Border;
40 import javax.swing.table.*;
41 
42 @SuppressWarnings("serial") // JDK-implementation class
43 public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer
44         implements UIResource {
45     private boolean horizontalTextPositionSet;
46     private Icon sortArrow;
47     private EmptyIcon emptyIcon = new EmptyIcon();
48 
DefaultTableCellHeaderRenderer()49     public DefaultTableCellHeaderRenderer() {
50         setHorizontalAlignment(JLabel.CENTER);
51     }
52 
setHorizontalTextPosition(int textPosition)53     public void setHorizontalTextPosition(int textPosition) {
54         horizontalTextPositionSet = true;
55         super.setHorizontalTextPosition(textPosition);
56     }
57 
getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)58     public Component getTableCellRendererComponent(JTable table, Object value,
59             boolean isSelected, boolean hasFocus, int row, int column) {
60         Icon sortIcon = null;
61 
62         boolean isPaintingForPrint = false;
63 
64         if (table != null) {
65             JTableHeader header = table.getTableHeader();
66             if (header != null) {
67                 Color fgColor = null;
68                 Color bgColor = null;
69                 if (hasFocus) {
70                     fgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellForeground");
71                     bgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellBackground");
72                 }
73                 if (fgColor == null) {
74                     fgColor = header.getForeground();
75                 }
76                 if (bgColor == null) {
77                     bgColor = header.getBackground();
78                 }
79                 setForeground(fgColor);
80                 setBackground(bgColor);
81 
82                 setFont(header.getFont());
83 
84                 isPaintingForPrint = header.isPaintingForPrint();
85             }
86 
87             if (!isPaintingForPrint && table.getRowSorter() != null) {
88                 if (!horizontalTextPositionSet) {
89                     // There is a row sorter, and the developer hasn't
90                     // set a text position, change to leading.
91                     setHorizontalTextPosition(JLabel.LEADING);
92                 }
93                 SortOrder sortOrder = getColumnSortOrder(table, column);
94                 if (sortOrder != null) {
95                     switch(sortOrder) {
96                     case ASCENDING:
97                         sortIcon = DefaultLookup.getIcon(
98                             this, ui, "Table.ascendingSortIcon");
99                         break;
100                     case DESCENDING:
101                         sortIcon = DefaultLookup.getIcon(
102                             this, ui, "Table.descendingSortIcon");
103                         break;
104                     case UNSORTED:
105                         sortIcon = DefaultLookup.getIcon(
106                             this, ui, "Table.naturalSortIcon");
107                         break;
108                     }
109                 }
110             }
111         }
112 
113         setText(value == null ? "" : value.toString());
114         setIcon(sortIcon);
115         sortArrow = sortIcon;
116 
117         Border border = null;
118         if (hasFocus) {
119             border = DefaultLookup.getBorder(this, ui, "TableHeader.focusCellBorder");
120         }
121         if (border == null) {
122             border = DefaultLookup.getBorder(this, ui, "TableHeader.cellBorder");
123         }
124         setBorder(border);
125 
126         return this;
127     }
128 
getColumnSortOrder(JTable table, int column)129     public static SortOrder getColumnSortOrder(JTable table, int column) {
130         SortOrder rv = null;
131         if (table == null || table.getRowSorter() == null) {
132             return rv;
133         }
134         java.util.List<? extends RowSorter.SortKey> sortKeys =
135             table.getRowSorter().getSortKeys();
136         if (sortKeys.size() > 0 && sortKeys.get(0).getColumn() ==
137             table.convertColumnIndexToModel(column)) {
138             rv = sortKeys.get(0).getSortOrder();
139         }
140         return rv;
141     }
142 
143     @Override
paintComponent(Graphics g)144     public void paintComponent(Graphics g) {
145         boolean b = DefaultLookup.getBoolean(this, ui,
146                 "TableHeader.rightAlignSortArrow", false);
147         if (b && sortArrow != null) {
148             //emptyIcon is used so that if the text in the header is right
149             //aligned, or if the column is too narrow, then the text will
150             //be sized appropriately to make room for the icon that is about
151             //to be painted manually here.
152             emptyIcon.width = sortArrow.getIconWidth();
153             emptyIcon.height = sortArrow.getIconHeight();
154             setIcon(emptyIcon);
155             super.paintComponent(g);
156             Point position = computeIconPosition(g);
157             sortArrow.paintIcon(this, g, position.x, position.y);
158         } else {
159             super.paintComponent(g);
160         }
161     }
162 
computeIconPosition(Graphics g)163     private Point computeIconPosition(Graphics g) {
164         FontMetrics fontMetrics = g.getFontMetrics();
165         Rectangle viewR = new Rectangle();
166         Rectangle textR = new Rectangle();
167         Rectangle iconR = new Rectangle();
168         Insets i = getInsets();
169         viewR.x = i.left;
170         viewR.y = i.top;
171         viewR.width = getWidth() - (i.left + i.right);
172         viewR.height = getHeight() - (i.top + i.bottom);
173         SwingUtilities.layoutCompoundLabel(
174             this,
175             fontMetrics,
176             getText(),
177             sortArrow,
178             getVerticalAlignment(),
179             getHorizontalAlignment(),
180             getVerticalTextPosition(),
181             getHorizontalTextPosition(),
182             viewR,
183             iconR,
184             textR,
185             getIconTextGap());
186         int x = getWidth() - i.right - sortArrow.getIconWidth();
187         int y = iconR.y;
188         return new Point(x, y);
189     }
190 
191     @SuppressWarnings("serial") // JDK-implementation class
192     private class EmptyIcon implements Icon, Serializable {
193         int width = 0;
194         int height = 0;
paintIcon(Component c, Graphics g, int x, int y)195         public void paintIcon(Component c, Graphics g, int x, int y) {}
getIconWidth()196         public int getIconWidth() { return width; }
getIconHeight()197         public int getIconHeight() { return height; }
198     }
199 }
200