1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 package org.opensolaris.os.vp.util.swing.time; 28 29 import java.awt.*; 30 import java.awt.geom.*; 31 import javax.swing.*; 32 import org.opensolaris.os.vp.util.swing.*; 33 34 @SuppressWarnings({"serial"}) 35 public class SunIcon extends SquareCachedIcon { 36 // 37 // Static data 38 // 39 40 public static final int DEFAULT_DIAMETER = 100; 41 public static final int DEFAULT_RAY_COUNT = 20; 42 public static final float DEFAULT_ORB_SIZE_PERCENTAGE = .6f; 43 private static final Color COLOR_FOCUS = new Color(254, 247, 1); 44 private static final Color COLOR_MAIN = new Color(235, 148, 1); 45 private static final Color COLOR_EDGE = new Color(221, 119, 0); 46 47 // 48 // Instance data 49 // 50 51 private int nRays = DEFAULT_RAY_COUNT; 52 private float orbSizePct = DEFAULT_ORB_SIZE_PERCENTAGE; 53 54 // 55 // Constructors 56 // 57 58 /** 59 * Constructs a {@code SunIcon} with the given diameter. 60 */ 61 public SunIcon(int diameter) { 62 super(diameter); 63 } 64 65 /** 66 * Constructs a {@code SunIcon} with the diameter {@link 67 * #DEFAULT_DIAMETER}. 68 */ 69 public SunIcon() { 70 this(100); 71 } 72 73 // 74 // CachedIcon methods 75 // 76 77 @Override 78 public void paintIcon(Graphics2D g) { 79 int diameter = getDiameter(); 80 float radius = diameter / 2f; 81 82 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 83 RenderingHints.VALUE_ANTIALIAS_ON); 84 85 // Draw rays 86 87 float[] pctFromCtr = { 88 orbSizePct, 1f, orbSizePct 89 }; 90 91 float[] fractions = {orbSizePct, 1f}; 92 Color[] colors = {COLOR_EDGE, COLOR_MAIN}; 93 Paint paint = new RadialGradientPaint( 94 radius, radius, radius, fractions, colors, 95 MultipleGradientPaint.CycleMethod.NO_CYCLE); 96 g.setPaint(paint); 97 98 float radsPerRay = (float)(2 * Math.PI / nRays); 99 for (int j = 0; j < nRays; j++) { 100 float deltaRads = j * radsPerRay; 101 float[] angles = { 102 -(float)Math.PI / nRays + deltaRads, 103 (float)Math.toRadians(-5) + deltaRads, 104 (float)Math.PI / nRays + deltaRads, 105 }; 106 107 Point2D.Float[] points = new Point2D.Float[angles.length]; 108 109 for (int i = 0; i < angles.length; i++) { 110 float distFromCtr = radius * pctFromCtr[i]; 111 float x = radius + distFromCtr * (float)Math.cos(angles[i]); 112 float y = radius - distFromCtr * (float)Math.sin(angles[i]); 113 points[i] = new Point2D.Float(x, y); 114 } 115 116 GeneralPath path = new GeneralPath(); 117 path.moveTo(points[0].x, points[0].y); 118 119 Point2D.Float[] controls = { 120 new Point2D.Float(), 121 new Point2D.Float(), 122 }; 123 124 // 1st path component (points[0] -> [1]) is a cubic Bezier curve 125 126 Point2D.Float midPoint = new Point2D.Float( 127 (points[0].x + points[1].x) / 2, 128 (points[0].y + points[1].y) / 2); 129 130 // Ratio of distance between controls to distance between points 131 float factor = .75f; 132 float xDelta = factor * (points[1].x - midPoint.x) / 2; 133 float yDelta = factor * (points[1].y - midPoint.y) / 2; 134 controls[0].x = midPoint.x - yDelta; 135 controls[0].y = midPoint.y + xDelta; 136 controls[1].x = midPoint.x + yDelta; 137 controls[1].y = midPoint.y - xDelta; 138 139 path.curveTo(controls[0].x, controls[0].y, controls[1].x, 140 controls[1].y, points[1].x, points[1].y); 141 142 // 2nd path component (points[1] -> [2]) is a quadratic Bezier curve 143 144 midPoint = new Point2D.Float( 145 (points[1].x + points[2].x) / 2, 146 (points[1].y + points[2].y) / 2); 147 148 factor = .7f; 149 xDelta = factor * (points[1].x - midPoint.x) / 2; 150 yDelta = factor * (points[1].y - midPoint.y) / 2; 151 controls[0].x = midPoint.x + yDelta; 152 controls[0].y = midPoint.y - xDelta; 153 154 path.quadTo(controls[0].x, controls[0].y, points[2].x, points[2].y); 155 156 path.closePath(); 157 g.fill(path); 158 } 159 160 // Draw orb 161 162 float innerDiam = diameter * pctFromCtr[0]; 163 float innerRad = innerDiam / 2f; 164 float offset = (diameter - innerDiam) / 2f; 165 166 fractions = new float[] {0f, 1f}; 167 colors = new Color[] {COLOR_FOCUS, COLOR_MAIN}; 168 paint = new RadialGradientPaint( 169 innerRad + offset, innerRad + offset, innerRad, 170 innerRad + offset, innerRad / 2f + offset, fractions, colors, 171 MultipleGradientPaint.CycleMethod.NO_CYCLE); 172 173 g.setPaint(paint); 174 175 Ellipse2D.Float orb = new Ellipse2D.Float(offset, offset, innerDiam, 176 innerDiam); 177 178 g.fill(orb); 179 180 // Draw reflection 181 182 float yMargin = innerDiam * .04f; 183 float yStart = offset + yMargin; 184 float yEnd = offset + innerDiam * .5f; 185 186 paint = new GradientPaint(0, yStart, Color.white, 0, yEnd, 187 ColorUtil.alpha(Color.white, 0)); 188 189 float xMargin = innerDiam * .15f; 190 float xStart = offset + xMargin; 191 float width = innerDiam - 2 * xMargin; 192 float height = innerDiam * .5f - yMargin; 193 194 Ellipse2D.Float reflection = new Ellipse2D.Float(xStart, yStart, width, 195 height); 196 197 g.setPaint(paint); 198 g.fill(reflection); 199 } 200 201 // 202 // SunIcon methods 203 // 204 205 /** 206 * Gets the size of the main orb of the sun, relative to the overall 207 * diameter. 208 * 209 * @see #DEFAULT_ORB_SIZE_PERCENTAGE 210 */ 211 public float getOrbSizePercentage() { 212 return orbSizePct; 213 } 214 215 /** 216 * Sets the number of rays on the sun. 217 * 218 * @see #DEFAULT_RAY_COUNT 219 */ 220 public int getRayCount() { 221 return nRays; 222 } 223 224 /** 225 * Sets the size of the main orb of the sun, relative to the overall 226 * diameter. 227 * 228 * @see #DEFAULT_ORB_SIZE_PERCENTAGE 229 */ 230 public void setOrbSizePercentage(float orbSizePct) { 231 if (this.orbSizePct != orbSizePct) { 232 this.orbSizePct = orbSizePct; 233 invalidateCachedImage(); 234 } 235 } 236 237 /** 238 * Sets the number of rays on the sun. 239 * 240 * @see #DEFAULT_RAY_COUNT 241 */ 242 public void setRayCount(int nRays) { 243 if (this.nRays != nRays) { 244 this.nRays = nRays; 245 invalidateCachedImage(); 246 } 247 } 248 249 // 250 // Static methods 251 // 252 253 public static void main(String args[]) { 254 Color light = new Color(148, 188, 246); 255 Color dark = new Color(0, 0, 78); 256 257 int diameter = 301; 258 SunIcon sunIcon = new SunIcon(diameter); 259 JLabel sun = new JLabel(sunIcon); 260 261 MoonIcon moonIcon = new MoonIcon((int) 262 (sunIcon.getDiameter() * sunIcon.getOrbSizePercentage())); 263 JLabel moon = new JLabel(moonIcon); 264 265 StarIcon starIcon = new StarIcon(diameter); 266 starIcon.setDiameter((int)(moonIcon.getDiameter() * .5f)); 267 JLabel star = new JLabel(starIcon); 268 269 GradientPanel p = new GradientPanel(light, dark); 270 p.setLayout(new BorderLayout()); 271 p.add(sun, BorderLayout.NORTH); 272 p.add(star, BorderLayout.CENTER); 273 p.add(moon, BorderLayout.SOUTH); 274 275 JFrame frame = new JFrame(); 276 Container cont = frame.getContentPane(); 277 cont.setLayout(new BorderLayout()); 278 cont.add(p, BorderLayout.CENTER); 279 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 280 frame.pack(); 281 frame.setVisible(true); 282 } 283 } 284