001 /*
002 * $Id: ShapePainter.java 3288 2009-03-10 14:36:28Z kschaefe $
003 *
004 * Copyright 2004 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 package org.jdesktop.swingx.painter;
023
024 import org.jdesktop.swingx.painter.effects.AreaEffect;
025
026 import javax.swing.*;
027 import java.awt.*;
028 import java.awt.geom.Ellipse2D;
029
030
031 /**
032 * <p>A Painter that paints java.awt.Shapes. It uses a stroke and a fillPaint to do so. The
033 * shape is painted as is, at a specific location. If no Shape is specified, nothing
034 * will be painted. If no stroke is specified, the default for the Graphics2D
035 * will be used. If no fillPaint is specified, the component background color
036 * will be used. The shape can be positioned using the insets, horizontal, and
037 * vertical properties.</p>
038 *
039 * <p>Here is an example that draws a rectangle aligned on the center right:
040 * <pre><code>
041 * Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, 50, 50);
042 * ShapePainter p = new ShapePainter(rect);
043 * p.setHorizontal(HorizontalAlignment.RIGHT);
044 * p.setVertical(VerticalAlignment.CENTER);
045 * </code></pre>
046 * @author rbair
047 */
048 public class ShapePainter extends AbstractAreaPainter<Object> {
049 /**
050 * The Shape to fillPaint. If null, nothing is painted.
051 */
052 private Shape shape;
053
054 /**
055 * Create a new ShapePainter
056 */
057 public ShapePainter() {
058 super();
059 this.shape = new Ellipse2D.Double(0,0,100,100);
060 this.setBorderWidth(3);
061 this.setFillPaint(Color.RED);
062 this.setBorderPaint(Color.BLACK);
063 }
064
065 /**
066 * Create a new ShapePainter with the specified shape.
067 *
068 *
069 * @param shape the shape to fillPaint
070 */
071 public ShapePainter(Shape shape) {
072 super();
073 this.shape = shape;
074 }
075
076 /**
077 * Create a new ShapePainter with the specified shape and fillPaint.
078 *
079 *
080 * @param shape the shape to fillPaint
081 * @param paint the fillPaint to be used to fillPaint the shape
082 */
083 public ShapePainter(Shape shape, Paint paint) {
084 super();
085 this.shape = shape;
086 this.setFillPaint(paint);
087 }
088
089 /**
090 * Create a new ShapePainter with the specified shape and fillPaint. The shape
091 * can be filled or stroked (only the ouline is painted).
092 *
093 *
094 * @param shape the shape to fillPaint
095 * @param paint the fillPaint to be used to fillPaint the shape
096 * @param style specifies the ShapePainter.Style to use for painting this shape.
097 * If null, then Style.BOTH is used
098 */
099 public ShapePainter(Shape shape, Paint paint, Style style) {
100 super();
101 this.shape = shape;
102 this.setFillPaint(paint);
103 this.setStyle(style == null ? Style.BOTH : style);
104 }
105
106 /**
107 * Sets the shape to fillPaint. This shape is not resized when the component
108 * bounds are. To do that, create a custom shape that is bound to the
109 * component width/height
110 *
111 *
112 * @param s the Shape to fillPaint. May be null
113 */
114 public void setShape(Shape s) {
115 Shape old = getShape();
116 this.shape = s;
117 setDirty(true);
118 firePropertyChange("shape", old, getShape());
119 }
120
121 /**
122 * Gets the current shape
123 * @return the Shape to fillPaint. May be null
124 */
125 public Shape getShape() {
126 return shape;
127 }
128
129 /**
130 * {@inheritDoc}
131 */
132 protected void doPaint(Graphics2D g, Object component, int w, int h) {
133 //set the stroke if it is not null
134 Stroke s = new BasicStroke(this.getBorderWidth());
135 g.setStroke(s);
136
137 if(getShape() != null) {
138 Shape shape = provideShape(g,component, w, h);
139 Rectangle bounds = shape.getBounds();
140 Rectangle rect = calculateLayout(bounds.width, bounds.height, w, h);
141 //u.p("rect = " + rect);
142 g = (Graphics2D)g.create();
143
144 try {
145 g.translate(rect.x, rect.y);
146 //draw/fill the shape
147 drawPathEffects(g, shape, rect.width, rect.height);
148 switch (getStyle()) {
149 case BOTH:
150 drawShape(g, shape, component, rect.width, rect.height);
151 fillShape(g, shape, component, rect.width, rect.height);
152 break;
153 case FILLED:
154 fillShape(g, shape, component, rect.width, rect.height);
155 break;
156 case OUTLINE:
157 drawShape(g, shape, component, rect.width, rect.height);
158 break;
159 }
160 } finally {
161 g.dispose();
162 }
163 }
164 }
165
166 private void drawShape(Graphics2D g, Shape shape, Object component, int w, int h) {
167 g.setPaint(calculateStrokePaint(component, w, h));
168 g.draw(shape);
169 }
170
171 private void fillShape(Graphics2D g, Shape shape, Object component, int w, int h) {
172 g.setPaint(calculateFillPaint(component, w, h));
173 g.fill(shape);
174 }
175
176 // shape effect stuff
177 protected Shape provideShape(Graphics2D g, Object comp, int width, int height) {
178 return getShape();
179 }
180
181 private Paint calculateStrokePaint(Object component, int width, int height) {
182 Paint p = getBorderPaint();
183 if (p == null) {
184 if(component instanceof JComponent) {
185 p = ((JComponent)component).getForeground();
186 }
187 }
188 if(isPaintStretched()) {
189 p = calculateSnappedPaint(p, width, height);
190 }
191 return p;
192 }
193
194 private Paint calculateFillPaint(Object component, int width, int height) {
195 //set the fillPaint
196 Paint p = getFillPaint();
197 if(isPaintStretched()) {
198 p = calculateSnappedPaint(p, width, height);
199 } else {
200 }
201 if (p == null) {
202 if(component instanceof JComponent) {
203 p = ((JComponent)component).getBackground();
204 }
205 }
206 return p;
207 }
208
209 private void drawPathEffects(Graphics2D g, Shape shape, int w, int h) {
210 if(getAreaEffects() != null) {
211 //Paint pt = calculateFillPaint(component, w, h);
212 for(AreaEffect ef : getAreaEffects()) {
213 ef.apply(g, shape, w, h);
214 }
215 }
216 }
217 }