1 /* 2 * Copyright (c) 2002, 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 26 package javax.swing.plaf.synth; 27 28 import java.awt.*; 29 import java.beans.*; 30 import javax.swing.*; 31 import javax.swing.border.*; 32 import javax.swing.plaf.*; 33 import javax.swing.plaf.basic.*; 34 import javax.swing.table.*; 35 import sun.swing.table.*; 36 37 /** 38 * Provides the Synth L&F UI delegate for 39 * {@link javax.swing.table.JTableHeader}. 40 * 41 * @author Alan Chung 42 * @author Philip Milne 43 * @since 1.7 44 */ 45 public class SynthTableHeaderUI extends BasicTableHeaderUI 46 implements PropertyChangeListener, SynthUI { 47 48 // 49 // Instance Variables 50 // 51 52 private TableCellRenderer prevRenderer = null; 53 54 private SynthStyle style; 55 56 /** 57 * Creates a new UI object for the given component. 58 * 59 * @param h component to create UI object for 60 * @return the UI object 61 */ 62 public static ComponentUI createUI(JComponent h) { 63 return new SynthTableHeaderUI(); 64 } 65 66 /** 67 * {@inheritDoc} 68 */ 69 @Override 70 protected void installDefaults() { 71 prevRenderer = header.getDefaultRenderer(); 72 if (prevRenderer instanceof UIResource) { 73 header.setDefaultRenderer(new HeaderRenderer()); 74 } 75 updateStyle(header); 76 } 77 78 private void updateStyle(JTableHeader c) { 79 SynthContext context = getContext(c, ENABLED); 80 SynthStyle oldStyle = style; 81 style = SynthLookAndFeel.updateStyle(context, this); 82 if (style != oldStyle) { 83 if (oldStyle != null) { 84 uninstallKeyboardActions(); 85 installKeyboardActions(); 86 } 87 } 88 context.dispose(); 89 } 90 91 /** 92 * {@inheritDoc} 93 */ 94 @Override 95 protected void installListeners() { 96 super.installListeners(); 97 header.addPropertyChangeListener(this); 98 } 99 100 /** 101 * {@inheritDoc} 102 */ 103 @Override 104 protected void uninstallDefaults() { 105 if (header.getDefaultRenderer() instanceof HeaderRenderer) { 106 header.setDefaultRenderer(prevRenderer); 107 } 108 109 SynthContext context = getContext(header, ENABLED); 110 111 style.uninstallDefaults(context); 112 context.dispose(); 113 style = null; 114 } 115 116 /** 117 * {@inheritDoc} 118 */ 119 @Override 120 protected void uninstallListeners() { 121 header.removePropertyChangeListener(this); 122 super.uninstallListeners(); 123 } 124 125 /** 126 * Notifies this UI delegate to repaint the specified component. 127 * This method paints the component background, then calls 128 * the {@link #paint(SynthContext,Graphics)} method. 129 * 130 * <p>In general, this method does not need to be overridden by subclasses. 131 * All Look and Feel rendering code should reside in the {@code paint} method. 132 * 133 * @param g the {@code Graphics} object used for painting 134 * @param c the component being painted 135 * @see #paint(SynthContext,Graphics) 136 */ 137 @Override 138 public void update(Graphics g, JComponent c) { 139 SynthContext context = getContext(c); 140 141 SynthLookAndFeel.update(context, g); 142 context.getPainter().paintTableHeaderBackground(context, 143 g, 0, 0, c.getWidth(), c.getHeight()); 144 paint(context, g); 145 context.dispose(); 146 } 147 148 /** 149 * Paints the specified component according to the Look and Feel. 150 * <p>This method is not used by Synth Look and Feel. 151 * Painting is handled by the {@link #paint(SynthContext,Graphics)} method. 152 * 153 * @param g the {@code Graphics} object used for painting 154 * @param c the component being painted 155 * @see #paint(SynthContext,Graphics) 156 */ 157 @Override 158 public void paint(Graphics g, JComponent c) { 159 SynthContext context = getContext(c); 160 161 paint(context, g); 162 context.dispose(); 163 } 164 165 /** 166 * Paints the specified component. 167 * 168 * @param context context for the component being painted 169 * @param g the {@code Graphics} object used for painting 170 * @see #update(Graphics,JComponent) 171 */ 172 protected void paint(SynthContext context, Graphics g) { 173 super.paint(g, context.getComponent()); 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 @Override 180 public void paintBorder(SynthContext context, Graphics g, int x, 181 int y, int w, int h) { 182 context.getPainter().paintTableHeaderBorder(context, g, x, y, w, h); 183 } 184 // 185 // SynthUI 186 // 187 /** 188 * {@inheritDoc} 189 */ 190 @Override 191 public SynthContext getContext(JComponent c) { 192 return getContext(c, SynthLookAndFeel.getComponentState(c)); 193 } 194 195 private SynthContext getContext(JComponent c, int state) { 196 return SynthContext.getContext(SynthContext.class, c, 197 SynthLookAndFeel.getRegion(c), style, state); 198 } 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override 204 protected void rolloverColumnUpdated(int oldColumn, int newColumn) { 205 header.repaint(header.getHeaderRect(oldColumn)); 206 header.repaint(header.getHeaderRect(newColumn)); 207 } 208 209 /** 210 * {@inheritDoc} 211 */ 212 @Override 213 public void propertyChange(PropertyChangeEvent evt) { 214 if (SynthLookAndFeel.shouldUpdateStyle(evt)) { 215 updateStyle((JTableHeader)evt.getSource()); 216 } 217 } 218 219 private class HeaderRenderer extends DefaultTableCellHeaderRenderer { 220 HeaderRenderer() { 221 setHorizontalAlignment(JLabel.LEADING); 222 setName("TableHeader.renderer"); 223 } 224 225 @Override 226 public Component getTableCellRendererComponent(JTable table, Object value, 227 boolean isSelected, 228 boolean hasFocus, 229 int row, int column) { 230 231 boolean hasRollover = (column == getRolloverColumn()); 232 if (isSelected || hasRollover || hasFocus) { 233 SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. 234 getUIOfType(getUI(), SynthLabelUI.class), 235 isSelected, hasFocus, table.isEnabled(), 236 hasRollover); 237 } else { 238 SynthLookAndFeel.resetSelectedUI(); 239 } 240 241 //stuff a variable into the client property of this renderer indicating the sort order, 242 //so that different rendering can be done for the header based on sorted state. 243 RowSorter rs = table == null ? null : table.getRowSorter(); 244 java.util.List<? extends RowSorter.SortKey> sortKeys = rs == null ? null : rs.getSortKeys(); 245 if (sortKeys != null && sortKeys.size() > 0 && sortKeys.get(0).getColumn() == 246 table.convertColumnIndexToModel(column)) { 247 switch(sortKeys.get(0).getSortOrder()) { 248 case ASCENDING: 249 putClientProperty("Table.sortOrder", "ASCENDING"); 250 break; 251 case DESCENDING: 252 putClientProperty("Table.sortOrder", "DESCENDING"); 253 break; 254 case UNSORTED: 255 putClientProperty("Table.sortOrder", "UNSORTED"); 256 break; 257 default: 258 throw new AssertionError("Cannot happen"); 259 } 260 } else { 261 putClientProperty("Table.sortOrder", "UNSORTED"); 262 } 263 264 super.getTableCellRendererComponent(table, value, isSelected, 265 hasFocus, row, column); 266 267 return this; 268 } 269 270 @Override 271 public void setBorder(Border border) { 272 if (border instanceof SynthBorder) { 273 super.setBorder(border); 274 } 275 } 276 } 277 }