1 /* 2 * Copyright (c) 1997, 2006, 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 package javax.swing.plaf.basic; 26 27 import java.awt.Dimension; 28 import java.awt.Graphics; 29 import java.awt.Color; 30 31 import javax.swing.*; 32 import javax.swing.plaf.UIResource; 33 34 /** 35 * JButton object that draws a scaled Arrow in one of the cardinal directions. 36 * <p> 37 * <strong>Warning:</strong> 38 * Serialized objects of this class will not be compatible with 39 * future Swing releases. The current serialization support is 40 * appropriate for short term storage or RMI between applications running 41 * the same version of Swing. As of 1.4, support for long term storage 42 * of all JavaBeans™ 43 * has been added to the <code>java.beans</code> package. 44 * Please see {@link java.beans.XMLEncoder}. 45 * 46 * @author David Kloba 47 */ 48 public class BasicArrowButton extends JButton implements SwingConstants 49 { 50 /** 51 * The direction of the arrow. One of 52 * {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH}, 53 * {@code SwingConstants.EAST} or {@code SwingConstants.WEST}. 54 */ 55 protected int direction; 56 57 private Color shadow; 58 private Color darkShadow; 59 private Color highlight; 60 61 /** 62 * Creates a {@code BasicArrowButton} whose arrow 63 * is drawn in the specified direction and with the specified 64 * colors. 65 * 66 * @param direction the direction of the arrow; one of 67 * {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH}, 68 * {@code SwingConstants.EAST} or {@code SwingConstants.WEST} 69 * @param background the background color of the button 70 * @param shadow the color of the shadow 71 * @param darkShadow the color of the dark shadow 72 * @param highlight the color of the highlight 73 * @since 1.4 74 */ 75 public BasicArrowButton(int direction, Color background, Color shadow, 76 Color darkShadow, Color highlight) { 77 super(); 78 setRequestFocusEnabled(false); 79 setDirection(direction); 80 setBackground(background); 81 this.shadow = shadow; 82 this.darkShadow = darkShadow; 83 this.highlight = highlight; 84 } 85 86 /** 87 * Creates a {@code BasicArrowButton} whose arrow 88 * is drawn in the specified direction. 89 * 90 * @param direction the direction of the arrow; one of 91 * {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH}, 92 * {@code SwingConstants.EAST} or {@code SwingConstants.WEST} 93 */ 94 public BasicArrowButton(int direction) { 95 this(direction, UIManager.getColor("control"), UIManager.getColor("controlShadow"), 96 UIManager.getColor("controlDkShadow"), UIManager.getColor("controlLtHighlight")); 97 } 98 99 /** 100 * Returns the direction of the arrow. 101 */ 102 public int getDirection() { 103 return direction; 104 } 105 106 /** 107 * Sets the direction of the arrow. 108 * 109 * @param direction the direction of the arrow; one of 110 * of {@code SwingConstants.NORTH}, 111 * {@code SwingConstants.SOUTH}, 112 * {@code SwingConstants.EAST} or {@code SwingConstants.WEST} 113 */ 114 public void setDirection(int direction) { 115 this.direction = direction; 116 } 117 118 public void paint(Graphics g) { 119 Color origColor; 120 boolean isPressed, isEnabled; 121 int w, h, size; 122 123 w = getSize().width; 124 h = getSize().height; 125 origColor = g.getColor(); 126 isPressed = getModel().isPressed(); 127 isEnabled = isEnabled(); 128 129 g.setColor(getBackground()); 130 g.fillRect(1, 1, w-2, h-2); 131 132 /// Draw the proper Border 133 if (getBorder() != null && !(getBorder() instanceof UIResource)) { 134 paintBorder(g); 135 } else if (isPressed) { 136 g.setColor(shadow); 137 g.drawRect(0, 0, w-1, h-1); 138 } else { 139 // Using the background color set above 140 g.drawLine(0, 0, 0, h-1); 141 g.drawLine(1, 0, w-2, 0); 142 143 g.setColor(highlight); // inner 3D border 144 g.drawLine(1, 1, 1, h-3); 145 g.drawLine(2, 1, w-3, 1); 146 147 g.setColor(shadow); // inner 3D border 148 g.drawLine(1, h-2, w-2, h-2); 149 g.drawLine(w-2, 1, w-2, h-3); 150 151 g.setColor(darkShadow); // black drop shadow __| 152 g.drawLine(0, h-1, w-1, h-1); 153 g.drawLine(w-1, h-1, w-1, 0); 154 } 155 156 // If there's no room to draw arrow, bail 157 if(h < 5 || w < 5) { 158 g.setColor(origColor); 159 return; 160 } 161 162 if (isPressed) { 163 g.translate(1, 1); 164 } 165 166 // Draw the arrow 167 size = Math.min((h - 4) / 3, (w - 4) / 3); 168 size = Math.max(size, 2); 169 paintTriangle(g, (w - size) / 2, (h - size) / 2, 170 size, direction, isEnabled); 171 172 // Reset the Graphics back to it's original settings 173 if (isPressed) { 174 g.translate(-1, -1); 175 } 176 g.setColor(origColor); 177 178 } 179 180 /** 181 * Returns the preferred size of the {@code BasicArrowButton}. 182 * 183 * @return the preferred size 184 */ 185 public Dimension getPreferredSize() { 186 return new Dimension(16, 16); 187 } 188 189 /** 190 * Returns the minimum size of the {@code BasicArrowButton}. 191 * 192 * @return the minimum size 193 */ 194 public Dimension getMinimumSize() { 195 return new Dimension(5, 5); 196 } 197 198 /** 199 * Returns the maximum size of the {@code BasicArrowButton}. 200 * 201 * @return the maximum size 202 */ 203 public Dimension getMaximumSize() { 204 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 205 } 206 207 /** 208 * Returns whether the arrow button should get the focus. 209 * {@code BasicArrowButton}s are used as a child component of 210 * composite components such as {@code JScrollBar} and 211 * {@code JComboBox}. Since the composite component typically gets the 212 * focus, this method is overriden to return {@code false}. 213 * 214 * @return {@code false} 215 */ 216 public boolean isFocusTraversable() { 217 return false; 218 } 219 220 /** 221 * Paints a triangle. 222 * 223 * @param g the {@code Graphics} to draw to 224 * @param x the x coordinate 225 * @param y the y coordinate 226 * @param size the size of the triangle to draw 227 * @param direction the direction in which to draw the arrow; 228 * one of {@code SwingConstants.NORTH}, 229 * {@code SwingConstants.SOUTH}, {@code SwingConstants.EAST} or 230 * {@code SwingConstants.WEST} 231 * @param isEnabled whether or not the arrow is drawn enabled 232 */ 233 public void paintTriangle(Graphics g, int x, int y, int size, 234 int direction, boolean isEnabled) { 235 Color oldColor = g.getColor(); 236 int mid, i, j; 237 238 j = 0; 239 size = Math.max(size, 2); 240 mid = (size / 2) - 1; 241 242 g.translate(x, y); 243 if(isEnabled) 244 g.setColor(darkShadow); 245 else 246 g.setColor(shadow); 247 248 switch(direction) { 249 case NORTH: 250 for(i = 0; i < size; i++) { 251 g.drawLine(mid-i, i, mid+i, i); 252 } 253 if(!isEnabled) { 254 g.setColor(highlight); 255 g.drawLine(mid-i+2, i, mid+i, i); 256 } 257 break; 258 case SOUTH: 259 if(!isEnabled) { 260 g.translate(1, 1); 261 g.setColor(highlight); 262 for(i = size-1; i >= 0; i--) { 263 g.drawLine(mid-i, j, mid+i, j); 264 j++; 265 } 266 g.translate(-1, -1); 267 g.setColor(shadow); 268 } 269 270 j = 0; 271 for(i = size-1; i >= 0; i--) { 272 g.drawLine(mid-i, j, mid+i, j); 273 j++; 274 } 275 break; 276 case WEST: 277 for(i = 0; i < size; i++) { 278 g.drawLine(i, mid-i, i, mid+i); 279 } 280 if(!isEnabled) { 281 g.setColor(highlight); 282 g.drawLine(i, mid-i+2, i, mid+i); 283 } 284 break; 285 case EAST: 286 if(!isEnabled) { 287 g.translate(1, 1); 288 g.setColor(highlight); 289 for(i = size-1; i >= 0; i--) { 290 g.drawLine(j, mid-i, j, mid+i); 291 j++; 292 } 293 g.translate(-1, -1); 294 g.setColor(shadow); 295 } 296 297 j = 0; 298 for(i = size-1; i >= 0; i--) { 299 g.drawLine(j, mid-i, j, mid+i); 300 j++; 301 } 302 break; 303 } 304 g.translate(-x, -y); 305 g.setColor(oldColor); 306 } 307 308 }