KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > StandardLegend


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * -------------------
23  * StandardLegend.java
24  * -------------------
25  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
26  *
27  * Original Author: David Gilbert (for Object Refinery Limited);
28  * Contributor(s): Andrzej Porebski;
29  * Luke Quinane;
30  *
31  * $Id: StandardLegend.java,v 1.16 2003/11/03 14:25:00 mungady Exp $
32  *
33  * Changes (from 20-Jun-2001)
34  * --------------------------
35  * 20-Jun-2001 : Modifications submitted by Andrzej Porebski for legend placement;
36  * 18-Sep-2001 : Updated header and fixed DOS encoding problem (DG);
37  * 16-Oct-2001 : Moved data source classes to com.jrefinery.data.* (DG);
38  * 19-Oct-2001 : Moved some methods [getSeriesPaint(...) etc.] from JFreeChart to Plot (DG);
39  * 22-Jan-2002 : Fixed bug correlating legend labels with pie data (DG);
40  * 06-Feb-2002 : Bug fix for legends in small areas (DG);
41  * 23-Apr-2002 : Legend item labels are now obtained from the plot, not the chart (DG);
42  * 20-Jun-2002 : Added outline paint and stroke attributes for the key boxes (DG);
43  * 18-Sep-2002 : Fixed errors reported by Checkstyle (DG);
44  * 23-Sep-2002 : Changed the name of LegendItem --> DrawableLegendItem (DG);
45  * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
46  * 16-Oct-2002 : Adjusted vertical text position in legend item (DG);
47  * 17-Oct-2002 : Fixed bug where legend items are not using the font that has been set (DG);
48  * 11-Feb-2003 : Added title code by Donald Mitchell, removed unnecessary constructor (DG);
49  * 26-Mar-2003 : Implemented Serializable (DG);
50  * 22-Sep-2003 : Added nullpointer checks (TM);
51  * 23-Sep-2003 : Fixed bug in equals(...) method (DG);
52  * 08-Oct-2003 : Applied patch for displaying series line style, contributed by Luke Quinane (DG);
53  *
54  */

55
56 package org.jfree.chart;
57
58 import java.awt.BasicStroke JavaDoc;
59 import java.awt.Color JavaDoc;
60 import java.awt.Font JavaDoc;
61 import java.awt.FontMetrics JavaDoc;
62 import java.awt.Graphics2D JavaDoc;
63 import java.awt.Paint JavaDoc;
64 import java.awt.Shape JavaDoc;
65 import java.awt.Stroke JavaDoc;
66 import java.awt.font.LineMetrics JavaDoc;
67 import java.awt.geom.AffineTransform JavaDoc;
68 import java.awt.geom.Line2D JavaDoc;
69 import java.awt.geom.Point2D JavaDoc;
70 import java.awt.geom.Rectangle2D JavaDoc;
71 import java.io.IOException JavaDoc;
72 import java.io.ObjectInputStream JavaDoc;
73 import java.io.ObjectOutputStream JavaDoc;
74 import java.io.Serializable JavaDoc;
75
76 import org.jfree.chart.entity.EntityCollection;
77 import org.jfree.chart.entity.LegendItemEntity;
78 import org.jfree.chart.event.LegendChangeEvent;
79 import org.jfree.io.SerialUtilities;
80 import org.jfree.ui.RefineryUtilities;
81 import org.jfree.ui.TextAnchor;
82 import org.jfree.util.ObjectUtils;
83
84 /**
85  * A chart legend shows the names and visual representations of the series
86  * that are plotted in a chart.
87  *
88  * @author David Gilbert
89  */

