Utilties for painting visual effects
/*
* $Id: PaintUtils.java,v 1.24 2009/05/25 16:37:52 kschaefe Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
/**
* A collection of utilties for painting visual effects.
*
* @author Mark Davidson
*/
public class PaintUtils {
public static final GradientPaint BLUE_EXPERIENCE = new GradientPaint(
new Point2D.Double(0, 0),
new Color(168, 204, 241),
new Point2D.Double(0, 1),
new Color(44, 61, 146));
public static final GradientPaint MAC_OSX_SELECTED = new GradientPaint(
new Point2D.Double(0, 0),
new Color(81, 141, 236),
new Point2D.Double(0, 1),
new Color(36, 96, 192));
public static final GradientPaint MAC_OSX = new GradientPaint(
new Point2D.Double(0, 0),
new Color(167, 210, 250),
new Point2D.Double(0, 1),
new Color(99, 147, 206));
public static final GradientPaint AERITH = new GradientPaint(
new Point2D.Double(0, 0),
Color.WHITE,
new Point2D.Double(0, 1),
new Color(64, 110, 161));
public static final GradientPaint GRAY = new GradientPaint(
new Point2D.Double(0, 0),
new Color(226, 226, 226),
new Point2D.Double(0, 1),
new Color(250, 248, 248));
public static final GradientPaint RED_XP = new GradientPaint(
new Point2D.Double(0, 0),
new Color(236, 81, 81),
new Point2D.Double(0, 1),
new Color(192, 36, 36));
public static final GradientPaint NIGHT_GRAY = new GradientPaint(
new Point2D.Double(0, 0),
new Color(102, 111, 127),
new Point2D.Double(0, 1),
new Color(38, 45, 61));
public static final GradientPaint NIGHT_GRAY_LIGHT = new GradientPaint(
new Point2D.Double(0, 0),
new Color(129, 138, 155),
new Point2D.Double(0, 1),
new Color(58, 66, 82));
private PaintUtils() {
}
/**
* Returns the bounds that the text of a label will be drawn into.
* Takes into account the current font metrics.
*/
public static Rectangle getTextBounds(Graphics g, JLabel label) {
FontMetrics fm = g.getFontMetrics();
Rectangle2D r2d = fm.getStringBounds(label.getText(), g);
Rectangle rect = r2d.getBounds();
int xOffset = 0;
switch (label.getHorizontalAlignment()) {
case SwingConstants.RIGHT:
case SwingConstants.TRAILING:
xOffset = label.getBounds().width - rect.width;
break;
case SwingConstants.CENTER:
xOffset = (label.getBounds().width - rect.width) / 2;
break;
default:
case SwingConstants.LEFT:
case SwingConstants.LEADING:
xOffset = 0;
break;
}
int yOffset = 0;
switch (label.getVerticalAlignment()) {
case SwingConstants.TOP:
yOffset = 0;
break;
case SwingConstants.CENTER:
yOffset = (label.getBounds().height - rect.height) / 2;
break;
case SwingConstants.BOTTOM:
yOffset = label.getBounds().height - rect.height;
break;
}
return new Rectangle(xOffset, yOffset, rect.width, rect.height);
}
/**
* Paints a top to bottom gradient fill over the component bounds
* from color1 to color2.
*/
public static void paintGradient(Graphics g, JComponent comp,
Color color1, Color color2) {
GradientPaint paint = new GradientPaint(0, 0, color1,
0, comp.getHeight(), color2,
true);
Graphics2D g2 = (Graphics2D) g;
Paint oldPaint = g2.getPaint();
g2.setPaint(paint);
g2.fillRect(0, 0, comp.getWidth(), comp.getHeight());
g2.setPaint(oldPaint);
}
/** Resizes a gradient to fill the width and height available. If the
* gradient is left to right it will be resized to fill the entire width.
* If the gradient is top to bottom it will be resized to fill the entire
* height. If the gradient is on an angle it will be resized to go from
* one corner to the other of the rectangle formed by (0,0 -> width,height).
*
* This method can resize java.awt.GradientPaint, java.awt.LinearGradientPaint,
* and the LinearGradientPaint implementation from Apache's Batik project. Note,
* this method does not require the MultipleGradientPaint.jar from Apache to
* compile or to run. MultipleGradientPaint.jar *is* required if you want
* to resize the LinearGradientPaint from that jar.
*
* Any paint passed into this method which is not a kind of gradient paint (like
* a Color or TexturePaint) will be returned unmodified. It will not throw
* an exception. If the gradient cannot be resized due to other errors the
* original paint will be returned unmodified. It will not throw an
* exception.
*
*/
public static Paint resizeGradient(Paint p, int width, int height) {
if(p == null) return p;
if(p instanceof GradientPaint) {
GradientPaint gp = (GradientPaint)p;
Point2D[] pts = new Point2D[2];
pts[0] = gp.getPoint1();
pts[1] = gp.getPoint2();
pts = adjustPoints(pts, width, height);
return new GradientPaint(pts[0], gp.getColor1(), pts[1], gp.getColor2(), gp.isCyclic());
}
if("java.awt.LinearGradientPaint".equals(p.getClass().getName()) ||
"org.apache.batik.ext.awt.LinearGradientPaint".equals(p.getClass().getName())) {
return resizeLinearGradient(p,width,height);
}
return p;
}
private static Paint resizeLinearGradient(Paint p, int width, int height) {
try {
Point2D[] pts = new Point2D[2];
pts[0] = (Point2D) invokeMethod(p,"getStartPoint");
pts[1] = (Point2D) invokeMethod(p,"getEndPoint");
pts = adjustPoints(pts, width, height);
float[] fractions = (float[]) invokeMethod(p,"getFractions");
Color[] colors = (Color[]) invokeMethod(p,"getColors");
Constructor<?> con = p.getClass().getDeclaredConstructor(
Point2D.class, Point2D.class,
new float[0].getClass(),
new Color[0].getClass());
return (Paint) con.newInstance(pts[0],pts[1],fractions, colors);
} catch (Exception ex) {
ex.printStackTrace();
}
return p;
}
private static Object invokeMethod(final Object p, final String methodName)
throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, SecurityException, IllegalAccessException {
Method meth = p.getClass().getMethod(methodName);
return meth.invoke(p);
}
private static Point2D[] adjustPoints(Point2D[] pts, int width, int height) {
Point2D start = pts[0];
Point2D end = pts[1];
double angle = calcAngle(start,end);
double a2 = Math.toDegrees(angle);
double e = 1;
// if it is near 0 degrees
if(Math.abs(angle) < Math.toRadians(e) ||
Math.abs(angle) > Math.toRadians(360-e)) {
start = new Point2D.Float(0,0);
end = new Point2D.Float(width,0);
}
// near 45
if(isNear(a2, 45, e)) {
start = new Point2D.Float(0,0);
end = new Point2D.Float(width,height);
}
// near 90
if(isNear(a2, 90, e)) {
start = new Point2D.Float(0,0);
end = new Point2D.Float(0,height);
}
// near 135
if(isNear(a2, 135, e)) {
start = new Point2D.Float(width,0);
end = new Point2D.Float(0,height);
}
// near 180
if(isNear(a2, 180, e)) {
start = new Point2D.Float(width,0);
end = new Point2D.Float(0,0);
}
// near 225
if(isNear(a2, 225, e)) {
start = new Point2D.Float(width,height);
end = new Point2D.Float(0,0);
}
// near 270
if(isNear(a2, 270, e)) {
start = new Point2D.Float(0,height);
end = new Point2D.Float(0,0);
}
// near 315
if(isNear(a2, 315, e)) {
start = new Point2D.Float(0,height);
end = new Point2D.Float(width,0);
}
return new Point2D[] { start, end };
}
private static boolean isNear(double angle, double target, double error) {
return Math.abs(target - Math.abs(angle)) < error;
}
private static double calcAngle(Point2D p1, Point2D p2) {
double x_off = p2.getX() - p1.getX();
double y_off = p2.getY() - p1.getY();
double angle = Math.atan(y_off / x_off);
if (x_off < 0) {
angle = angle + Math.PI;
}
if(angle < 0) { angle+= 2*Math.PI; }
if(angle > 2*Math.PI) { angle -= 2*Math.PI; }
return angle;
}
/*
public static void main(String ... args) {
LinearGradientPaint in = new LinearGradientPaint(
new Point(0,0), new Point(10,0),
new float[] {0f, 0.5f, 1f},
new Color[] {Color.RED, Color.GREEN, Color.BLUE});
log.fine("in = " + toString(in));
Paint out = resizeGradient(in,100,100);
log.fine(("out = " + toString((MultipleGradientPaint) out));
}*/
/*
private static String toString(MultipleGradientPaint paint) {
StringBuffer buffer = new StringBuffer();
buffer.append(paint.getClass().getName());
Color[] colors = paint.getColors();
float[] values = paint.getFractions();
buffer.append("[");
for(int i=0; i<colors.length; i++) {
buffer.append("#").append(Integer.toHexString(colors[i].getRGB()));
buffer.append(":");
buffer.append(values[i]);
buffer.append(", ");
}
buffer.append("]");
if(paint instanceof LinearGradientPaint) {
LinearGradientPaint lgp = (LinearGradientPaint) paint;
buffer.append(", ");
buffer.append(""+lgp.getStartPoint().getX() + ", " + lgp.getStartPoint().getY());
buffer.append("->");
buffer.append(""+lgp.getEndPoint().getX() + ", " + lgp.getEndPoint().getY());
}
return buffer.toString();
}*/
// private static void p(String string) {
// log.fine((string);
// }
}
Related examples in the same category