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 }