1 /*
   2  * Copyright (c) 2005, 2010, 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 public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer
  43         implements UIResource {
  44     private boolean horizontalTextPositionSet;
  45     private Icon sortArrow;
  46     private EmptyIcon emptyIcon = new EmptyIcon();
  47 
  48     public DefaultTableCellHeaderRenderer() {
  49         setHorizontalAlignment(JLabel.CENTER);
  50     }
  51 
  52     public void setHorizontalTextPosition(int textPosition) {
  53         horizontalTextPositionSet = true;
  54         super.setHorizontalTextPosition(textPosition);
  55     }
  56 
  57     public Component getTableCellRendererComponent(JTable table, Object value,
  58             boolean isSelected, boolean hasFocus, int row, int column) {
  59         Icon sortIcon = null;
  60 
  61         boolean isPaintingForPrint = false;
  62 
  63         if (table != null) {
  64             JTableHeader header = table.getTableHeader();
  65             if (header != null) {
  66                 Color fgColor = null;
  67                 Color bgColor = null;
  68                 if (hasFocus) {
  69                     fgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellForeground");
  70                     bgColor = DefaultLookup.getColor(this, ui, "TableHeader.focusCellBackground");
  71                 }
  72                 if (fgColor == null) {
  73                     fgColor = header.getForeground();
  74                 }
  75                 if (bgColor == null) {
  76                     bgColor = header.getBackground();
  77                 }
  78                 setForeground(fgColor);
  79                 setBackground(bgColor);
  80 
  81                 setFont(header.getFont());
  82 
  83                 isPaintingForPrint = header.isPaintingForPrint();
  84             }
  85 
  86             if (!isPaintingForPrint && table.getRowSorter() != null) {
  87                 if (!horizontalTextPositionSet) {
  88                     // There is a row sorter, and the developer hasn't
  89                     // set a text position, change to leading.
  90                     setHorizontalTextPosition(JLabel.LEADING);
  91                 }
  92                 SortOrder sortOrder = getColumnSortOrder(table, column);
  93                 if (sortOrder != null) {
  94                     switch(sortOrder) {
  95                     case ASCENDING:
  96                         sortIcon = DefaultLookup.getIcon(
  97                             this, ui, "Table.ascendingSortIcon");
  98                         break;
  99                     case DESCENDING:
 100                         sortIcon = DefaultLookup.getIcon(
 101                             this, ui, "Table.descendingSortIcon");
 102                         break;
 103                     case UNSORTED:
 104                         sortIcon = DefaultLookup.getIcon(
 105                             this, ui, "Table.naturalSortIcon");
 106                         break;
 107                     }
 108                 }
 109             }
 110         }
 111 
 112         setText(value == null ? "" : value.toString());
 113         setIcon(sortIcon);
 114         sortArrow = sortIcon;
 115 
 116         Border border = null;
 117         if (hasFocus) {
 118             border = DefaultLookup.getBorder(this, ui, "TableHeader.focusCellBorder");
 119         }
 120         if (border == null) {
 121             border = DefaultLookup.getBorder(this, ui, "TableHeader.cellBorder");
 122         }
 123         setBorder(border);
 124 
 125         return this;
 126     }
 127 
 128     public static SortOrder getColumnSortOrder(JTable table, int column) {
 129         SortOrder rv = null;
 130         if (table == null || table.getRowSorter() == null) {
 131             return rv;
 132         }
 133         java.util.List<? extends RowSorter.SortKey> sortKeys =
 134             table.getRowSorter().getSortKeys();
 135         if (sortKeys.size() > 0 && sortKeys.get(0).getColumn() ==
 136             table.convertColumnIndexToModel(column)) {
 137             rv = sortKeys.get(0).getSortOrder();
 138         }
 139         return rv;
 140     }
 141 
 142     @Override
 143     public void paintComponent(Graphics g) {
 144         boolean b = DefaultLookup.getBoolean(this, ui,
 145                 "TableHeader.rightAlignSortArrow", false);
 146         if (b && sortArrow != null) {
 147             //emptyIcon is used so that if the text in the header is right
 148             //aligned, or if the column is too narrow, then the text will
 149             //be sized appropriately to make room for the icon that is about
 150             //to be painted manually here.
 151             emptyIcon.width = sortArrow.getIconWidth();
 152             emptyIcon.height = sortArrow.getIconHeight();
 153             setIcon(emptyIcon);
 154             super.paintComponent(g);
 155             Point position = computeIconPosition(g);
 156             sortArrow.paintIcon(this, g, position.x, position.y);
 157         } else {
 158             super.paintComponent(g);
 159         }
 160     }
 161 
 162     private Point computeIconPosition(Graphics g) {
 163         FontMetrics fontMetrics = g.getFontMetrics();
 164         Rectangle viewR = new Rectangle();
 165         Rectangle textR = new Rectangle();
 166         Rectangle iconR = new Rectangle();
 167         Insets i = getInsets();
 168         viewR.x = i.left;
 169         viewR.y = i.top;
 170         viewR.width = getWidth() - (i.left + i.right);
 171         viewR.height = getHeight() - (i.top + i.bottom);
 172         SwingUtilities.layoutCompoundLabel(
 173             this,
 174             fontMetrics,
 175             getText(),
 176             sortArrow,
 177             getVerticalAlignment(),
 178             getHorizontalAlignment(),
 179             getVerticalTextPosition(),
 180             getHorizontalTextPosition(),
 181             viewR,
 182             iconR,
 183             textR,
 184             getIconTextGap());
 185         int x = getWidth() - i.right - sortArrow.getIconWidth();
 186         int y = iconR.y;
 187         return new Point(x, y);
 188     }
 189 
 190     private class EmptyIcon implements Icon, Serializable {
 191         int width = 0;
 192         int height = 0;
 193         public void paintIcon(Component c, Graphics g, int x, int y) {}
 194         public int getIconWidth() { return width; }
 195         public int getIconHeight() { return height; }
 196     }
 197 }