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