001/* 002 * $Id: NeonBorderEffect.java 3829 2010-10-07 02:01:20Z kschaefe $ 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 023package org.jdesktop.swingx.painter.effects; 024 025import java.awt.AlphaComposite; 026import java.awt.BasicStroke; 027import java.awt.Color; 028import java.awt.Graphics2D; 029import java.awt.Point; 030import java.awt.Shape; 031 032/** 033 * An effect which draws a multicolored border around a painter's shape. 034 * It will interpolate between two specified colors, creating a neon like effect. 035 * @author joshy 036 */ 037public class NeonBorderEffect extends AbstractAreaEffect { 038 039 private Color edgeColor; 040 private Color centerColor; 041 private BorderPosition borderPosition = BorderPosition.Outside; 042 043 /** 044 * An enum representing the position of the border: inside, outside, or centered on the border. 045 */ 046 public enum BorderPosition { Inside, Centered, Outside } 047 048 049 /** 050 * Create a new NeonBorderEffect 051 */ 052 public NeonBorderEffect() { 053 this(Color.GREEN, Color.WHITE, 10); 054 } 055 056 /** Creates a new instance of NeonBorderEffect */ 057 public NeonBorderEffect(Color edgeColor, Color centerColor, int effectWidth) { 058 super(); 059 setEffectWidth(effectWidth); 060 this.setEdgeColor(edgeColor); 061 this.setCenterColor(centerColor); 062 this.setRenderInsideShape(false); 063 this.setShouldFillShape(false); 064 this.setOffset(new Point(0,0)); 065 } 066 067 @Override 068 protected void paintBorderGlow(Graphics2D gfx, Shape clipShape, int width, int height) { 069 070 /* 071 // draw the effect 072 for(float i=steps-1; i>=0; i=i-1f) { 073 float brushWidth = i * getEffectWidth()/steps; 074 gfx.setPaint(interpolateColor(i/steps,edgeColor,centerColor)); 075 gfx.setStroke(new BasicStroke(brushWidth, 076 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 077 gfx.draw(clipShape); 078 }*/ 079 080 /* // an interesting outline effect. stroke the shape with a wide brush 081 * // then stroke again with slightly less wide one, then don't fill the middle 082 for(int i=0; i<2; i++) { 083 float brushWidth = (2-i)*5; 084 p("widdth = " + brushWidth); 085 gfx.setPaint(interpolateColor((float)(1-i), Color.BLACK, Color.WHITE)); 086 gfx.setStroke(new BasicStroke(brushWidth)); 087 gfx.draw(clipShape); 088 } 089 */ 090 gfx.translate(getOffset().getX(), getOffset().getY()); 091 gfx.setComposite(AlphaComposite.SrcOver); 092 int steps = getEffectWidth(); 093 if(borderPosition == BorderPosition.Centered) { 094 steps = steps/2; 095 } 096 for(int i=0; i<steps; i++) { 097 098 // make the brush width smaller each time until there is nothing left 099 float brushWidth = steps+1-i; 100 float half = steps/2; 101 102 if(borderPosition == BorderPosition.Centered) { 103 gfx.setPaint(interpolateColor((float)(steps-i)/steps, getEdgeColor(), getCenterColor())); 104 } else { 105 if(i<half) { 106 gfx.setPaint(interpolateColor((half-i)/half, getEdgeColor(), getCenterColor())); 107 } else { 108 gfx.setPaint(interpolateColor((i-half)/half, getEdgeColor(), getCenterColor())); 109 } 110 } 111 112 // to make the effect softer use a different stroke 113 gfx.setStroke(new BasicStroke(brushWidth, 114 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 115 //gfx.setStroke(new BasicStroke(brushWidth)); 116 gfx.draw(clipShape); 117 } 118 gfx.translate(-getOffset().getX(), -getOffset().getY()); 119 120 } 121 122 protected Color interpolateColor(float t, Color start, Color end) { 123 float[] partsS = start.getRGBComponents(null); 124 float[] partsE = end.getRGBComponents(null); 125 float[] partsR = new float[4]; 126 for(int i=0; i<4; i++) { 127 partsR[i] = (partsS[i] - partsE[i])*t + partsE[i]; 128 } 129 return new Color(partsR[0],partsR[1],partsR[2],partsR[3]); 130 } 131 132 /** 133 * Gets the current edge color. 134 * @return current edge color 135 */ 136 public Color getEdgeColor() { 137 return edgeColor; 138 } 139 140 /** 141 * Set the edge color 142 * @param edgeColor 143 */ 144 public void setEdgeColor(Color edgeColor) { 145 this.edgeColor = edgeColor; 146 } 147 148 /** 149 * 150 * @return color in the center of the effect 151 */ 152 public Color getCenterColor() { 153 return centerColor; 154 } 155 156 /** 157 * 158 * @param centerColor color in the center of the effect. 159 * @see #getCenterColor() 160 */ 161 public void setCenterColor(Color centerColor) { 162 this.centerColor = centerColor; 163 } 164 165 /** 166 * 167 * @return position of the border relative to the edge of painter covered area. 168 * @see BorderPosition 169 */ 170 public BorderPosition getBorderPosition() { 171 return borderPosition; 172 } 173 174 /** 175 * 176 * @param borderPosition position of the border relative to the edge of painter covered area. 177 * @see #getBorderPosition() 178 * @see BorderPosition 179 */ 180 public void setBorderPosition(BorderPosition borderPosition) { 181 this.borderPosition = borderPosition; 182 switch(borderPosition) { 183 case Centered : 184 setShapeMasked(false); 185 break; 186 case Inside : 187 setShapeMasked(true); 188 setRenderInsideShape(true); 189 break; 190 case Outside : 191 setShapeMasked(true); 192 setRenderInsideShape(false); 193 break; 194 } 195 if(borderPosition == BorderPosition.Centered) { 196 } 197 } 198}