90 public class StandardLegend extends Legend implements Serializable JavaDoc {
91
92     /** The default outer gap. */
93     public static final Spacer DEFAULT_OUTER_GAP = new Spacer(Spacer.ABSOLUTE, 3, 3, 3, 3);
94
95     /** The default inner gap. */
96     public static final Spacer DEFAULT_INNER_GAP = new Spacer(Spacer.ABSOLUTE, 2, 2, 2, 2);
97
98     /** The default outline stroke. */
99     public static final Stroke JavaDoc DEFAULT_OUTLINE_STROKE = new BasicStroke JavaDoc();
100
101     /** The default outline paint. */
102     public static final Paint JavaDoc DEFAULT_OUTLINE_PAINT = Color.gray;
103
104     /** The default background paint. */
105     public static final Paint JavaDoc DEFAULT_BACKGROUND_PAINT = Color.white;
106
107     /** The default title font. */
108     public static final Font JavaDoc DEFAULT_TITLE_FONT = new Font JavaDoc("SansSerif", Font.BOLD, 11);
109
110     /** The default item font. */
111     public static final Font JavaDoc DEFAULT_ITEM_FONT = new Font JavaDoc("SansSerif", Font.PLAIN, 10);
112
113     /** The amount of blank space around the legend. */
114     private Spacer outerGap;
115
116     /** The pen/brush used to draw the outline of the legend. */
117     private transient Stroke JavaDoc outlineStroke;
118
119     /** The color used to draw the outline of the legend. */
120     private transient Paint JavaDoc outlinePaint;
121
122     /** The color used to draw the background of the legend. */
123     private transient Paint JavaDoc backgroundPaint;
124
125     /** The blank space inside the legend box. */
126     private Spacer innerGap;
127
128     /** An optional title for the legend. */
129     private String JavaDoc title;
130
131     /** The font used to display the legend title. */
132     private Font JavaDoc titleFont;
133
134     /** The font used to display the legend item names. */
135     private Font JavaDoc itemFont;
136
137     /** The color used to display the legend item names. */
138     private transient Paint JavaDoc itemPaint;
139
140     /** A flag controlling whether or not outlines are drawn around shapes.*/
141     private boolean outlineShapes;
142
143     /** The stroke used to outline item shapes. */
144     private transient Stroke JavaDoc shapeOutlineStroke = new BasicStroke JavaDoc(0.5f);
145
146     /** The paint used to outline item shapes. */
147     private transient Paint JavaDoc shapeOutlinePaint = Color.lightGray;
148
149     /** A flag that controls whether the legend displays the series shapes. */
150     private boolean displaySeriesShapes;
151
152     /** A flag that controls whether the legend displays the series line */
153     private boolean displaySeriesLines;
154
155     /**
156      * Constructs a new legend with default settings.
157      *
158      * @param chart the chart that the legend belongs to.
159      */

160     public StandardLegend(JFreeChart chart) {
161
162         super(chart);
163         this.outerGap = DEFAULT_OUTER_GAP;
164         this.innerGap = DEFAULT_INNER_GAP;
165         this.backgroundPaint = DEFAULT_BACKGROUND_PAINT;
166         this.outlineStroke = DEFAULT_OUTLINE_STROKE;
167         this.outlinePaint = DEFAULT_OUTLINE_PAINT;
168         this.title = null;
169         this.titleFont = DEFAULT_TITLE_FONT;
170         this.itemFont = DEFAULT_ITEM_FONT;
171         this.itemPaint = Color.black;
172         this.displaySeriesShapes = false;
173         this.displaySeriesLines = false;
174
175     }
176
177     /**
178      * Returns the outer gap for the legend.
179      * <P>
180      * This is the amount of blank space around the outside of the legend.
181      *
182      * @return The gap.
183      */

184     public Spacer getOuterGap() {
185         return this.outerGap;
186     }
187
188     /**
189      * Sets the outer gap for the legend. A {@link LegendChangeEvent} is sent to all
190      * registered listeners.
191      *
192      * @param outerGap the outer gap (<code>null</code> not permitted).
193      */

194     public void setOuterGap(Spacer outerGap) {
195         if (outerGap == null) {
196             throw new NullPointerException JavaDoc("StandardLegend.setOuterGap(..): Null argument.");
197         }
198         this.outerGap = outerGap;
199         notifyListeners(new LegendChangeEvent(this));
200     }
201
202
203     /**
204      * Returns the inner gap for the legend.
205      * <P>
206      * This is the amount of blank space around the inside of the legend.
207      *
208      * @return The gap.
209      */

210     public Spacer getInnerGap() {
211         return innerGap;
212     }
213
214     /**
215      * Sets the inner gap for the legend. A {@link LegendChangeEvent} is sent to all
216      * registered listeners.
217      *
218      * @param innerGap the inner gap (<code>null</code> not permitted).
219      */

220     public void setInnerGap(Spacer innerGap) {
221         if (innerGap == null) {
222             throw new NullPointerException JavaDoc("StandardLegend.setInnerGap(..): Null argument.");
223         }
224         this.innerGap = innerGap;
225         notifyListeners(new LegendChangeEvent(this));
226     }
227
228     /**
229      * Returns the background color for the legend.
230      *
231      * @return The background color.
232      */

233     public Paint JavaDoc getBackgroundPaint() {
234         return this.backgroundPaint;
235     }
236
237     /**
238      * Sets the background color of the legend. A {@link LegendChangeEvent} is sent to all
239      * registered listeners.
240      *
241      * @param paint the new background color.
242      */

243     public void setBackgroundPaint(Paint JavaDoc paint) {
244         this.backgroundPaint = paint;
245         notifyListeners(new LegendChangeEvent(this));
246     }
247
248     /**
249      * Returns the outline pen/brush.
250      *
251      * @return The outline pen/brush.
252      */

253     public Stroke JavaDoc getOutlineStroke() {
254         return this.outlineStroke;
255     }
256
257     /**
258      * Sets the outline pen/brush. A {@link LegendChangeEvent} is sent to all registered
259      * listeners.
260      *
261      * @param stroke the new outline pen/brush (<code>null</code> not permitted).
262      */

263     public void setOutlineStroke(Stroke JavaDoc stroke) {
264         if (stroke == null) {
265             throw new NullPointerException JavaDoc("StandardLegend.setOutlineStroke(..): null argument");
266         }
267         this.outlineStroke = stroke;
268         notifyListeners(new LegendChangeEvent(this));
269     }
270
271     /**
272      * Returns the outline color.
273      *
274      * @return The outline color.
275      */

276     public Paint JavaDoc getOutlinePaint() {
277         return this.outlinePaint;
278     }
279
280     /**
281      * Sets the outline color. A {@link LegendChangeEvent} is sent to all registered listeners.
282      *
283      * @param paint the new outline color.
284      */

285     public void setOutlinePaint(Paint JavaDoc paint) {
286         this.outlinePaint = paint;
287         notifyListeners(new LegendChangeEvent(this));
288     }
289
290     /**
291      * Gets the title for the legend.
292      *
293      * @return The title of the legend; which may be null.
294      */

295     public String JavaDoc getTitle() {
296         return title;
297     }
298
299     /**
300      * Sets the title of the legend.
301      *
302      * @param title The title to use (<code>null</code> permitted).
303      */

304     public void setTitle(String JavaDoc title) {
305         this.title = title;
306     }
307
308     /**
309      * Returns the title font.
310      *
311      * @return The font.
312      */

313     public Font JavaDoc getTitleFont() {
314         return this.titleFont;
315     }
316
317     /**
318      * Sets the title font.
319      *
320      * @param font the new font.
321      */

322     public void setTitleFont(Font JavaDoc font) {
323         this.titleFont = font;
324         notifyListeners(new LegendChangeEvent(this));
325     }
326
327     /**
328      * Returns the series label font.
329      *
330      * @return The series label font.
331      */

332     public Font JavaDoc getItemFont() {
333         return this.itemFont;
334     }
335
336     /**
337      * Sets the series label font. A {@link LegendChangeEvent} is sent to all registered
338      * listeners.
339      *
340      * @param font the new series label font.
341      */

342     public void setItemFont(Font JavaDoc font) {
343         this.itemFont = font;
344         notifyListeners(new LegendChangeEvent(this));
345     }
346
347     /**
348      * Returns the series label color.
349      *
350      * @return The series label color.
351      */

352     public Paint JavaDoc getItemPaint() {
353         return this.itemPaint;
354     }
355
356     /**
357      * Sets the series label color. A {@link LegendChangeEvent} is sent to all registered
358      * listeners.
359      *
360      * @param paint the new series label color.
361      */

362     public void setItemPaint(Paint JavaDoc paint) {
363         this.itemPaint = paint;
364         notifyListeners(new LegendChangeEvent(this));
365     }
366
367     /**
368      * Returns the flag that indicates whether or not outlines are drawn around shapes.
369      *
370      * @return The flag.
371      */

372     public boolean getOutlineShapes() {
373         return this.outlineShapes;
374     }
375
376     /**
377      * Sets the flag that controls whether or not outlines are drawn around shapes.
378      *
379      * @param flag the flag.
380      */

381     public void setOutlineShapes(boolean flag) {
382         this.outlineShapes = flag;
383         notifyListeners(new LegendChangeEvent(this));
384     }
385
386     /**
387      * Returns the stroke used to outline shapes.
388      *
389      * @return The stroke.
390      */

391     public Stroke JavaDoc getShapeOutlineStroke() {
392         return this.shapeOutlineStroke;
393     }
394
395     /**
396      * Sets the stroke used to outline shapes. A {@link LegendChangeEvent} is sent to all
397      * registered listeners.
398      *
399      * @param stroke the stroke (<code>null</code> not permitted).
400      */

401     public void setShapeOutlineStroke(Stroke JavaDoc stroke) {
402         if (stroke == null) {
403             throw new NullPointerException JavaDoc(
404                 "StandardLegend.setShapeOutlineStroke(..): null argument");
405         }
406         this.shapeOutlineStroke = stroke;
407         notifyListeners(new LegendChangeEvent(this));
408     }
409
410     /**
411      * Returns the paint used to outline shapes.
412      *
413      * @return The paint.
414      */

415     public Paint JavaDoc getShapeOutlinePaint() {
416         return this.shapeOutlinePaint;
417     }
418
419     /**
420      * Sets the paint used to outline shapes. A {@link LegendChangeEvent} is sent to all
421      * registered listeners.
422      *
423      * @param paint the paint.
424      */

425     public void setShapeOutlinePaint(Paint JavaDoc paint) {
426         this.shapeOutlinePaint = paint;
427         notifyListeners(new LegendChangeEvent(this));
428     }
429
430     /**
431      * Sets a flag that controls whether or not the legend displays the series shapes.
432      *
433      * @param flag the new value of the flag.
434      */

435     public void setDisplaySeriesShapes(boolean flag) {
436         this.displaySeriesShapes = flag;
437         notifyListeners(new LegendChangeEvent(this));
438     }
439
440     /**
441      * Returns a flag that controls whether or not the legend displays the series shapes.
442      *
443      * @return <code>true</code> if the series shapes should be displayed, <code>false</code>
444      * otherwise.
445      */

446     public boolean getDisplaySeriesShapes() {
447         return this.displaySeriesShapes;
448     }
449
450     /**
451      * Sets a flag that controls whether or not the legend displays the series line stroke.
452      *
453      * @param flag the new value of the flag.
454      */

455     public void setDisplaySeriesLines(boolean flag) {
456         this.displaySeriesLines = flag;
457         notifyListeners(new LegendChangeEvent(this));
458     }
459
460     /**
461      * Returns a flag that controls whether or not the legend displays the series line stroke.
462      *
463      * @return <code>true</code> if the series lines should be displayed, <code>false</code>
464      * otherwise.
465      */

466     public boolean getDisplaySeriesLines() {
467         return this.displaySeriesLines;
468     }
469
470     /**
471      * Draws the legend on a Java 2D graphics device (such as the screen or a printer).
472      *
473      * @param g2 the graphics device.
474      * @param available the area within which the legend, and afterwards the plot, should be
475      * drawn.
476      * @param info collects rendering info (optional).
477      *
478      * @return The area used by the legend.
479      */

480     public Rectangle2D JavaDoc draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc available, ChartRenderingInfo info) {
481
482         return draw(g2, available,
483                     (getAnchor() & HORIZONTAL) != 0, (getAnchor() & INVERTED) != 0,
484                     info);
485
486     }
487
488     /**
489      * Draws the legend.
490      *
491      * @param g2 the graphics device.
492      * @param available the area available for drawing the chart.
493      * @param horizontal a flag indicating whether the legend items are laid out horizontally.
494      * @param inverted ???
495      * @param info collects rendering info (optional).
496      *
497      * @return The remaining available drawing area.
498      */

