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 
  49     public DefaultTableCellHeaderRenderer() {
  50         setHorizontalAlignment(JLabel.CENTER);
  51     }
  52 
  53     public void setHorizontalTextPosition(int textPosition) {
  54         horizontalTextPositionSet = true;
  55         super.setHorizontalTextPosition(textPosition);
  56     }
  57 
  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 
 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
 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 
 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;
 195         public void paintIcon(Component c, Graphics g, int x, int y) {}
 196         public int getIconWidth() { return width; }
 197         public int getIconHeight() { return height; }
 198     }
 199 }