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 }