499     protected Rectangle2D JavaDoc draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc available,
500                                boolean horizontal, boolean inverted,
501                                ChartRenderingInfo info) {
502
503         LegendItemCollection legendItems = getChart().getPlot().getLegendItems();
504
505         if ((legendItems != null) && (legendItems.getItemCount() > 0)) {
506
507             DrawableLegendItem legendTitle = null;
508
509             Rectangle2D JavaDoc legendArea = new Rectangle2D.Double JavaDoc();
510             double availableWidth = available.getWidth();
511             double availableHeight = available.getHeight();
512
513             // the translation point for the origin of the drawing system
514
Point2D JavaDoc translation = new Point2D.Double JavaDoc();
515
516             // Create buffer for individual rectangles within the legend
517
DrawableLegendItem[] items = new DrawableLegendItem[legendItems.getItemCount()];
518
519             // Compute individual rectangles in the legend, translation point as well
520
// as the bounding box for the legend.
521
if (horizontal) {
522                 double xstart = available.getX() + getOuterGap().getLeftSpace(availableWidth);
523                 double xlimit = available.getMaxX()
524                     + getOuterGap().getRightSpace(availableWidth) - 1;
525                 double maxRowWidth = 0;
526                 double xoffset = 0;
527                 double rowHeight = 0;
528                 double totalHeight = 0;
529                 boolean startingNewRow = true;
530
531
532                 if (title != null && !title.equals("")) {
533
534                     g2.setFont(getTitleFont());
535
536                     LegendItem titleItem = new LegendItem(title,
537                         title,
538                         null,
539                         Color.black,
540                         DEFAULT_OUTLINE_PAINT,
541                         DEFAULT_OUTLINE_STROKE);
542
543                     legendTitle = createDrawableLegendItem(g2, titleItem,
544                         xoffset,
545                         totalHeight);
546
547                     rowHeight = Math.max(rowHeight, legendTitle.getHeight());
548                     xoffset += legendTitle.getWidth();
549                 }
550
551                 g2.setFont(itemFont);
552                 for (int i = 0; i < legendItems.getItemCount(); i++) {
553                     items[i] = createDrawableLegendItem(g2, legendItems.get(i),
554                         xoffset, totalHeight);
555                     if ((!startingNewRow)
556                         && (items[i].getX() + items[i].getWidth() + xstart > xlimit)) {
557
558                         maxRowWidth = Math.max(maxRowWidth, xoffset);
559                         xoffset = 0;
560                         totalHeight += rowHeight;
561                         i--;
562                         startingNewRow = true;
563
564                     }
565                     else {
566                         rowHeight = Math.max(rowHeight, items[i].getHeight());
567                         xoffset += items[i].getWidth();
568                         startingNewRow = false;
569                     }
570                 }
571
572                 maxRowWidth = Math.max(maxRowWidth, xoffset);
573                 totalHeight += rowHeight;
574
575                 // Create the bounding box
576
legendArea = new Rectangle2D.Double JavaDoc(0, 0, maxRowWidth, totalHeight);
577
578                 // The yloc point is the variable part of the translation point
579
// for horizontal legends. xloc is constant.
580
double yloc = (inverted)
581                     ? available.getMaxY() - totalHeight
582                     - getOuterGap().getBottomSpace(availableHeight)
583                     : available.getY() + getOuterGap().getTopSpace(availableHeight);
584                 double xloc = available.getX() + available.getWidth() / 2 - maxRowWidth / 2;
585
586                 // Create the translation point
587
translation = new Point2D.Double JavaDoc(xloc, yloc);
588             }
589             else { // vertical...
590
double totalHeight = 0;
591                 double maxWidth = 0;
592
593                 if (title != null && !title.equals("")) {
594
595                     g2.setFont(getTitleFont());
596
597                     LegendItem titleItem = new LegendItem(title,
598                         title,
599                         null,
600                         Color.black,
601                         DEFAULT_OUTLINE_PAINT,
602                         DEFAULT_OUTLINE_STROKE);
603
604                     legendTitle = createDrawableLegendItem(g2, titleItem, 0, totalHeight);
605
606                     totalHeight += legendTitle.getHeight();
607                     maxWidth = Math.max(maxWidth, legendTitle.getWidth());
608                 }
609
610                 g2.setFont(itemFont);
611                 for (int i = 0; i < items.length; i++) {
612                     items[i] = createDrawableLegendItem(g2, legendItems.get(i), 0, totalHeight);
613                     totalHeight += items[i].getHeight();
614                     maxWidth = Math.max(maxWidth, items[i].getWidth());
615                 }
616
617                 // Create the bounding box
618
legendArea = new Rectangle2D.Float JavaDoc(0, 0, (float) maxWidth, (float) totalHeight);
619
620                 // The xloc point is the variable part of the translation point
621
// for vertical legends. yloc is constant.
622
double xloc = (inverted)
623                     ? available.getMaxX() - maxWidth - getOuterGap().getRightSpace(availableWidth)
624                     : available.getX() + getOuterGap().getLeftSpace(availableWidth);
625                 double yloc = available.getY() + (available.getHeight() / 2) - (totalHeight / 2);
626
627                 // Create the translation point
628
translation = new Point2D.Double JavaDoc(xloc, yloc);
629             }
630
631             // Move the origin of the drawing to the appropriate location
632
g2.translate(translation.getX(), translation.getY());
633
634             // Draw the legend's bounding box
635
g2.setPaint(backgroundPaint);
636             g2.fill(legendArea);
637             g2.setPaint(outlinePaint);
638             g2.setStroke(outlineStroke);
639             g2.draw(legendArea);
640
641             // draw legend title
642
if (legendTitle != null) {
643                 // XXX dsm - make title bold?
644
g2.setPaint(legendTitle.getItem().getPaint());
645                 g2.setPaint(this.itemPaint);
646                 g2.setFont(getTitleFont());
647                 g2.drawString(legendTitle.getItem().getLabel(),
648                     (float) legendTitle.getLabelPosition().getX(),
649                     (float) legendTitle.getLabelPosition().getY());
650             }
651
652             EntityCollection entities = null;
653             if (info != null) {
654                 entities = info.getEntityCollection();
655             }
656             // Draw individual series elements
657
for (int i = 0; i < items.length; i++) {
658                 g2.setPaint(items[i].getItem().getPaint());
659                 Shape JavaDoc keyBox = items[i].getMarker();
660                 if (displaySeriesLines) {
661                     g2.setStroke(items[i].getLineStroke());
662                     g2.draw(items[i].getLine());
663
664                     if (displaySeriesShapes) {
665                         g2.fill(keyBox);
666                     }
667
668                 }
669                 else {
670                     g2.fill(keyBox);
671                 }
672                 if (getOutlineShapes()) {
673                     g2.setPaint(this.shapeOutlinePaint);
674                     g2.setStroke(this.shapeOutlineStroke);
675                     g2.draw(keyBox);
676                 }
677                 g2.setPaint(this.itemPaint);
678                 g2.setFont(this.itemFont);
679                 //g2.drawString(items[i].getItem().getLabel(),
680
// (float) items[i].getLabelPosition().getX(),
681
// (float) items[i].getLabelPosition().getY());
682
RefineryUtilities.drawAlignedString(items[i].getItem().getLabel(), g2,
683                     (float) items[i].getLabelPosition().getX(),
684                     (float) items[i].getLabelPosition().getY(),
685                     TextAnchor.CENTER_LEFT);
686
687                 if (entities != null) {
688                     Rectangle2D JavaDoc area = new Rectangle2D.Double JavaDoc(translation.getX() + items[i].getX(),
689                         translation.getY() + items[i].getY(),
690                         items[i].getWidth(),
691                         items[i].getHeight());
692                     LegendItemEntity entity = new LegendItemEntity(area);
693                     entity.setSeriesIndex(i);
694                     entities.addEntity(entity);
695                 }
696             }
697
698             // translate the origin back to what it was prior to drawing the legend
699
g2.translate(-translation.getX(), -translation.getY());
700
701             if (horizontal) {
702                 // The remaining drawing area bounding box will have the same
703
// x origin, width and height independent of the anchor's
704
// location. The variable is the y coordinate. If the anchor is
705
// SOUTH, the y coordinate is simply the original y coordinate
706
// of the available area. If it is NORTH, we adjust original y
707
// by the total height of the legend and the initial gap.
708
double yy = available.getY();
709                 double yloc = (inverted) ? yy
710                     : yy + legendArea.getHeight()
711                     + getOuterGap().getBottomSpace(availableHeight);
712
713                 // return the remaining available drawing area
714
return new Rectangle2D.Double JavaDoc(available.getX(), yloc, availableWidth,
715                     availableHeight - legendArea.getHeight()
716                     - getOuterGap().getTopSpace(availableHeight)
717                     - getOuterGap().getBottomSpace(availableHeight));
718             }
719             else {
720                 // The remaining drawing area bounding box will have the same
721
// y origin, width and height independent of the anchor's
722
// location. The variable is the x coordinate. If the anchor is
723
// EAST, the x coordinate is simply the original x coordinate
724
// of the available area. If it is WEST, we adjust original x
725
// by the total width of the legend and the initial gap.
726
double xloc = (inverted) ? available.getX()
727                     : available.getX()
728                     + legendArea.getWidth()
729                     + getOuterGap().getLeftSpace(availableWidth)
730                     + getOuterGap().getRightSpace(availableWidth);
731
732
733                 // return the remaining available drawing area
734
return new Rectangle2D.Double JavaDoc(xloc, available.getY(),
735                     availableWidth - legendArea.getWidth()
736                     - getOuterGap().getLeftSpace(availableWidth)
737                     - getOuterGap().getRightSpace(availableWidth),
738                     availableHeight);
739             }
740         }
741         else {
742             return available;
743         }
744     }
745
746     /**
747      * Returns a rectangle surrounding a individual entry in the legend.
748          * <P>
749      * The marker box for each entry will be positioned next to the name of the
750      * specified series within the legend area. The marker box will be square
751      * and 70% of the height of current font.
752      *
753      * @param graphics the graphics context (supplies font metrics etc.).
754      * @param legendItem the legend item.
755      * @param x the upper left x coordinate for the bounding box.
756      * @param y the upper left y coordinate for the bounding box.
757      *
758      * @return A legend item encapsulating all necessary info for drawing.
759      */

