Home | History | Annotate | Download | only in time
      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