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 skin = XPStyle.getXP().getSkin(header, Part.HP_HEADERITEM); 95 } 96 Insets margins = skin.getContentMargin(); 97 Border border = null; 98 int contentTop = 0; 99 int contentLeft = 0; 100 int contentBottom = 0; 101 int contentRight = 0; 102 if (margins != null) { 103 contentTop = margins.top; 104 contentLeft = margins.left; 105 contentBottom = margins.bottom; 106 contentRight = margins.right; 107 } 108 /* idk: 109 * Both on Vista and XP there is some offset to the 110 * HP_HEADERITEM content. It does not seem to come from 111 * Prop.CONTENTMARGINS. Do not know where it is defined. 112 * using some hardcoded values. 113 */ 114 contentLeft += 5; 115 contentBottom += 4; 116 contentRight += 5; 117 118 /* On Vista sortIcon is painted above the header's text. 119 * We use border to paint it. 120 */ 121 Icon sortIcon; 122 if (WindowsLookAndFeel.isOnVista() 123 && ((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource 124 || sortIcon == null)) { 125 contentTop += 1; 126 setIcon(null); 127 sortIcon = null; 128 SortOrder sortOrder = 129 getColumnSortOrder(table, column); 130 if (sortOrder != null) { 131 switch (sortOrder) { 132 case ASCENDING: 133 sortIcon = 134 UIManager.getIcon("Table.ascendingSortIcon"); 135 break; 136 case DESCENDING: 137 sortIcon = 138 UIManager.getIcon("Table.descendingSortIcon"); 139 break; 140 } 141 } 142 if (sortIcon != null) { 143 contentBottom = sortIcon.getIconHeight(); 144 border = new IconBorder(sortIcon, contentTop, contentLeft, 145 contentBottom, contentRight); 146 } else { 147 sortIcon = 148 UIManager.getIcon("Table.ascendingSortIcon"); 149 int sortIconHeight = 150 (sortIcon != null) ? sortIcon.getIconHeight() : 0; 151 if (sortIconHeight != 0) { 152 contentBottom = sortIconHeight; 153 } 154 border = 155 new EmptyBorder( 156 sortIconHeight + contentTop, contentLeft, 157 contentBottom, contentRight); 158 } 159 } else { 160 contentTop += 3; 161 border = new EmptyBorder(contentTop, contentLeft, 162 contentBottom, contentRight); 163 } 164 setBorder(border); 165 return this; 166 } 167 168 public void paint(Graphics g) { 169 Dimension size = getSize(); 170 State state = State.NORMAL; 171 TableColumn draggedColumn = header.getDraggedColumn(); 172 if (draggedColumn != null && 173 column == SwingUtilities2.convertColumnIndexToView( 174 header.getColumnModel(), draggedColumn.getModelIndex())) { 175 state = State.PRESSED; 176 } else if (isSelected || hasFocus || hasRollover) { 177 state = State.HOT; 178 } 179 /* on Vista there are more states for sorted columns */ 180 if (WindowsLookAndFeel.isOnVista()) { 181 SortOrder sortOrder = getColumnSortOrder(header.getTable(), column); 182 if (sortOrder != null) { 183 switch(sortOrder) { 184 case ASCENDING: 185 case DESCENDING: 186 switch (state) { 187 case NORMAL: 188 state = State.SORTEDNORMAL; 189 break; 190 case PRESSED: 191 state = State.SORTEDPRESSED; 192 break; 193 case HOT: 194 state = State.SORTEDHOT; 195 break; 196 default: 197 /* do nothing */ 198 } 199 break; 200 default : 201 /* do nothing */ 202 } 203 } 204 } 205 skin.paintSkin(g, 0, 0, size.width-1, size.height-1, state); 206 super.paint(g); 207 } 208 } 209 210 /** 211 * A border with an Icon at the middle of the top side. 212 * Outer insets can be provided for this border. 213 */ 214 private static class IconBorder implements Border, UIResource{ 215 private final Icon icon; 216 private final int top; 217 private final int left; 218 private final int bottom; 219 private final int right; 220 /** 221 * Creates this border; 222 * @param icon - icon to paint for this border 223 * @param top, left, bottom, right - outer insets for this border 224 */ 225 public IconBorder(Icon icon, int top, int left, 226 int bottom, int right) { 227 this.icon = icon; 228 this.top = top; 229 this.left = left; 230 this.bottom = bottom; 231 this.right = right; 232 } 233 public Insets getBorderInsets(Component c) { 234 return new Insets(icon.getIconHeight() + top, left, bottom, right); 235 } 236 public boolean isBorderOpaque() { 237 return false; 238 } 239 public void paintBorder(Component c, Graphics g, int x, int y, 240 int width, int height) { 241 icon.paintIcon(c, g, 242 x + left + (width - left - right - icon.getIconWidth()) / 2, 243 y + top); 244 } 245 } 246 }