001/* ======================================================
002 * Orson : a free chart beans library based on JFreeChart
003 * ======================================================
004 *
005 * (C) Copyright 2007, by Object Refinery Limited.
006 *
007 * Project Info:  http://www.jfree.org/orson/
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
029package org.jfree.beans;
030
031import java.awt.Font;
032import java.awt.Insets;
033import java.awt.Paint;
034import java.awt.event.MouseEvent;
035import java.beans.PropertyChangeEvent;
036import java.beans.PropertyEditorManager;
037import java.text.NumberFormat;
038
039import org.jfree.beans.editors.AxisScaleEditor;
040import org.jfree.beans.events.XYItemClickEvent;
041import org.jfree.beans.events.XYItemClickListener;
042import org.jfree.chart.axis.AxisLocation;
043import org.jfree.chart.axis.NumberAxis;
044import org.jfree.chart.axis.ValueAxis;
045import org.jfree.chart.entity.ChartEntity;
046import org.jfree.chart.entity.EntityCollection;
047import org.jfree.chart.entity.XYItemEntity;
048import org.jfree.chart.labels.StandardXYToolTipGenerator;
049import org.jfree.chart.plot.PlotOrientation;
050import org.jfree.chart.plot.XYPlot;
051import org.jfree.chart.renderer.xy.XYItemRenderer;
052
053/**
054 * A base class for beans that use the {@link XYPlot} class.
055 */
056public abstract class AbstractXYChart extends AbstractChart {
057    
058    static {
059        PropertyEditorManager.registerEditor(AxisScale.class, 
060                AxisScaleEditor.class);
061    }
062
063    /** The scale for the y-axis. */
064    private AxisScale yAxisScale;
065    
066    /**
067     * Creates a new instance.
068     */
069    public AbstractXYChart() {
070        super();
071        this.yAxisScale = AxisScale.FLOAT;
072    }
073    
074    /**
075     * Returns the orientation for the plot.
076     * 
077     * @return The orientation.
078     * 
079     * @see #setOrientation(PlotOrientation)
080     */
081    public PlotOrientation getOrientation() {
082        PlotOrientation result = null;
083        XYPlot plot = (XYPlot) this.chart.getPlot();
084        if (plot != null) {
085            result = plot.getOrientation();
086        }
087        return result;        
088    }
089    
090    /**
091     * Sets the orientation for the plot and fires a 
092     * {@link PropertyChangeEvent} for the <code>orientation</code> property.
093     * 
094     * @param orientation  the orientation (<code>null</code> not permitted).
095     * 
096     * @see #setOrientation(PlotOrientation)
097     */
098    public void setOrientation(PlotOrientation orientation) {
099        XYPlot plot = (XYPlot) this.chart.getPlot();
100        if (plot != null) {
101            PlotOrientation old = plot.getOrientation();
102            plot.setOrientation(orientation);
103            firePropertyChange("orientation", old, orientation);
104        }        
105    }
106    
107    /**
108     * Returns the x-axis label.
109     * 
110     * @return The x-axis label.
111     * 
112     * @see #setXAxisLabel(String)
113     */
114    public String getXAxisLabel() {
115        String result = null;
116        XYPlot plot = (XYPlot) this.chart.getPlot();
117        if (plot != null) {
118            result = plot.getDomainAxis().getLabel();
119        }
120        return result;
121    }
122    
123    /**
124     * Sets the x-axis label and fires a {@link PropertyChangeEvent} for the
125     * <code>xAxisLabel</code> property.
126     * 
127     * @param label  the new label.
128     * 
129     * @see #getXAxisLabel()
130     */
131    public void setXAxisLabel(String label) {
132        XYPlot plot = (XYPlot) this.chart.getPlot();
133        if (plot != null) {
134            ValueAxis axis = plot.getDomainAxis();
135            String old = axis.getLabel();
136            axis.setLabel(label);
137            firePropertyChange("xAxisLabel", old, label);
138        }                
139    }
140    
141    /**
142     * Returns the font for the x-axis label.
143     * 
144     * @return The font for the x-axis label.
145     * 
146     * @see #setXAxisLabelFont(Font)
147     */
148    public Font getXAxisLabelFont() {
149        Font result = null;
150        XYPlot plot = (XYPlot) this.chart.getPlot();
151        if (plot != null) {
152            result = plot.getDomainAxis().getLabelFont();
153        }
154        return result;   
155    }
156    
157    /**
158     * Sets the font for the x-axis label and fires a 
159     * {@link PropertyChangeEvent} for the <code>xAxisLabelFont</code> 
160     * property.
161     * 
162     * @param font  the font (<code>null</code> not permitted).
163     * 
164     * @see #getXAxisLabelFont()
165     */
166    public void setXAxisLabelFont(Font font) {
167        if (font == null) {
168            throw new IllegalArgumentException("Null 'font' argument.");
169        }
170        XYPlot plot = (XYPlot) this.chart.getPlot();
171        if (plot != null) {
172            ValueAxis axis = plot.getDomainAxis();
173            Font old = axis.getLabelFont();
174            axis.setLabelFont(font);
175            firePropertyChange("xAxisLabelFont", old, font);
176        }
177    }
178
179    /**
180     * Returns the paint for the x-axis label.
181     * 
182     * @return The paint for the x-axis label.
183     * 
184     * @see #setXAxisLabelPaint(Paint)
185     */
186    public Paint getXAxisLabelPaint() {
187        Paint result = null;
188        XYPlot plot = (XYPlot) this.chart.getPlot();
189        if (plot != null) {
190            result = plot.getDomainAxis().getLabelPaint();
191        }
192        return result;   
193    }
194    
195    /**
196     * Sets the paint for the x-axis label and fires a 
197     * {@link PropertyChangeEvent} for the <code>xAxisLabelPaint</code> 
198     * property.
199     * 
200     * @param paint  the paint (<code>null</code> not permitted).
201     * 
202     * @see #getXAxisLabelPaint()
203     */
204    public void setXAxisLabelPaint(Paint paint) {
205        if (paint == null) {
206            throw new IllegalArgumentException("Null 'paint' argument.");
207        }
208        XYPlot plot = (XYPlot) this.chart.getPlot();
209        if (plot != null) {
210            ValueAxis axis = plot.getDomainAxis();
211            Paint old = axis.getLabelPaint();
212            axis.setLabelPaint(paint);
213            firePropertyChange("xAxisLabelPaint", old, paint);
214        }
215    }
216
217    /**
218     * Returns <code>true</code> if the x-axis is inverted, and 
219     * <code>false</code> otherwise.
220     * 
221     * @return A boolean.
222     * 
223     * @see #setXAxisInverted(boolean)
224     */
225    public boolean isXAxisInverted() {
226        XYPlot plot = (XYPlot) this.chart.getPlot();
227        if (plot != null) {
228            return plot.getDomainAxis().isInverted();
229        }
230        return false;
231    }
232
233    /**
234     * Sets a flag that controls whether or not the x-axis is inverted and
235     * fires a {@link PropertyChangeEvent} for the <code>xAxisInverted</code>
236     * property.
237     * 
238     * @param inverted  the new flag value.
239     * 
240     * @see #isXAxisInverted()
241     */
242    public void setXAxisInverted(boolean inverted) {
243        XYPlot plot = (XYPlot) this.chart.getPlot();
244        if (plot != null) {
245            ValueAxis axis = plot.getDomainAxis();
246            boolean old = axis.isInverted();
247            axis.setInverted(inverted);
248            firePropertyChange("xAxisInverted", old, inverted);
249        }                
250    }
251    
252    /**
253     * Returns the lower margin for the x-axis.
254     * 
255     * @return The lower margin.
256     * 
257     * @see #setXAxisLowerMargin(double)
258     */
259    public double getXAxisLowerMargin() {
260        XYPlot plot = (XYPlot) this.chart.getPlot();
261        if (plot != null) {
262            return plot.getDomainAxis().getLowerMargin();
263        }
264        return -1.0;
265    }
266    
267    /**
268     * Sets the lower margin for the x-axis and fires a 
269     * {@link PropertyChangeEvent} for the <code>xAxisLowerMargin</code>
270     * property.
271     * 
272     * @param margin  the margin.
273     * 
274     * @see #getXAxisLowerMargin()
275     */
276    public void setXAxisLowerMargin(double margin) {
277        XYPlot plot = (XYPlot) this.chart.getPlot();
278        if (plot != null) {
279            ValueAxis axis = plot.getDomainAxis();
280            double old = axis.getLowerMargin();
281            axis.setLowerMargin(margin);
282            firePropertyChange("xAxisLowerMargin", old, margin);
283        }                
284    }
285    
286    /**
287     * Returns the upper margin for the x-axis.
288     * 
289     * @return The upper margin for the x-axis.
290     * 
291     * @see #setXAxisUpperMargin(double)
292     */
293    public double getXAxisUpperMargin() {
294        XYPlot plot = (XYPlot) this.chart.getPlot();
295        if (plot != null) {
296            return plot.getDomainAxis().getUpperMargin();
297        }
298        return -1.0;
299    }
300
301    /**
302     * Sets the upper margin for the x-axis and fires a 
303     * {@link PropertyChangeEvent} for the <code>xAxisUpperMargin</code> 
304     * property.
305     * 
306     * @param margin  the margin.
307     * 
308     * @see #getXAxisUpperMargin()
309     */
310    public void setXAxisUpperMargin(double margin) {
311        XYPlot plot = (XYPlot) this.chart.getPlot();
312        if (plot != null) {
313            ValueAxis axis = plot.getDomainAxis();
314            double old = axis.getUpperMargin();
315            axis.setUpperMargin(margin);
316            firePropertyChange("xAxisUpperMargin", old, margin);
317        }                
318    }
319    
320    /**
321     * Returns <code>true</code> if the x-axis gridlines are visible, and 
322     * <code>false</code> otherwise.
323     * 
324     * @return A boolean.
325     * 
326     * @see #setXAxisGridlinesVisible(boolean)
327     */
328    public boolean isXAxisGridlinesVisible() {
329        XYPlot plot = (XYPlot) this.chart.getPlot();
330        if (plot != null) {
331            return plot.isDomainGridlinesVisible();
332        }
333        return false;
334    }
335
336    /**
337     * Sets a flag that controls whether or not the x-axis gridlines are
338     * drawn and fires a {@link PropertyChangeEvent} for the 
339     * <code>xAxisGridlinesVisible</code> property.
340     * 
341     * @param visible  the new flag value.
342     * 
343     * @see #isXAxisGridlinesVisible()
344     */
345    public void setXAxisGridlinesVisible(boolean visible) {
346        XYPlot plot = (XYPlot) this.chart.getPlot();
347        if (plot != null) {
348            boolean old = plot.isDomainGridlinesVisible();
349            plot.setDomainGridlinesVisible(visible);
350            firePropertyChange("xAxisGridlinesVisible", old, visible);
351        }                
352    }
353    
354    /**
355     * Returns the font for the x-axis tick labels.
356     * 
357     * @return The font for the x-axis tick labels.
358     * 
359     * @see #setXAxisTickLabelFont(Font)
360     */
361    public Font getXAxisTickLabelFont() {
362        Font result = null;
363        XYPlot plot = (XYPlot) this.chart.getPlot();
364        if (plot != null) {
365            result = plot.getDomainAxis().getTickLabelFont();
366        }
367        return result;   
368    }
369    
370    /**
371     * Sets the font for the x-axis tick labels and fires a 
372     * {@link PropertyChangeEvent} for the <code>xAxisTickLabelFont</code>
373     * property.
374     * 
375     * @param font  the font (<code>null</code> not permitted).
376     * 
377     * @see #getXAxisTickLabelFont()
378     */
379    public void setXAxisTickLabelFont(Font font) {
380        if (font == null) {
381            throw new IllegalArgumentException("Null 'font' argument.");
382        }
383        XYPlot plot = (XYPlot) this.chart.getPlot();
384        if (plot != null) {
385            ValueAxis axis = plot.getDomainAxis();
386            Font old = axis.getTickLabelFont();
387            axis.setTickLabelFont(font);
388            firePropertyChange("xAxisTickLabelFont", old, font);
389        }
390    }
391
392    /**
393     * Returns the paint for the x-axis tick labels.
394     * 
395     * @return The paint for the x-axis tick labels.
396     * 
397     * @see #setXAxisTickLabelPaint(Paint)
398     */
399    public Paint getXAxisTickLabelPaint() {
400        Paint result = null;
401        XYPlot plot = (XYPlot) this.chart.getPlot();
402        if (plot != null) {
403            result = plot.getDomainAxis().getTickLabelPaint();
404        }
405        return result;   
406    }
407    
408    /**
409     * Sets the paint for the x-axis tick labels and fires a 
410     * {@link PropertyChangeEvent} for the <code>xAxisTickLabelPaint</code>
411     * property.
412     * 
413     * @param paint  the paint (<code>null</code> not permitted).
414     * 
415     * @see #getXAxisTickLabelPaint()
416     */
417    public void setXAxisTickLabelPaint(Paint paint) {
418        if (paint == null) {
419            throw new IllegalArgumentException("Null 'paint' argument.");
420        }
421        XYPlot plot = (XYPlot) this.chart.getPlot();
422        if (plot != null) {
423            ValueAxis axis = plot.getDomainAxis();
424            Paint old = axis.getTickLabelPaint();
425            axis.setTickLabelPaint(paint);
426            firePropertyChange("xAxisTickLabelPaint", old, paint);
427        }
428    }
429    
430    /**
431     * Returns the y-axis label.
432     * 
433     * @return The y-axis label.
434     * 
435     * @see #setYAxisLabel(String)
436     */
437    public String getYAxisLabel() {
438        String result = null;
439        XYPlot plot = (XYPlot) this.chart.getPlot();
440        if (plot != null) {
441            result = plot.getRangeAxis().getLabel();
442        }
443        return result;
444    }
445    
446    /**
447     * Sets the y-axis label and fires a {@link PropertyChangeEvent} for the
448     * <code>yAxisLabel</code> property.
449     * 
450     * @param label  the label.
451     * 
452     * @see #getYAxisLabel()
453     */
454    public void setYAxisLabel(String label) {
455        XYPlot plot = (XYPlot) this.chart.getPlot();
456        if (plot != null) {
457            ValueAxis axis = plot.getRangeAxis();
458            String old = axis.getLabel();
459            axis.setLabel(label);
460            firePropertyChange("yAxisLabel", old, label);
461        }                
462    }
463
464    /**
465     * Returns the font for the y-axis label.
466     * 
467     * @return The font for the y-axis label.
468     * 
469     * @see #setYAxisLabelFont(Font)
470     */
471    public Font getYAxisLabelFont() {
472        Font result = null;
473        XYPlot plot = (XYPlot) this.chart.getPlot();
474        if (plot != null) {
475            result = plot.getRangeAxis().getLabelFont();
476        }
477        return result;   
478    }
479    
480    /**
481     * Sets the font for the y-axis label and fires a 
482     * {@link PropertyChangeEvent} for the <code>yAxisLabelFont</code>
483     * property.
484     * 
485     * @param font  the font (<code>null</code> not permitted).
486     * 
487     * @see #getYAxisLabelFont()
488     */
489    public void setYAxisLabelFont(Font font) {
490        if (font == null) {
491            throw new IllegalArgumentException("Null 'font' argument.");
492        }
493        XYPlot plot = (XYPlot) this.chart.getPlot();
494        if (plot != null) {
495            ValueAxis axis = plot.getRangeAxis();
496            Font old = axis.getLabelFont();
497            axis.setLabelFont(font);
498            firePropertyChange("yAxisLabelFont", old, font);
499        }
500    }
501
502    /**
503     * Returns the paint for the y-axis label.
504     * 
505     * @return The paint for the y-axis label.
506     * 
507     * @see #setYAxisLabelPaint(Paint)
508     */
509    public Paint getYAxisLabelPaint() {
510        Paint result = null;
511        XYPlot plot = (XYPlot) this.chart.getPlot();
512        if (plot != null) {
513            result = plot.getRangeAxis().getLabelPaint();
514        }
515        return result;   
516    }
517    
518    /**
519     * Sets the paint for the y-axis label and fires a 
520     * {@link PropertyChangeEvent} for the <code>yAxisLabelPaint</code> 
521     * property.
522     * 
523     * @param paint  the paint (<code>null</code> not permitted).
524     * 
525     * @see #getYAxisLabelPaint()
526     */
527    public void setYAxisLabelPaint(Paint paint) {
528        if (paint == null) {
529            throw new IllegalArgumentException("Null 'paint' argument.");
530        }
531        XYPlot plot = (XYPlot) this.chart.getPlot();
532        if (plot != null) {
533            ValueAxis axis = plot.getRangeAxis();
534            Paint old = axis.getLabelPaint();
535            axis.setLabelPaint(paint);
536            firePropertyChange("yAxisLabelPaint", old, paint);
537        }
538    }
539    
540    /**
541     * Returns the scale type for the y-axis.
542     * 
543     * @return The scale type.
544     * 
545     * @see #setYAxisScale(AxisScale)
546     */
547    public AxisScale getYAxisScale() {
548        return this.yAxisScale;
549    }
550
551    /**
552     * Sets the scale type for the y-axis and fires a 
553     * {@link PropertyChangeEvent} for the <code>yAxisScale</code> property.
554     * 
555     * @param scale  the scale type.
556     * 
557     * @see #getYAxisScale()
558     */
559    public void setYAxisScale(AxisScale scale) {
560        XYPlot plot = (XYPlot) this.chart.getPlot();
561        if (plot != null) {
562            AxisScale old = this.yAxisScale;
563            ValueAxis axis = plot.getRangeAxis();
564            if (AxisScale.INTEGER.equals(scale)) {
565                axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
566            }
567            else if (AxisScale.FLOAT.equals(scale)) {
568                axis.setStandardTickUnits(NumberAxis.createStandardTickUnits());
569            }
570
571            firePropertyChange("yAxisScale", old, scale);
572        }
573    }
574    
575    /**
576     * Returns <code>true</code> if the y-axis is inverted, and 
577     * <code>false</code> otherwise.
578     * 
579     * @return A boolean.
580     * 
581     * @see #setYAxisInverted(boolean)
582     */
583    public boolean isYAxisInverted() {
584        XYPlot plot = (XYPlot) this.chart.getPlot();
585        if (plot != null) {
586            return plot.getRangeAxis().isInverted();
587        }
588        return false;
589    }
590
591    /**
592     * Sets a flag that controls whether or not the y-axis is inverted and
593     * fires a {@link PropertyChangeEvent} for the <code>yAxisInverted</code>
594     * property.
595     * 
596     * @param inverted  the new flag value.
597     * 
598     * @see #isYAxisInverted()
599     */
600    public void setYAxisInverted(boolean inverted) {
601        XYPlot plot = (XYPlot) this.chart.getPlot();
602        if (plot != null) {
603            ValueAxis axis = plot.getRangeAxis();
604            boolean old = axis.isInverted();
605            axis.setInverted(inverted);
606            firePropertyChange("yAxisInverted", old, inverted);
607        }                
608    }
609    
610    /**
611     * Returns the flag that controls whether or not the auto range calculation
612     * is forced to include zero.
613     * 
614     * @return A boolean.
615     * 
616     * @see #setYAxisAutoRangeIncludesZero(boolean)
617     */
618    public boolean getYAxisAutoRangeIncludesZero() {
619        XYPlot plot = (XYPlot) this.chart.getPlot();
620        if (plot == null) {
621            return false;
622        }
623        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
624        return yAxis.getAutoRangeIncludesZero();
625    }
626    
627    /**
628     * Sets the flag that controls whether or not the auto range calculation
629     * is forced to include zero, and fires a {@link PropertyChangeEvent} 
630     * for the <code>yAxisAutoRangeIncludesZero</code> property.
631     * 
632     * @param include  the new flag value.
633     * 
634     * @see #getYAxisAutoRangeIncludesZero()
635     */
636    public void setYAxisAutoRangeIncludesZero(boolean include) {
637        XYPlot plot = (XYPlot) this.chart.getPlot();
638        if (plot == null) {
639            return;
640        }
641        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
642        boolean old = yAxis.getAutoRangeIncludesZero();
643        yAxis.setAutoRangeIncludesZero(include);
644        firePropertyChange("yAxisAutoRangeIncludesZero", old, include);
645    }
646
647    /**
648     * Returns the lower margin for the y-axis.
649     * 
650     * @return The lower margin.
651     * 
652     * @see #setYAxisLowerMargin(double)
653     */
654    public double getYAxisLowerMargin() {
655        XYPlot plot = (XYPlot) this.chart.getPlot();
656        if (plot != null) {
657            return plot.getRangeAxis().getLowerMargin();
658        }
659        return -1.0;
660    }
661    
662    /**
663     * Sets the lower margin for the y-axis and fires a 
664     * {@link PropertyChangeEvent} for the <code>yAxisLowerMargin</code>
665     * property.
666     * 
667     * @param margin  the margin.
668     * 
669     * @see #getYAxisLowerMargin()
670     */
671    public void setYAxisLowerMargin(double margin) {
672        XYPlot plot = (XYPlot) this.chart.getPlot();
673        if (plot != null) {
674            ValueAxis axis = plot.getRangeAxis();
675            double old = axis.getLowerMargin();
676            axis.setLowerMargin(margin);
677            firePropertyChange("yAxisLowerMargin", old, margin);
678        }                
679    }
680    
681    /**
682     * Returns the upper margin for the y-axis.
683     * 
684     * @return The upper margin for the y-axis.
685     * 
686     * @see #setYAxisUpperMargin(double)
687     */
688    public double getYAxisUpperMargin() {
689        XYPlot plot = (XYPlot) this.chart.getPlot();
690        if (plot != null) {
691            return plot.getRangeAxis().getUpperMargin();
692        }
693        return -1.0;
694    }
695
696    /**
697     * Sets the upper margin for the y-axis and fires a 
698     * {@link PropertyChangeEvent} for the <code>yAxisUpperMargin</code> 
699     * property.
700     * 
701     * @param margin  the margin.
702     * 
703     * @see #getYAxisUpperMargin()
704     */
705    public void setYAxisUpperMargin(double margin) {
706        XYPlot plot = (XYPlot) this.chart.getPlot();
707        if (plot != null) {
708            ValueAxis axis = plot.getRangeAxis();
709            double old = axis.getUpperMargin();
710            axis.setUpperMargin(margin);
711            firePropertyChange("yAxisUpperMargin", old, margin);
712        }                
713    }
714    
715    /**
716     * Returns <code>true</code> if the y-axis gridlines are visible, and 
717     * <code>false</code> otherwise.
718     * 
719     * @return A boolean.
720     * 
721     * @see #setYAxisGridlinesVisible(boolean)
722     */
723    public boolean isYAxisGridlinesVisible() {
724        XYPlot plot = (XYPlot) this.chart.getPlot();
725        if (plot != null) {
726            return plot.isRangeGridlinesVisible();
727        }
728        return false;
729    }
730
731    /**
732     * Sets a flag that controls whether or not the y-axis gridlines are
733     * drawn and fires a {@link PropertyChangeEvent} for the
734     * <code>yAxisGridlinesVisible</code> property.
735     * 
736     * @param visible  the new flag value.
737     * 
738     * @see #isYAxisGridlinesVisible()
739     */
740    public void setYAxisGridlinesVisible(boolean visible) {
741        XYPlot plot = (XYPlot) this.chart.getPlot();
742        if (plot != null) {
743            boolean old = plot.isRangeGridlinesVisible();
744            plot.setRangeGridlinesVisible(visible);
745            firePropertyChange("yAxisGridlinesVisible", old, visible);
746        }                
747    }
748    
749    /**
750     * Returns the grid line paint for the gridlines perpendicular to the
751     * x-axis.
752     * 
753     * @return The paint.
754     * 
755     * @see #setXAxisGridlinePaint(Paint)
756     */
757    public Paint getXAxisGridlinePaint() {
758        XYPlot plot = (XYPlot) this.chart.getPlot();
759        if (plot != null) {
760            return plot.getDomainGridlinePaint();
761        }
762        return null;
763    }
764    
765    /**
766     * Sets the paint for the x-axis gridlines and fires a 
767     * {@link PropertyChangeEvent} for the <code>xAxisGridlinePaint</code>
768     * property.
769     * 
770     * @param paint  the paint.
771     * 
772     * @see #getXAxisGridlinePaint()
773     */
774    public void setXAxisGridlinePaint(Paint paint) {
775        XYPlot plot = (XYPlot) this.chart.getPlot();
776        if (plot != null) {
777            Paint old = plot.getDomainGridlinePaint();
778            plot.setDomainGridlinePaint(paint);
779            firePropertyChange("xAxisGridlinePaint", old, paint);
780        }
781    }
782    
783    /**
784     * Returns the y-axis gridline paint.
785     * 
786     * @return The y-axis gridline paint.
787     * 
788     * @see #setYAxisGridlinePaint(Paint)
789     */
790    public Paint getYAxisGridlinePaint() {
791        XYPlot plot = (XYPlot) this.chart.getPlot();
792        if (plot != null) {
793            return plot.getRangeGridlinePaint();
794        }
795        return null;
796    }
797    
798    /**
799     * Sets the y-axis gridline paint and fires a {@link PropertyChangeEvent}
800     * for the <code>yAxisGridlinePaint</code> property.
801     * 
802     * @param paint  the paint.
803     * 
804     * @see #getYAxisGridlinePaint()
805     */
806    public void setYAxisGridlinePaint(Paint paint) {
807        XYPlot plot = (XYPlot) this.chart.getPlot();
808        if (plot != null) {
809            Paint old = plot.getRangeGridlinePaint();
810            plot.setRangeGridlinePaint(paint);
811            firePropertyChange("yAxisGridlinePaint", old, paint);
812        }
813    }
814    
815    /**
816     * Returns the font for the y-axis tick labels.
817     * 
818     * @return The font for the y-axis tick labels.
819     * 
820     * @see #setYAxisTickLabelFont(Font)
821     */
822    public Font getYAxisTickLabelFont() {
823        Font result = null;
824        XYPlot plot = (XYPlot) this.chart.getPlot();
825        if (plot != null) {
826            result = plot.getRangeAxis().getTickLabelFont();
827        }
828        return result;   
829    }
830    
831    /**
832     * Sets the font for the y-axis tick labels and fires a 
833     * {@link PropertyChangeEvent} for the <code>yAxisTickLabelFont</code>
834     * property.
835     * 
836     * @param font  the font (<code>null</code> not permitted).
837     * 
838     * @see #getYAxisTickLabelFont()
839     */
840    public void setYAxisTickLabelFont(Font font) {
841        if (font == null) {
842            throw new IllegalArgumentException("Null 'font' argument.");
843        }
844        XYPlot plot = (XYPlot) this.chart.getPlot();
845        if (plot != null) {
846            ValueAxis axis = plot.getRangeAxis();
847            Font old = axis.getTickLabelFont();
848            axis.setTickLabelFont(font);
849            firePropertyChange("yAxisTickLabelFont", old, font);
850        }
851    }
852
853    /**
854     * Returns the paint for the y-axis tick labels.
855     * 
856     * @return The paint for the y-axis tick labels.
857     * 
858     * @see #setYAxisTickLabelPaint(Paint)
859     */
860    public Paint getYAxisTickLabelPaint() {
861        Paint result = null;
862        XYPlot plot = (XYPlot) this.chart.getPlot();
863        if (plot != null) {
864            result = plot.getRangeAxis().getTickLabelPaint();
865        }
866        return result;   
867    }
868    
869    /**
870     * Sets the paint for the y-axis tick labels and fires a 
871     * {@link PropertyChangeEvent} for the <code>yAxisTickLabelPaint</code>
872     * property.
873     * 
874     * @param paint  the paint (<code>null</code> not permitted).
875     * 
876     * @see #getYAxisTickLabelPaint()
877     */
878    public void setYAxisTickLabelPaint(Paint paint) {
879        if (paint == null) {
880            throw new IllegalArgumentException("Null 'paint' argument.");
881        }
882        XYPlot plot = (XYPlot) this.chart.getPlot();
883        if (plot != null) {
884            ValueAxis axis = plot.getRangeAxis();
885            Paint old = axis.getTickLabelPaint();
886            axis.setTickLabelPaint(paint);
887            firePropertyChange("yAxisTickLabelPaint", old, paint);
888        }
889    }
890    
891    /**
892     * Returns the permitted axis locations for the x-axis.
893     * 
894     * @return The axis location.
895     * 
896     * @see #setXAxisLocation(AxisLocation)
897     */
898    public AxisLocation getXAxisLocation() {
899        XYPlot plot = (XYPlot) this.chart.getPlot();
900        if (plot != null) {
901            return plot.getDomainAxisLocation();
902        }
903        return null;                
904    }
905    
906    /**
907     * Sets the axis location for the x-axis and fires a 
908     * {@link PropertyChangeEvent} for the <code>xAxisLocation</code> argument.
909     * 
910     * @param location  the location (<code>null</code> not permitted).
911     * 
912     * @see #getXAxisLocation()
913     */
914    public void setXAxisLocation(AxisLocation location) {
915        if (location == null) {
916            throw new IllegalArgumentException("Null 'location' argument.");
917        }
918        XYPlot plot = (XYPlot) this.chart.getPlot();
919        if (plot != null) {
920            AxisLocation old = plot.getDomainAxisLocation();
921            plot.setDomainAxisLocation(location);
922            firePropertyChange("xAxisLocation", old, location);
923        }
924    }
925    
926    /**
927     * Returns the permitted axis locations for the y-axis.
928     * 
929     * @return The axis location.
930     * 
931     * @see #setYAxisLocation(AxisLocation)
932     */
933    public AxisLocation getYAxisLocation() {
934        XYPlot plot = (XYPlot) this.chart.getPlot();
935        if (plot != null) {
936            return plot.getRangeAxisLocation();
937        }
938        return null;                
939    }
940    
941    /**
942     * Sets the axis location for the y-axis and fires a 
943     * {@link PropertyChangeEvent} for the <code>yAxisLocation</code>
944     * property.
945     * 
946     * @param location  the location (<code>null</code> not permitted).
947     * 
948     * @see #getYAxisLocation()
949     */
950    public void setYAxisLocation(AxisLocation location) {
951        if (location == null) {
952            throw new IllegalArgumentException("Null 'location' argument.");
953        }
954        XYPlot plot = (XYPlot) this.chart.getPlot();
955        if (plot != null) {
956            AxisLocation old = plot.getRangeAxisLocation();
957            plot.setRangeAxisLocation(location);
958            firePropertyChange("yAxisLocation", old, location);
959        }
960    }
961    
962    /**
963     * Returns the format string for the item tool tips.
964     * 
965     * @return The format string.
966     * 
967     * @see #setToolTipFormat(String)
968     */
969    public String getToolTipFormat() {
970        XYPlot p = (XYPlot) this.chart.getPlot();
971        if (p == null) {
972            return "";
973        }
974        XYItemRenderer r = p.getRenderer();
975        if (r == null) {
976            return "";
977        }
978        StandardXYToolTipGenerator g = (StandardXYToolTipGenerator) 
979                r.getBaseToolTipGenerator();
980        if (g == null) {
981            return "";
982        }
983        return g.getFormatString();
984    }
985    
986    /**
987     * Sets the format string for the section tool tips and fires a 
988     * {@link PropertyChangeEvent} for the <code>toolTipFormat</code> property.
989     * 
990     * @param format  the format string.
991     * 
992     * @see #getToolTipFormat()
993     */
994    public void setToolTipFormat(String format) {
995        XYPlot p = (XYPlot) this.chart.getPlot();
996        if (p == null) {
997            return;
998        }
999        XYItemRenderer r = p.getRenderer();
1000        if (r == null) {
1001            return;
1002        }
1003        if (format.equals("")) {
1004            r.setBaseToolTipGenerator(null);
1005        }
1006        else {
1007            r.setBaseToolTipGenerator(new StandardXYToolTipGenerator(format, 
1008                    NumberFormat.getInstance(), NumberFormat.getInstance()));   
1009        }
1010        // FIXME: what to use for the oldValue
1011        firePropertyChange("toolTipFormat", null, format);
1012    }
1013    
1014    /**
1015     * Returns a flag that controls whether or not an arrow-head is displayed
1016     * at the positive end of the x-axis.
1017     * 
1018     * @return A boolean.
1019     * 
1020     * @see #setXAxisPositiveArrowVisible(boolean)
1021     */
1022    public boolean isXAxisPositiveArrowVisible() {
1023        XYPlot plot = (XYPlot) this.chart.getPlot();
1024        if (plot != null) {
1025            return plot.getDomainAxis().isPositiveArrowVisible();
1026        }
1027        return false;                
1028    }
1029    
1030    /**
1031     * Sets the flag that controls whether or not an arrow-head is displayed
1032     * at the positive end of the y-axis and fires a {@link PropertyChangeEvent} 
1033     * for the <code>yAxisPositiveArrowVisible</code> property.
1034     * 
1035     * @param visible  the new flag value.
1036     * 
1037     * @see #isYAxisPositiveArrowVisible()
1038     */
1039    public void setXAxisPositiveArrowVisible(boolean visible) {
1040        XYPlot plot = (XYPlot) this.chart.getPlot();
1041        if (plot != null) {
1042            ValueAxis axis = plot.getDomainAxis();
1043            boolean old = axis.isPositiveArrowVisible();
1044            axis.setPositiveArrowVisible(visible);
1045            firePropertyChange("xAxisPositiveArrowVisible", old, visible);
1046        }                
1047    }
1048
1049    /**
1050     * Returns a flag that controls whether or not an arrow-head is displayed
1051     * at the negative end of the x-axis.
1052     * 
1053     * @return A boolean.
1054     * 
1055     * @see #setXAxisNegativeArrowVisible(boolean)
1056     */
1057    public boolean isXAxisNegativeArrowVisible() {
1058        XYPlot plot = (XYPlot) this.chart.getPlot();
1059        if (plot != null) {
1060            return plot.getDomainAxis().isNegativeArrowVisible();
1061        }
1062        return false;                
1063    }
1064    
1065    /**
1066     * Sets the flag that controls whether or not an arrow-head is displayed
1067     * at the negative end of the x-axis and fires a {@link PropertyChangeEvent} 
1068     * for the <code>xAxisNegativeArrowVisible</code> property.
1069     * 
1070     * @param visible  the new flag value.
1071     * 
1072     * @see #isXAxisNegativeArrowVisible()
1073     */
1074    public void setXAxisNegativeArrowVisible(boolean visible) {
1075        XYPlot plot = (XYPlot) this.chart.getPlot();
1076        if (plot != null) {
1077            ValueAxis axis = plot.getDomainAxis();
1078            boolean old = axis.isNegativeArrowVisible();
1079            axis.setNegativeArrowVisible(visible);
1080            firePropertyChange("xAxisNegativeArrowVisible", old, visible);
1081        }                
1082    }
1083
1084    /**
1085     * Returns a flag that controls whether or not an arrow-head is displayed
1086     * at the positive end of the y-axis.
1087     * 
1088     * @return A boolean.
1089     * 
1090     * @see #setYAxisPositiveArrowVisible(boolean)
1091     */
1092    public boolean isYAxisPositiveArrowVisible() {
1093        XYPlot plot = (XYPlot) this.chart.getPlot();
1094        if (plot != null) {
1095            return plot.getRangeAxis().isPositiveArrowVisible();
1096        }
1097        return false;                
1098    }
1099    
1100    /**
1101     * Sets the flag that controls whether or not an arrow-head is displayed
1102     * at the positive end of the y-axis and fires a {@link PropertyChangeEvent} 
1103     * for the <code>yAxisPositiveArrowVisible</code> property.
1104     * 
1105     * @param visible  the new flag value.
1106     * 
1107     * @see #isYAxisPositiveArrowVisible()
1108     */
1109    public void setYAxisPositiveArrowVisible(boolean visible) {
1110        XYPlot plot = (XYPlot) this.chart.getPlot();
1111        if (plot != null) {
1112            ValueAxis axis = plot.getRangeAxis();
1113            boolean old = axis.isPositiveArrowVisible();
1114            axis.setPositiveArrowVisible(visible);
1115            firePropertyChange("yAxisPositiveArrowVisible", old, visible);
1116        }                
1117    }
1118
1119    /**
1120     * Returns a flag that controls whether or not an arrow-head is displayed
1121     * at the negative end of the y-axis.
1122     * 
1123     * @return A boolean.
1124     * 
1125     * @see #setYAxisNegativeArrowVisible(boolean)
1126     */
1127    public boolean isYAxisNegativeArrowVisible() {
1128        XYPlot plot = (XYPlot) this.chart.getPlot();
1129        if (plot != null) {
1130            return plot.getRangeAxis().isNegativeArrowVisible();
1131        }
1132        return false;                
1133    }
1134    
1135    /**
1136     * Sets the flag that controls whether or not an arrow-head is displayed
1137     * at the negative end of the y-axis and fires a {@link PropertyChangeEvent} 
1138     * for the <code>yAxisNegativeArrowVisible</code> property.
1139     * 
1140     * @param visible  the new flag value.
1141     * 
1142     * @see #isYAxisNegativeArrowVisible()
1143     */
1144    public void setYAxisNegativeArrowVisible(boolean visible) {
1145        XYPlot plot = (XYPlot) this.chart.getPlot();
1146        if (plot != null) {
1147            ValueAxis axis = plot.getRangeAxis();
1148            boolean old = axis.isNegativeArrowVisible();
1149            axis.setNegativeArrowVisible(visible);
1150            firePropertyChange("yAxisNegativeArrowVisible", old, visible);
1151        }                
1152    }
1153
1154    /**
1155     * Registers a listener to receive notification of category item clicks.
1156     * 
1157     * @param listener  the listener (<code>null</code> not permitted).
1158     */
1159    public void addXYItemClickListener(XYItemClickListener listener) {
1160        if (listener == null) {
1161            throw new IllegalArgumentException("Null 'listener' argument.");
1162        }
1163        this.listeners.add(XYItemClickListener.class, listener);
1164    }
1165    
1166    /**
1167     * Unregisters a listener so that it no longer receives notification of 
1168     * category item clicks.
1169     * 
1170     * @param listener  the listener (<code>null</code> not permitted).
1171     */
1172    public void removeXYItemClickListener(XYItemClickListener listener) {
1173        if (listener == null) {
1174            throw new IllegalArgumentException("Null 'listener' argument.");
1175        }
1176        this.listeners.remove(XYItemClickListener.class, listener);        
1177    }
1178    
1179    /**
1180     * Fires a category item click event.
1181     * 
1182     * @param event  the event.
1183     */
1184    public void fireXYItemClickEvent(XYItemClickEvent event) {
1185        Object[] listeners = this.listeners.getListeners(
1186                XYItemClickListener.class);
1187        for (int i = listeners.length - 1; i >= 0; i -= 1) {
1188            ((XYItemClickListener) listeners[i]).onXYItemClick(event);
1189        }                
1190        
1191    }
1192    
1193    /**
1194     * If the user clicks on the chart, see if that translates into an event
1195     * that we report...
1196     * 
1197     * @param event  the event.
1198     */
1199    public void mouseClicked(MouseEvent event) {
1200        // if no-one is listening, just return...
1201        Object[] listeners = this.listeners.getListeners(
1202                XYItemClickListener.class);
1203        if (listeners.length == 0) {
1204            super.mouseClicked(event);
1205        }
1206
1207        Insets insets = getInsets();
1208        int x = event.getX() - insets.left;
1209        int y = event.getY() - insets.top;
1210
1211        ChartEntity entity = null;
1212        if (this.info != null) {
1213            EntityCollection entities = this.info.getEntityCollection();
1214            if (entities != null) {
1215                entity = entities.getEntity(x, y);
1216            }
1217        }
1218        if (entity instanceof XYItemEntity) {
1219            XYItemEntity xyie = (XYItemEntity) entity;
1220            XYItemClickEvent lce = new XYItemClickEvent(this, 
1221                    xyie.getDataset(), xyie.getSeriesIndex(), xyie.getItem());
1222            fireXYItemClickEvent(lce);
1223        }
1224        else {
1225            super.mouseClicked(event);
1226        }
1227        
1228    }
1229
1230}