1 /* 2 * Copyright (c) 1997, 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 26 package com.sun.java.swing.plaf.windows; 27 28 import java.awt.*; 29 import javax.swing.*; 30 import javax.swing.border.*; 31 import javax.swing.plaf.*; 32 import javax.swing.plaf.basic.*; 33 import javax.swing.table.*; 34 35 import static com.sun.java.swing.plaf.windows.TMSchema.*; 36 import static com.sun.java.swing.plaf.windows.XPStyle.*; 37 import sun.swing.table.*; 38 import sun.swing.SwingUtilities2; 39 40 41 public class WindowsTableHeaderUI extends BasicTableHeaderUI { 42 private TableCellRenderer originalHeaderRenderer; 43 44 public static ComponentUI createUI(JComponent h) { 45 return new WindowsTableHeaderUI(); 46 } 47 48 public void installUI(JComponent c) { 49 super.installUI(c); 50 51 if (XPStyle.getXP() != null) { 52 originalHeaderRenderer = header.getDefaultRenderer(); 53 if (originalHeaderRenderer instanceof UIResource) { 54 header.setDefaultRenderer(new XPDefaultRenderer()); 55 } 56 } 57 } 58 59 public void uninstallUI(JComponent c) { 60 if (header.getDefaultRenderer() instanceof XPDefaultRenderer) { 61 header.setDefaultRenderer(originalHeaderRenderer); 62 } 63 super.uninstallUI(c); 64 } 65 66 @Override 67 protected void rolloverColumnUpdated(int oldColumn, int newColumn) { 68 if (XPStyle.getXP() != null) { 69 header.repaint(header.getHeaderRect(oldColumn)); 70 header.repaint(header.getHeaderRect(newColumn)); 71 } 72 } 73 74 @SuppressWarnings("serial") // JDK-implementation class 75 private class XPDefaultRenderer extends DefaultTableCellHeaderRenderer { 76 Skin skin; 77 boolean isSelected, hasFocus, hasRollover; 78 int column; 79 80 XPDefaultRenderer() { 81 setHorizontalAlignment(LEADING); 82 } 83 84 public Component getTableCellRendererComponent(JTable table, Object value, 85 boolean isSelected, boolean hasFocus, 86 int row, int column) { 87 super.getTableCellRendererComponent(table, value, isSelected, 88 hasFocus, row, column); 89 this.isSelected = isSelected; 90 this.hasFocus = hasFocus; 91 this.column = column; 92 this.hasRollover = (column == getRolloverColumn()); 93 if (skin == null) { 94 XPStyle xp = XPStyle.getXP(); 95 skin = (xp != null) ? xp.getSkin(header, Part.HP_HEADERITEM) : null; 96 } 97 Insets margins = (skin != null) ? skin.getContentMargin() : null; 98 Border border = null; 99 int contentTop = 0; 100 int contentLeft = 0; 101 int contentBottom = 0; 102 int contentRight = 0; 103 if (margins != null) { 104 contentTop = margins.top; 105 contentLeft = margins.left; 106 contentBottom = margins.bottom; 107 contentRight = margins.right; 108 } 109 /* idk: 110 * Both on Vista and XP there is some offset to the 111 * HP_HEADERITEM content. It does not seem to come from 112 * Prop.CONTENTMARGINS. Do not know where it is defined. 113 * using some hardcoded values. 114 */ 115 contentLeft += 5; 116 contentBottom += 4; 117 contentRight += 5; 118 119 /* On Vista sortIcon is painted above the header's text. 120 * We use border to paint it. 121 */ 122 Icon sortIcon; 123 if (WindowsLookAndFeel.isOnVista() 124 && ((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource 125 || sortIcon == null)) { 126 contentTop += 1; 127 setIcon(null); 128 sortIcon = null; 129 SortOrder sortOrder = 130 getColumnSortOrder(table, column); 131 if (sortOrder != null) { 132 switch (sortOrder) { 133 case ASCENDING: 134 sortIcon = 135 UIManager.getIcon("Table.ascendingSortIcon"); 136 break; 137 case DESCENDING: 138 sortIcon = 139 UIManager.getIcon("Table.descendingSortIcon"); 140 break; 141 } 142 } 143 if (sortIcon != null) { 144 contentBottom = sortIcon.getIconHeight(); 145 border = new IconBorder(sortIcon, contentTop, contentLeft, 146 contentBottom, contentRight); 147 } else { 148 sortIcon = 149 UIManager.getIcon("Table.ascendingSortIcon"); 150 int sortIconHeight = 151 (sortIcon != null) ? sortIcon.getIconHeight() : 0; 152 if (sortIconHeight != 0) { 153 contentBottom = sortIconHeight; 154 } 155 border = 156 new EmptyBorder( 157 sortIconHeight + contentTop, contentLeft, 158 contentBottom, contentRight); 159 } 160 } else { 161 contentTop += 3; 162 border = new EmptyBorder(contentTop, contentLeft, 163 contentBottom, contentRight); 164 } 165 setBorder(border); 166 return this; 167 } 168 169 public void paint(Graphics g) { 170 Dimension size = getSize(); 171 State state = State.NORMAL; 172 TableColumn draggedColumn = header.getDraggedColumn(); 173 if (draggedColumn != null && 174 column == SwingUtilities2.convertColumnIndexToView( 175 header.getColumnModel(), draggedColumn.getModelIndex())) { 176 state = State.PRESSED; 177 } else if (isSelected || hasFocus || hasRollover) { 178 state = State.HOT; 179 } 180 /* on Vista there are more states for sorted columns */ 181 if (WindowsLookAndFeel.isOnVista()) { 182 SortOrder sortOrder = getColumnSortOrder(header.getTable(), column); 183 if (sortOrder != null) { 184 switch(sortOrder) { 185 case ASCENDING: 186 case DESCENDING: 187 switch (state) { 188 case NORMAL: 189 state = State.SORTEDNORMAL; 190 break; 191 case PRESSED: 192 state = State.SORTEDPRESSED; 193 break; 194 case HOT: 195 state = State.SORTEDHOT; 196 break; 197 default: 198 /* do nothing */ 199 } 200 break; 201 default : 202 /* do nothing */ 203 } 204 } 205 } 206 skin.paintSkin(g, 0, 0, size.width-1, size.height-1, state); 207 super.paint(g); 208 } 209 } 210 211 /** 212 * A border with an Icon at the middle of the top side. 213 * Outer insets can be provided for this border. 214 */ 215 private static class IconBorder implements Border, UIResource{ 216 private final Icon icon; 217 private final int top; 218 private final int left; 219 private final int bottom; 220 private final int right; 221 /** 222 * Creates this border; 223 * @param icon - icon to paint for this border 224 * @param top, left, bottom, right - outer insets for this border 225 */ 226 public IconBorder(Icon icon, int top, int left, 227 int bottom, int right) { 228 this.icon = icon; 229 this.top = top; 230 this.left = left; 231 this.bottom = bottom; 232 this.right = right; 233 } 234 public Insets getBorderInsets(Component c) { 235 return new Insets(icon.getIconHeight() + top, left, bottom, right); 236 } 237 public boolean isBorderOpaque() { 238 return false; 239 } 240 public void paintBorder(Component c, Graphics g, int x, int y, 241 int width, int height) { 242 icon.paintIcon(c, g, 243 x + left + (width - left - right - icon.getIconWidth()) / 2, 244 y + top); 245 } 246 } 247 }