1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.spc.ofp.raptor;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.swingx.graphics.BlendComposite;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.jdesktop.swingx.image.GaussianBlurFilter;
import org.jdesktop.swingx.painter.AbstractPainter;
class JellyButtonPainter<T extends AbstractButton> extends AbstractPainter<T> {
// Button shape.
private RoundRectangle2D.Float rect = new RoundRectangle2D.Float();
//Bakcground.
private float[] backgroundFractions = {0, 0.4999f, 0.5f, 1f};
private Color[] backgroundColors = {new Color(98, 108, 136), new Color(63, 71, 86), new Color(17, 17, 17), new Color(59, 70, 110)};
private Paint backgroundPaint;
// Outer border.
private Paint outerBorderPaint = Color.BLACK;
private Stroke outerBorderStroke = new BasicStroke(1.0f);
private Composite outerBorderComposite = AlphaComposite.SrcOver;
// Inner border.
private float[] innerBorderFractions = {0, 0.4999f, 0.5f, 1f};
private Color[] innerBorderColors = {Color.WHITE, new Color(105, 105, 105), Color.WHITE, new Color(105, 105, 105)};
private Composite innerBorderComposite = BlendComposite.Screen.derive(0.5f);
private Paint innerBorderPaint;
private Stroke innerBorderStroke = new BasicStroke(3.0f);
// Glow
private BufferedImage glowImage;
private Composite glowComposite = BlendComposite.ColorDodge;
// Sate paints.
private Paint armedPaint = new Color(64, 64, 64);
private Paint selectedPaint = new Color(104, 158, 216);
private Paint armedSelectedPaint = new Color(50, 118, 190);
private Paint rolloverSelectedPaint = new Color(136, 179, 224);
private float[] rolloverFractions = {0.0f, 0.05f, 0.35f, 1.0f};
private Color[] rolloverColors = {Color.WHITE, Color.WHITE, new Color(127, 127, 127, 0), new Color(127, 127, 127, 0)};
private Paint rolloverPaint;
private Paint disabledPaint = new Color(192, 192, 192);
private Paint disabledSelectedPaint = new Color(160, 160, 160);
// State composites.
private Composite highlights1Composite = BlendComposite.HardLight.derive(0.5f);
private Composite highlights2Composite = BlendComposite.Overlay.derive(0.3f);
private Composite highlights3Composite = BlendComposite.ColorDodge.derive(0.3f);
/** Last know width.
*/
private int width;
/** Last known height.
*/
private int height;
/** the button's image.
*/
public JellyButtonPainter(T target) {
// Make use of abstract painter's cacheability feature.
setCacheable(true);
// But then we need to be aware when the button's state changes.
target.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent event) {
// Will provoke a redraw of the cached image.
setDirty(true);
}
});
}
/** Rerender glow intermediate image.
* @param object The target object.
* @param width Width of the drawing area.
* @param height Height of the drawing area.
*/
private void createGlowImage(T object, int width, int height) {
if (width <= 0 || height <= 0) {
return;
}
int rectX = (int) Math.floor(rect.getX());
int rectY = (int) Math.floor(rect.getY());
int rectWidth = (int) Math.ceil(rect.getWidth());
int rectHeight = (int) Math.ceil(rect.getHeight());
glowImage = GraphicsUtilities.createCompatibleTranslucentImage(width, height);
//glowImage = GraphicsUtilities.createCompatibleTranslucentImage(rectWidth, rectHeight);
// Draw base shape.
Graphics2D g = glowImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setColor(new Color(136, 179, 224));
//g.fillOval(5, (int) (rectHeight * 2 / 3f), rectWidth - 5, (int) (rectHeight * 2 / 3f));
g.fillOval(rectX + 5, (int) (rectY + rectHeight * 2 / 3f), rectWidth - 2 * 5, (int) (rectHeight * 2 / 3f));
g.dispose();
// Apply gaussian blur.
// Hum values are funny, I used a 5.0 blur in PSP and here it requires a double-15 blur and still does not look OK.
// Documentation is odd, only uses integer but mentions 0.1 radius.
GaussianBlurFilter gaussianBlur = new GaussianBlurFilter(15);
glowImage = gaussianBlur.filter(glowImage, null);
glowImage = gaussianBlur.filter(glowImage, null);
glowImage = gaussianBlur.filter(glowImage, null);
// Hack.
// Clear outsite parts.
g = glowImage.createGraphics();
Area area = new Area(new Rectangle(0, 0, width, height));
area.subtract(new Area(rect));
g.setClip(area);
g.setComposite(AlphaComposite.Clear);
g.fillRect(0, 0, width, height);
g.dispose();
}
private void renderButton(Graphics2D g, T object, int width, int height) {
int rectX = (int) Math.floor(rect.getX());
int rectY = (int) Math.floor(rect.getY());
int rectWidth = (int) Math.ceil(rect.getWidth());
int rectHeight = (int) Math.ceil(rect.getHeight());
Shape oldClip = g.getClip();
g.setClip(rect);
backgroundPaint = new LinearGradientPaint(0, 0, 0, rectHeight, backgroundFractions, backgroundColors);
innerBorderPaint = new LinearGradientPaint(0, 0, 0, rectHeight, innerBorderFractions, innerBorderColors);
rolloverPaint = new LinearGradientPaint(0, 0, 0, rectHeight, rolloverFractions, rolloverColors);
// Background.
g.setPaint(backgroundPaint);
g.fill(rect);
// Hightlights.
//System.out.println("Armed: "+model.isArmed());
//System.out.println("Enabled: "+model.isEnabled());
//System.out.println("Pressed: "+model.isPressed());
//System.out.println("Rollover: "+model.isRollover());
//System.out.println("Selected: "+model.isSelected());
//System.out.println();
Paint paint = null;
ButtonModel model = object.getModel();
if (!model.isEnabled() && model.isSelected()) {
paint = disabledSelectedPaint;
}
else if (!model.isEnabled()) {
paint = disabledPaint;
}
else if (model.isArmed() && model.isSelected()) {
paint = armedSelectedPaint;
}
else if (model.isRollover() && model.isSelected()) {
paint = rolloverSelectedPaint;
}
else if (model.isSelected()) {
paint = selectedPaint;
}
else if (model.isArmed()) {
paint = armedPaint;
}
else if (model.isRollover()) {
paint = rolloverPaint;
}
if (paint != null) {
g.setPaint(paint);
// Highlights 1.
g.setComposite(highlights1Composite);
g.fill(rect);
// Highlights 2.
g.setComposite(highlights2Composite);
g.fill(rect);
// Highlights 3.
g.setComposite(highlights3Composite);
g.fill(rect);
}
// Inner glowImage.
if ((model.isRollover() || model.isSelected() || model.isArmed()) && glowImage != null) {
// Hack.
g.setClip(oldClip);
g.setComposite(glowComposite);
//g.setComposite(AlphaComposite.SrcOver);
try {
g.drawImage(glowImage, 0, 0, null);
//g.drawImage(glowImage.getSubimage(rectX, rectY, rectWidth, rectHeight), rectX, rectY, null);
//g.drawImage(glowImage, rectX, rectY, null);
}
catch (Exception e) {
System.err.println(glowImage.getWidth()+", "+glowImage.getHeight()+"\t"+width+", "+height);
e.printStackTrace();
}
// Hack.
g.setClip(rect);
}
// Inner border.
g.setComposite(innerBorderComposite);
g.setPaint(innerBorderPaint);
g.setStroke(innerBorderStroke);
g.draw(rect);
g.setClip(oldClip);
// Outer border.
g.setComposite(outerBorderComposite);
g.setStroke(outerBorderStroke);
g.setPaint(outerBorderPaint);
g.draw(rect);
}
/** {@inheritDoc}
*/
@Override
protected void doPaint(Graphics2D g, T object, int width, int height) {
//Insets insets = object.getMargin();
//rect.setRoundRect(insets.left, insets.top, width - (insets.left + insets.right) - 1, height - (insets.top + insets.bottom) - 1, 10, 10);
rect.setRoundRect(0, 0, width - 1, height - 1, 10, 10);
if (width != this.width || height != this.height || glowImage == null) {
createGlowImage(object, width, height);
this.width = width;
this.height = height;
}
renderButton(g, object, width, height);
}
} |
Partager