760     private DrawableLegendItem createDrawableLegendItem(Graphics2D JavaDoc graphics,
761                                                         LegendItem legendItem,
762                                                         double x, double y) {
763
764         int innerGap = 2;
765         FontMetrics JavaDoc fm = graphics.getFontMetrics();
766         LineMetrics JavaDoc lm = fm.getLineMetrics(legendItem.getLabel(), graphics);
767         float textAscent = lm.getAscent();
768         float lineHeight = textAscent + lm.getDescent() + lm.getLeading();
769
770         DrawableLegendItem item = new DrawableLegendItem(legendItem);
771
772         float xLabelLoc = (float) (x + innerGap + 1.15f * lineHeight);
773         //float yloc = (float) (y + innerGap + 0.15f * lineHeight + textAscent);
774
float yLabelLoc = (float) (y + innerGap + 0.5f * lineHeight);
775
776         item.setLabelPosition(new Point2D.Float JavaDoc(xLabelLoc, yLabelLoc));
777
778         float width = (float) (item.getLabelPosition().getX() - x
779             + fm.getStringBounds(legendItem.getLabel(), graphics).getWidth()
780             + 0.5 * textAscent);
781
782         float height = (2 * innerGap + lineHeight);
783         item.setBounds(x, y, width, height);
784         float boxDim = lineHeight * 0.70f;
785         float xloc = (float) (x + innerGap + 0.15f * lineHeight);
786         float yloc = (float) (y + innerGap + 0.15f * lineHeight);
787         if (this.displaySeriesLines) {
788             Line2D JavaDoc line = new Line2D.Float JavaDoc(xloc, yloc + boxDim / 2,
789                                            xloc + boxDim * 3, yloc + boxDim / 2);
790             item.setLineStroke(legendItem.getStroke());
791             item.setLine(line);
792             // lengthen the bounds to accomodate the longer item
793
item.setBounds(item.getX(), item.getY(),
794                            item.getWidth() + boxDim * 2,
795                            item.getHeight());
796             item.setLabelPosition(new Point2D.Float JavaDoc(xLabelLoc + boxDim * 2, yLabelLoc));
797             if (this.displaySeriesShapes) {
798                 Shape JavaDoc marker = legendItem.getShape();
799                 AffineTransform JavaDoc transformer = AffineTransform.getTranslateInstance(
800                     xloc + (boxDim * 1.5), yloc + boxDim / 2);
801                 marker = transformer.createTransformedShape(marker);
802                 item.setMarker(marker);
803            }
804
805         }
806         else {
807             if (this.displaySeriesShapes) {
808                 Shape JavaDoc marker = legendItem.getShape();
809        
810                 AffineTransform JavaDoc transformer = AffineTransform.getTranslateInstance(
811                     xloc + boxDim / 2, yloc + boxDim / 2);
812                 marker = transformer.createTransformedShape(marker);
813                 item.setMarker(marker);
814             }
815             else {
816                 item.setMarker(new Rectangle2D.Float JavaDoc(xloc, yloc, boxDim, boxDim));
817             }
818         }
819         return item;
820
821     }
822
823     /**
824      * Tests an object for equality with this legend.
825      *
826      * @param obj the object.
827      *
828      * @return <code>true</code> or <code>false</code>.
829      */

