001 /*
002 * $Id: NeonBorderEffect.java 3166 2009-01-02 13:27:18Z rah003 $
003 *
004 * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022
023 package org.jdesktop.swingx.painter.effects;
024
025 import java.awt.*;
026
027 /**
028 * An effect which draws a multicolored border around a painter's shape.
029 * It will interpolate between two specified colors, creating a neon like effect.
030 * @author joshy
031 */
032 public class NeonBorderEffect extends AbstractAreaEffect {
033
034 private Color edgeColor;
035 private Color centerColor;
036 private BorderPosition borderPosition = BorderPosition.Outside;
037
038 /**
039 * An enum representing the position of the border: inside, outside, or centered on the border.
040 */
041 public enum BorderPosition { Inside, Centered, Outside }
042
043
044 /**
045 * Create a new NeonBorderEffect
046 */
047 public NeonBorderEffect() {
048 this(Color.GREEN, Color.WHITE, 10);
049 }
050
051 /** Creates a new instance of NeonBorderEffect */
052 public NeonBorderEffect(Color edgeColor, Color centerColor, int effectWidth) {
053 super();
054 setEffectWidth(effectWidth);
055 this.setEdgeColor(edgeColor);
056 this.setCenterColor(centerColor);
057 this.setRenderInsideShape(false);
058 this.setShouldFillShape(false);
059 this.setOffset(new Point(0,0));
060 }
061
062 protected void paintBorderGlow(Graphics2D gfx, Shape clipShape, int width, int height) {
063
064 /*
065 // draw the effect
066 for(float i=steps-1; i>=0; i=i-1f) {
067 float brushWidth = i * getEffectWidth()/steps;
068 gfx.setPaint(interpolateColor(i/steps,edgeColor,centerColor));
069 gfx.setStroke(new BasicStroke(brushWidth,
070 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
071 gfx.draw(clipShape);
072 }*/
073
074 /* // an interesting outline effect. stroke the shape with a wide brush
075 * // then stroke again with slightly less wide one, then don't fill the middle
076 for(int i=0; i<2; i++) {
077 float brushWidth = (2-i)*5;
078 p("widdth = " + brushWidth);
079 gfx.setPaint(interpolateColor((float)(1-i), Color.BLACK, Color.WHITE));
080 gfx.setStroke(new BasicStroke(brushWidth));
081 gfx.draw(clipShape);
082 }
083 */
084 gfx.translate(getOffset().getX(), getOffset().getY());
085 gfx.setComposite(AlphaComposite.SrcOver);
086 int steps = getEffectWidth();
087 if(borderPosition == BorderPosition.Centered) {
088 steps = steps/2;
089 }
090 for(int i=0; i<steps; i++) {
091
092 // make the brush width smaller each time until there is nothing left
093 float brushWidth = (float)(steps+1-i);
094 float half = steps/2;
095
096 if(borderPosition == BorderPosition.Centered) {
097 gfx.setPaint(interpolateColor((float)(steps-i)/steps, getEdgeColor(), getCenterColor()));
098 } else {
099 if(i<half) {
100 gfx.setPaint(interpolateColor((float)(half-i)/half, getEdgeColor(), getCenterColor()));
101 } else {
102 gfx.setPaint(interpolateColor((float)(i-half)/half, getEdgeColor(), getCenterColor()));
103 }
104 }
105
106 // to make the effect softer use a different stroke
107 gfx.setStroke(new BasicStroke(brushWidth,
108 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
109 //gfx.setStroke(new BasicStroke(brushWidth));
110 gfx.draw(clipShape);
111 }
112 gfx.translate(-getOffset().getX(), -getOffset().getY());
113
114 }
115
116 protected Color interpolateColor(float t, Color start, Color end) {
117 float[] partsS = start.getRGBComponents(null);
118 float[] partsE = end.getRGBComponents(null);
119 float[] partsR = new float[4];
120 for(int i=0; i<4; i++) {
121 partsR[i] = (partsS[i] - partsE[i])*t + partsE[i];
122 }
123 return new Color(partsR[0],partsR[1],partsR[2],partsR[3]);
124 }
125
126 /**
127 * Gets the current edge color.
128 * @return current edge color
129 */
130 public Color getEdgeColor() {
131 return edgeColor;
132 }
133
134 /**
135 * Set the edge color
136 * @param edgeColor
137 */
138 public void setEdgeColor(Color edgeColor) {
139 this.edgeColor = edgeColor;
140 }
141
142 /**
143 *
144 * @return color in the center of the effect
145 */
146 public Color getCenterColor() {
147 return centerColor;
148 }
149
150 /**
151 *
152 * @param centerColor color in the center of the effect.
153 * @see #getCenterColor()
154 */
155 public void setCenterColor(Color centerColor) {
156 this.centerColor = centerColor;
157 }
158
159 /**
160 *
161 * @return position of the border relative to the edge of painter covered area.
162 * @see BorderPosition
163 */
164 public BorderPosition getBorderPosition() {
165 return borderPosition;
166 }
167
168 /**
169 *
170 * @param borderPosition position of the border relative to the edge of painter covered area.
171 * @see #getBorderPosition()
172 * @see BorderPosition
173 */
174 public void setBorderPosition(BorderPosition borderPosition) {
175 this.borderPosition = borderPosition;
176 switch(borderPosition) {
177 case Centered :
178 setShapeMasked(false);
179 break;
180 case Inside :
181 setShapeMasked(true);
182 setRenderInsideShape(true);
183 break;
184 case Outside :
185 setShapeMasked(true);
186 setRenderInsideShape(false);
187 break;
188 }
189 if(borderPosition == BorderPosition.Centered) {
190 }
191 }
192 }