1 /* 2 * Copyright (c) 2002, 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 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 @SuppressWarnings("serial") // Superclass is not serializable across versions 220 private class HeaderRenderer extends DefaultTableCellHeaderRenderer { 221 HeaderRenderer() { 222 setHorizontalAlignment(JLabel.LEADING); 223 setName("TableHeader.renderer"); 224 } 225 226 @Override 227 public Component getTableCellRendererComponent(JTable table, Object value, 228 boolean isSelected, 229 boolean hasFocus, 230 int row, int column) { 231 232 boolean hasRollover = (column == getRolloverColumn()); 233 if (isSelected || hasRollover || hasFocus) { 234 SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. 235 getUIOfType(getUI(), SynthLabelUI.class), 236 isSelected, hasFocus, table.isEnabled(), 237 hasRollover); 238 } else { 239 SynthLookAndFeel.resetSelectedUI(); 240 } 241 242 //stuff a variable into the client property of this renderer indicating the sort order, 243 //so that different rendering can be done for the header based on sorted state. 244 RowSorter rs = table == null ? null : table.getRowSorter(); 245 java.util.List<? extends RowSorter.SortKey> sortKeys = rs == null ? null : rs.getSortKeys(); 246 if (sortKeys != null && sortKeys.size() > 0 && sortKeys.get(0).getColumn() == 247 table.convertColumnIndexToModel(column)) { 248 switch(sortKeys.get(0).getSortOrder()) { 249 case ASCENDING: 250 putClientProperty("Table.sortOrder", "ASCENDING"); 251 break; 252 case DESCENDING: 253 putClientProperty("Table.sortOrder", "DESCENDING"); 254 break; 255 case UNSORTED: 256 putClientProperty("Table.sortOrder", "UNSORTED"); 257 break; 258 default: 259 throw new AssertionError("Cannot happen"); 260 } 261 } else { 262 putClientProperty("Table.sortOrder", "UNSORTED"); 263 } 264 265 super.getTableCellRendererComponent(table, value, isSelected, 266 hasFocus, row, column); 267 268 return this; 269 } 270 271 @Override 272 public void setBorder(Border border) { 273 if (border instanceof SynthBorder) { 274 super.setBorder(border); 275 } 276 } 277 } 278 }