830     public boolean equals(Object JavaDoc obj) {
831
832         if (obj == null) {
833             return false;
834         }
835
836         if (obj == this) {
837             return true;
838         }
839
840         if (obj instanceof StandardLegend) {
841             StandardLegend l = (StandardLegend) obj;
842             if (super.equals(obj)) {
843
844                 if (ObjectUtils.equal(this.outerGap, l.outerGap) == false) {
845                     return false;
846                 }
847                 if (ObjectUtils.equal(this.outlineStroke, l.outlineStroke) == false) {
848                     return false;
849                 }
850                 if (ObjectUtils.equal(this.outlinePaint, l.outlinePaint) == false) {
851                     return false;
852                 }
853                 if (ObjectUtils.equal(this.backgroundPaint, l.backgroundPaint) == false) {
854                     return false;
855                 }
856                 if (ObjectUtils.equal(this.innerGap, l.innerGap) == false) {
857                     return false;
858                 }
859                 if (ObjectUtils.equal(this.title, l.title) == false) {
860                     return false;
861                 }
862                 if (ObjectUtils.equal(this.titleFont, l.titleFont) == false) {
863                     return false;
864                 }
865                 if (ObjectUtils.equal(this.itemFont, l.itemFont) == false) {
866                     return false;
867                 }
868                 if (ObjectUtils.equal(this.itemPaint, l.itemPaint) == false) {
869                     return false;
870                 }
871                 if (this.outlineShapes != l.outlineShapes) {
872                     return false;
873                 }
874                 if (ObjectUtils.equal(this.shapeOutlineStroke, l.shapeOutlineStroke) == false) {
875                     return false;
876                 }
877                 if (ObjectUtils.equal(this.shapeOutlinePaint, l.shapeOutlinePaint) == false) {
878                     return false;
879                 }
880                 if (this.displaySeriesShapes == l.displaySeriesShapes) {
881                     return true;
882                 }
883             }
884         }
885
886         return false;
887     }
888
889     /**
890      * Provides serialization support.
891      *
892      * @param stream the output stream.
893      *
894      * @throws IOException if there is an I/O error.
895      */

