001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it 
010     * under the terms of the GNU Lesser General Public License as published by 
011     * the Free Software Foundation; either version 2.1 of the License, or 
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but 
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022     * USA.  
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     *
027     * -------------
028     * ClipPath.java
029     * -------------
030     * (C) Copyright 2003, 2004, by David M. O'Donnell and Contributors.
031     *
032     * Original Author:  David M. O'Donnell;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *                   Nicolas Brodu;
035     *
036     * $Id: ClipPath.java,v 1.2.2.1 2005/10/25 16:50:20 mungady Exp $
037     *
038     * Changes
039     * -------
040     * 22-Apr-2003 : Added standard header (DG);
041     * 09-May-2003 : Added AxisLocation (DG);
042     * 11-Sep-2003 : Implemented Cloneable (NB);
043     * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
044     *
045     */
046    
047    package org.jfree.chart;
048    
049    import java.awt.BasicStroke;
050    import java.awt.Composite;
051    import java.awt.Graphics2D;
052    import java.awt.Paint;
053    import java.awt.Stroke;
054    import java.awt.geom.GeneralPath;
055    import java.awt.geom.Rectangle2D;
056    
057    import org.jfree.chart.axis.ValueAxis;
058    import org.jfree.ui.RectangleEdge;
059    
060    /**
061     * This class would typically be used with a 
062     * {@link org.jfree.chart.plot.ContourPlot}.  It allows the user to define a 
063     * <code>GeneralPath</code> curve in plot coordinates.  This curve can then be 
064     * used mask off or define regions within the contour plot.  The data must be 
065     * sorted.
066     * 
067     * @author dmo
068     */
069    public class ClipPath implements Cloneable {
070    
071        /** The x values. */
072        private double[] xValue = null;
073        
074        /** The y values. */
075        private double[] yValue = null;
076    
077        /** Controls whether drawing will be clipped (
078         * false would still allow the drawing or filling of path */
079        private boolean clip = true;
080    
081        /** Controls whether the path is drawn as an outline. */
082        private boolean drawPath = false;
083    
084        /** Controls whether the path is filled. */
085        private boolean fillPath = false;
086    
087        /** The fill paint. */
088        private Paint fillPaint = null;
089        
090        /** The draw paint. */
091        private Paint drawPaint = null;
092        
093        /** The draw stroke. */
094        private Stroke drawStroke = null;
095        
096        /** The composite. */
097        private Composite composite = null;
098    
099        /**
100         * Constructor for ClipPath.
101         */
102        public ClipPath() {
103            super();
104        }
105    
106        /**
107         * Constructor for ClipPath.
108         * Default values are assumed for the fillPath and drawPath options as 
109         * false and true respectively.  The fillPaint is set to Color.GRAY, the 
110         * drawColor is Color.BLUE, the stroke is BasicStroke(1)
111         * and the composite is AlphaComposite.Src.
112         *
113         * @param xValue  x coordinates of curved to be created
114         * @param yValue  y coordinates of curved to be created
115         */
116        public ClipPath(double[] xValue, double[] yValue) {
117            this(xValue, yValue, true, false, true);
118        }
119    
120    
121        /**
122         * Constructor for ClipPath.
123         * The fillPaint is set to Color.GRAY, the drawColor is Color.BLUE, the 
124         * stroke is BasicStroke(1) and the composite is AlphaComposite.Src.
125         *
126         * @param xValue  x coordinates of curved to be created
127         * @param yValue  y coordinates of curved to be created
128         * @param clip  clip?
129         * @param fillPath  whether the path is to filled
130         * @param drawPath  whether the path is to drawn as an outline
131         */
132        public ClipPath(double[] xValue, double[] yValue,
133                        boolean clip, boolean fillPath, boolean drawPath) {
134            this.xValue = xValue;
135            this.yValue = yValue;
136    
137            this.clip = clip;
138            this.fillPath = fillPath;
139            this.drawPath = drawPath;
140    
141            this.fillPaint = java.awt.Color.gray;
142            this.drawPaint = java.awt.Color.blue;
143            this.drawStroke = new BasicStroke(1);
144            this.composite = java.awt.AlphaComposite.Src;
145        }
146    
147        /**
148         * Constructor for ClipPath.
149         *
150         * @param xValue  x coordinates of curved to be created
151         * @param yValue  y coordinates of curved to be created
152         * @param fillPath  whether the path is to filled
153         * @param drawPath  whether the path is to drawn as an outline
154         * @param fillPaint  the fill paint
155         * @param drawPaint  the outline stroke color
156         * @param drawStroke  the stroke style
157         * @param composite  the composite rule
158         */
159        public ClipPath(double[] xValue, double[] yValue, boolean fillPath, 
160                        boolean drawPath, Paint fillPaint, Paint drawPaint, 
161                        Stroke drawStroke, Composite composite) {
162    
163            this.xValue = xValue;
164            this.yValue = yValue;
165    
166            this.fillPath = fillPath;
167            this.drawPath = drawPath;
168    
169            this.fillPaint = fillPaint;
170            this.drawPaint = drawPaint;
171            this.drawStroke = drawStroke;
172            this.composite = composite;
173    
174        }
175    
176        /**
177         * Draws the clip path.
178         *
179         * @param g2  current graphics2D.
180         * @param dataArea  the dataArea that the plot is being draw in.
181         * @param horizontalAxis  the horizontal axis.
182         * @param verticalAxis  the vertical axis.
183         *
184         * @return The GeneralPath defining the outline
185         */
186        public GeneralPath draw(Graphics2D g2,
187                                Rectangle2D dataArea,
188                                ValueAxis horizontalAxis, ValueAxis verticalAxis) {
189    
190            GeneralPath generalPath = generateClipPath(
191                dataArea, horizontalAxis, verticalAxis
192            );
193            if (this.fillPath || this.drawPath) {
194                Composite saveComposite = g2.getComposite();
195                Paint savePaint = g2.getPaint();
196                Stroke saveStroke = g2.getStroke();
197    
198                if (this.fillPaint != null) {
199                    g2.setPaint(this.fillPaint);
200                }
201                if (this.composite != null) {
202                    g2.setComposite(this.composite);
203                }
204                if (this.fillPath) {
205                    g2.fill(generalPath);
206                }
207    
208                if (this.drawStroke != null) {
209                    g2.setStroke(this.drawStroke);
210                }
211                if (this.drawPath) {
212                    g2.draw(generalPath);
213                }
214                g2.setPaint(savePaint);
215                g2.setComposite(saveComposite);
216                g2.setStroke(saveStroke);
217            }
218            return generalPath;
219    
220        }
221    
222        /**
223         * Generates the clip path.
224         *
225         * @param dataArea  the dataArea that the plot is being draw in.
226         * @param horizontalAxis  the horizontal axis.
227         * @param verticalAxis  the vertical axis.
228         *
229         * @return The GeneralPath defining the outline
230         */
231        public GeneralPath generateClipPath(Rectangle2D dataArea,
232                                            ValueAxis horizontalAxis, 
233                                            ValueAxis verticalAxis) {
234    
235            GeneralPath generalPath = new GeneralPath();
236            double transX = horizontalAxis.valueToJava2D(
237                this.xValue[0], dataArea, RectangleEdge.BOTTOM
238            );
239            double transY = verticalAxis.valueToJava2D(
240                this.yValue[0], dataArea, RectangleEdge.LEFT
241            );
242            generalPath.moveTo((float) transX, (float) transY);
243            for (int k = 0; k < this.yValue.length; k++) {
244                transX = horizontalAxis.valueToJava2D(
245                    this.xValue[k], dataArea, RectangleEdge.BOTTOM
246                );
247                transY = verticalAxis.valueToJava2D(
248                    this.yValue[k], dataArea, RectangleEdge.LEFT
249                );
250                generalPath.lineTo((float) transX, (float) transY);
251            }
252            generalPath.closePath();
253    
254            return generalPath;
255    
256        }
257    
258        /**
259         * Returns the composite.
260         * 
261         * @return Composite
262         */
263        public Composite getComposite() {
264            return this.composite;
265        }
266    
267        /**
268         * Returns the drawPaint.
269         * 
270         * @return Paint
271         */
272        public Paint getDrawPaint() {
273            return this.drawPaint;
274        }
275    
276        /**
277         * Returns the drawPath.
278         * 
279         * @return boolean
280         */
281        public boolean isDrawPath() {
282            return this.drawPath;
283        }
284    
285        /**
286         * Returns the drawStroke.
287         * 
288         * @return Stroke
289         */
290        public Stroke getDrawStroke() {
291            return this.drawStroke;
292        }
293    
294        /**
295         * Returns the fillPaint.
296         * 
297         * @return Paint
298         */
299        public Paint getFillPaint() {
300            return this.fillPaint;
301        }
302    
303        /**
304         * Returns the fillPath.
305         * 
306         * @return boolean
307         */
308        public boolean isFillPath() {
309            return this.fillPath;
310        }
311    
312        /**
313         * Returns the xValue.
314         * 
315         * @return double[]
316         */
317        public double[] getXValue() {
318            return this.xValue;
319        }
320    
321        /**
322         * Returns the yValue.
323         * 
324         * @return double[]
325         */
326        public double[] getYValue() {
327            return this.yValue;
328        }
329    
330        /**
331         * Sets the composite.
332         * 
333         * @param composite The composite to set
334         */
335        public void setComposite(Composite composite) {
336            this.composite = composite;
337        }
338    
339        /**
340         * Sets the drawPaint.
341         * 
342         * @param drawPaint The drawPaint to set
343         */
344        public void setDrawPaint(Paint drawPaint) {
345            this.drawPaint = drawPaint;
346        }
347    
348        /**
349         * Sets the drawPath.
350         * 
351         * @param drawPath The drawPath to set
352         */
353        public void setDrawPath(boolean drawPath) {
354            this.drawPath = drawPath;
355        }
356    
357        /**
358         * Sets the drawStroke.
359         * 
360         * @param drawStroke The drawStroke to set
361         */
362        public void setDrawStroke(Stroke drawStroke) {
363            this.drawStroke = drawStroke;
364        }
365    
366        /**
367         * Sets the fillPaint.
368         * 
369         * @param fillPaint The fillPaint to set
370         */
371        public void setFillPaint(Paint fillPaint) {
372            this.fillPaint = fillPaint;
373        }
374    
375        /**
376         * Sets the fillPath.
377         * 
378         * @param fillPath The fillPath to set
379         */
380        public void setFillPath(boolean fillPath) {
381            this.fillPath = fillPath;
382        }
383    
384        /**
385         * Sets the xValue.
386         * 
387         * @param xValue The xValue to set
388         */
389        public void setXValue(double[] xValue) {
390            this.xValue = xValue;
391        }
392    
393        /**
394         * Sets the yValue.
395         * 
396         * @param yValue The yValue to set
397         */
398        public void setYValue(double[] yValue) {
399            this.yValue = yValue;
400        }
401    
402        /**
403         * Returns the clip.
404         * 
405         * @return boolean
406         */
407        public boolean isClip() {
408            return this.clip;
409        }
410    
411        /**
412         * Sets the clip.
413         * 
414         * @param clip The clip to set
415         */
416        public void setClip(boolean clip) {
417            this.clip = clip;
418        }
419    
420        /** 
421         * Returns a clone of the object (a deeper clone than default to avoid bugs 
422         * when setting values in cloned object).
423         * 
424         * @return The clone.
425         * 
426         * @throws CloneNotSupportedException if cloning is not supported.
427         */
428        public Object clone() throws CloneNotSupportedException {
429            ClipPath clone = (ClipPath) super.clone();
430            clone.xValue = (double[]) this.xValue.clone();
431            clone.yValue = (double[]) this.yValue.clone();
432            return clone;
433        }
434    
435    }