001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.forms.gui.effects;
031:
032: import java.awt.Color;
033: import java.awt.Component;
034: import java.awt.Graphics;
035: import java.awt.Graphics2D;
036: import java.awt.Paint;
037: import java.awt.Rectangle;
038:
039: import javax.swing.LookAndFeel;
040: import javax.swing.UIManager;
041:
042: import org.apache.batik.ext.awt.LinearGradientPaint;
043:
044: import com.jeta.forms.store.properties.effects.GradientProperty;
045:
046: /**
047: * This class is an implementation of a Painter that renders a a linear gradient
048: * on a part of a canvas or component. This class uses the Batik library for
049: * rendering the gradient. See <a
050: * href="http://xml.apache.org/batik/">http://xml.apache.org/batik/</a>
051: *
052: * @author Jeff Tassin
053: */
054: public class LinearGradientPainter implements Painter {
055: /**
056: * The property that defines the gradient settings.
057: */
058: private GradientProperty m_gradient_prop;
059:
060: /**
061: * A paint object derived from the gradient property. It is cached so we
062: * don't have to re-instantiate with every paint.
063: */
064: private Paint m_cached_paint;
065:
066: /**
067: * A rectangle used as a basis for the gradient paint. This value is checked
068: * everytime the paint method is called. If the paint area has changed, we
069: * regenerate the Paint object.
070: */
071: private Rectangle m_last_rect = new Rectangle();
072:
073: /**
074: * We keep track of the look and feel. If it changes, we need to regenerate
075: * the paint
076: */
077: private LookAndFeel m_look_and_feel;
078:
079: /**
080: * Creates a <code>LinearGradientProperty</code> instance with no paint
081: * attributes.
082: */
083: public LinearGradientPainter() {
084:
085: }
086:
087: /**
088: * Creates a <code>LinearGradientProperty</code> instance with the
089: * specified paint properties.
090: */
091: public LinearGradientPainter(GradientProperty prop) {
092: m_gradient_prop = prop;
093: }
094:
095: /**
096: * Creates a paint object based on the given rectangle and gradient
097: * property.
098: *
099: * @param rect
100: * the rectangle that defines the area for the gradient.
101: * @param gp
102: * the gradient properties used to define the paint.
103: * @return a paint object used for rendering the gradient on a graphics
104: * context.
105: */
106: private Paint createPaint(Rectangle rect, GradientProperty gp) {
107: Color startcolor = gp.getStartColor().getColor();
108: Color endcolor = gp.getEndColor().getColor();
109: int x1 = rect.x;
110: int y1 = rect.y;
111: int x2 = rect.x;
112: int y2 = rect.y + (int) (rect.height * gp.getMagnitude());
113:
114: if (startcolor == null)
115: startcolor = Color.white;
116: if (endcolor == null)
117: endcolor = Color.white;
118:
119: if (gp.getDirection() == GradientProperty.TOP_BOTTOM) {
120: x1 = rect.x;
121: y1 = rect.y;
122: x2 = rect.x;
123: y2 = rect.y + (int) (rect.height * gp.getMagnitude());
124: } else if (gp.getDirection() == GradientProperty.BOTTOM_TOP) {
125: x1 = rect.x;
126: y2 = rect.y;
127: x2 = rect.x;
128: y1 = rect.y + (int) (rect.height * gp.getMagnitude());
129: } else if (gp.getDirection() == GradientProperty.LEFT_RIGHT) {
130: x1 = rect.x;
131: y1 = rect.y;
132: x2 = rect.x + (int) (rect.width * gp.getMagnitude());
133: y2 = rect.y;
134: } else if (gp.getDirection() == GradientProperty.RIGHT_LEFT) {
135: x2 = rect.x;
136: y1 = rect.y;
137: x1 = rect.x + (int) (rect.width * gp.getMagnitude());
138: y2 = rect.y;
139: } else if (gp.getDirection() == GradientProperty.UP_LEFT) {
140: x1 = rect.x;
141: y1 = rect.y + (int) (rect.height * gp.getMagnitude());
142: x2 = rect.x + (int) (rect.width * gp.getMagnitude());
143: y2 = rect.y;
144: } else // assume down diagonal
145: {
146: x1 = rect.x;
147: y1 = rect.y;
148: x2 = rect.x + (int) (rect.width * gp.getMagnitude());
149: y2 = rect.y + (int) (rect.height * gp.getMagnitude());
150: }
151:
152: float[] fractions = new float[] { 0.0f, 1.0f };
153: Color[] colors = new Color[] { startcolor, endcolor };
154: LinearGradientPaint paint = new LinearGradientPaint((float) x1,
155: (float) y1, (float) x2, (float) y2, fractions, colors);
156: return paint;
157: }
158:
159: /**
160: * Painter Implementation. Paints a linear gradient on a given graphics
161: * context.
162: *
163: * @param g
164: * the graphics context
165: * @param rect
166: * the rectangle that defines the region to paint. Note, that
167: * this is different than the clipping rectangle.
168: */
169: public void paint(Component c, Graphics g, Rectangle rect) {
170: if (rect == null || m_gradient_prop == null)
171: return;
172:
173: Graphics2D g2 = (Graphics2D) g;
174: Paint old_paint = g2.getPaint();
175:
176: LookAndFeel lf = UIManager.getLookAndFeel();
177: if (m_look_and_feel != lf) {
178: m_cached_paint = null;
179: m_look_and_feel = lf;
180: }
181:
182: if (m_cached_paint == null || !rect.equals(m_last_rect)) {
183: m_last_rect.setBounds(rect.x, rect.y, rect.width,
184: rect.height);
185: m_cached_paint = createPaint(rect, m_gradient_prop);
186: }
187:
188: g2.setPaint(m_cached_paint);
189:
190: Rectangle clip_rect = g.getClipBounds();
191: if (rect.intersects(clip_rect)) {
192: Rectangle irect = rect.intersection(clip_rect);
193: g.fillRect(irect.x, irect.y, irect.width, irect.height);
194: g2.setPaint(old_paint);
195: }
196: }
197:
198: /**
199: * Sets the gradient attributes for this painter
200: *
201: * @param prop
202: * the gradient property to associate with this painter.
203: */
204: public void setGradientProperty(GradientProperty prop) {
205: m_cached_paint = null;
206: m_gradient_prop = prop;
207: }
208: }
|