896     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
897         stream.defaultWriteObject();
898         SerialUtilities.writeStroke(this.outlineStroke, stream);
899         SerialUtilities.writePaint(this.outlinePaint, stream);
900         SerialUtilities.writePaint(this.backgroundPaint, stream);
901         SerialUtilities.writePaint(this.itemPaint, stream);
902         SerialUtilities.writeStroke(this.shapeOutlineStroke, stream);
903         SerialUtilities.writePaint(this.shapeOutlinePaint, stream);
904     }
905
906     /**
907      * Provides serialization support.
908      *
909      * @param stream the output stream.
910      *
911      * @throws IOException if there is an I/O error.
912      * @throws ClassNotFoundException if there is a classpath problem.
913      */

914     private void readObject(ObjectInputStream JavaDoc stream) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
915         stream.defaultReadObject();
916         this.outlineStroke = SerialUtilities.readStroke(stream);
917         this.outlinePaint = SerialUtilities.readPaint(stream);
918         this.backgroundPaint = SerialUtilities.readPaint(stream);
919         this.itemPaint = SerialUtilities.readPaint(stream);
920         this.shapeOutlineStroke = SerialUtilities.readStroke(stream);
921         this.shapeOutlinePaint = SerialUtilities.readPaint(stream);
922     }
923
924 }
925
Popular Tags