Source for org.jfree.report.modules.misc.survey.SurveyScale

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation 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:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: SurveyScale.java 3525 2007-10-16 11:43:48Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.modules.misc.survey;
  33: 
  34: import java.awt.BasicStroke;
  35: import java.awt.Color;
  36: import java.awt.Font;
  37: import java.awt.Graphics2D;
  38: import java.awt.Paint;
  39: import java.awt.Shape;
  40: import java.awt.Stroke;
  41: import java.awt.geom.Ellipse2D;
  42: import java.awt.geom.Line2D;
  43: import java.awt.geom.Rectangle2D;
  44: import java.io.IOException;
  45: import java.io.ObjectInputStream;
  46: import java.io.ObjectOutputStream;
  47: import java.io.Serializable;
  48: 
  49: import org.jfree.serializer.SerializerHelper;
  50: import org.jfree.text.TextUtilities;
  51: import org.jfree.ui.Drawable;
  52: import org.jfree.ui.TextAnchor;
  53: import org.jfree.util.BooleanList;
  54: import org.jfree.util.BooleanUtilities;
  55: import org.jfree.util.ShapeList;
  56: import org.jfree.util.ShapeUtilities;
  57: 
  58: /**
  59:  * Draws a survey scale.  By implementing the {@link Drawable} interface,
  60:  * instances can be displayed within a report using the {@link
  61:  * org.jfree.report.DrawableElement} class.
  62:  *
  63:  * @author David Gilbert
  64:  */
  65: public class SurveyScale implements Drawable, Serializable
  66: {
  67:   private static final Number[] EMPTY_VALUES = new Number[0];
  68: 
  69:   /** The lowest response value on the scale. */
  70:   private int lowest;
  71: 
  72:   /** The highest response value on the scale. */
  73:   private int highest;
  74: 
  75:   /** The lower margin. */
  76:   private double lowerMargin = 0.10;
  77: 
  78:   /** The upper margin. */
  79:   private double upperMargin = 0.10;
  80: 
  81:   /** A list of flags that control whether or not the shapes are filled. */
  82:   private BooleanList fillShapes;
  83: 
  84:   /** The values to display. */
  85:   private Number[] values;
  86: 
  87:   /** The lower bound of the highlighted range. */
  88:   private Number rangeLowerBound;
  89: 
  90:   /** The upper bound of the highlighted range. */
  91:   private Number rangeUpperBound;
  92: 
  93:   /** Draw a border? */
  94:   private boolean drawBorder = false;
  95: 
  96:   /** Draw the tick marks? */
  97:   private boolean drawTickMarks;
  98: 
  99:   /** Draw the scale values. */
 100:   private boolean drawScaleValues = false;
 101: 
 102:   /** The font used to display the scale values. */
 103:   private Font scaleValueFont;
 104: 
 105:   /** The paint used to draw the scale values. */
 106:   private transient Paint scaleValuePaint;
 107: 
 108:   /** The range paint. */
 109:   private transient Paint rangePaint;
 110: 
 111:   /** The shapes to display. */
 112:   private transient ShapeList shapes;
 113: 
 114:   /** The fill paint. */
 115:   private transient Paint fillPaint;
 116: 
 117:   /** The outline stroke for the shapes. */
 118:   private transient Stroke outlineStroke;
 119: 
 120:   /**
 121:    * The default shape, if no shape is defined in the shapeList for the given
 122:    * value.
 123:    */
 124:   private transient Shape defaultShape;
 125: 
 126:   /** The tick mark paint. */
 127:   private transient Paint tickMarkPaint;
 128: 
 129:   private transient Paint borderPaint;
 130: 
 131:   private int range;
 132:   private double lowerBound;
 133:   private double upperBound;
 134: 
 135:   /** Creates a new default instance. */
 136:   public SurveyScale()
 137:   {
 138:     this(1, 5, EMPTY_VALUES);
 139:   }
 140: 
 141:   /**
 142:    * Creates a new instance.
 143:    *
 144:    * @param lowest  the lowest response value on the scale.
 145:    * @param highest the highest response value on the scale.
 146:    * @param values  the values to display.
 147:    */
 148:   public SurveyScale(final int lowest, final int highest,
 149:                      final Number[] values)
 150:   {
 151: 
 152:     this.lowest = lowest;
 153:     this.highest = highest;
 154:     if (values == null)
 155:     {
 156:       this.values = EMPTY_VALUES;
 157:     }
 158:     else
 159:     {
 160:       this.values = (Number[]) values.clone();
 161:     }
 162: 
 163:     this.drawTickMarks = true;
 164:     this.tickMarkPaint = Color.gray;
 165: 
 166:     this.scaleValueFont = new Font("Serif", Font.ITALIC, 10);
 167:     this.scaleValuePaint = Color.black;
 168:     this.defaultShape = new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0);
 169: 
 170:     this.rangeLowerBound = null;
 171:     this.rangeUpperBound = null;
 172:     this.rangePaint = Color.lightGray;
 173: 
 174:     this.shapes = createShapeList();
 175:     this.fillShapes = new BooleanList();
 176:     this.fillShapes.setBoolean(0, Boolean.TRUE);
 177:     //this.fillShapes.setBoolean(5, Boolean.TRUE);
 178:     this.fillPaint = Color.black;
 179:     this.outlineStroke = new BasicStroke(0.5f);
 180:     recompute();
 181:   }
 182: 
 183:   public int getLowest()
 184:   {
 185:     return lowest;
 186:   }
 187: 
 188:   public void setLowest(final int lowest)
 189:   {
 190:     this.lowest = lowest;
 191:     recompute();
 192:   }
 193: 
 194:   public int getHighest()
 195:   {
 196:     return highest;
 197:   }
 198: 
 199:   public void setHighest(final int highest)
 200:   {
 201:     this.highest = highest;
 202:     recompute();
 203:   }
 204: 
 205:   /**
 206:    * This method is called whenever lowest or highest has changed. It will
 207:    * recompute the range and upper and lower bounds.
 208:    */
 209:   protected void recompute()
 210:   {
 211:     this.range = Math.max(0, this.highest - this.lowest);
 212:     this.lowerBound = this.lowest - (range * this.lowerMargin);
 213:     this.upperBound = this.highest + (range * this.upperMargin);
 214:   }
 215: 
 216:   protected int getRange()
 217:   {
 218:     return range;
 219:   }
 220: 
 221:   protected void setRange(final int range)
 222:   {
 223:     this.range = range;
 224:   }
 225: 
 226:   protected double getLowerBound()
 227:   {
 228:     return lowerBound;
 229:   }
 230: 
 231:   protected void setLowerBound(final double lowerBound)
 232:   {
 233:     this.lowerBound = lowerBound;
 234:   }
 235: 
 236:   protected double getUpperBound()
 237:   {
 238:     return upperBound;
 239:   }
 240: 
 241:   protected void setUpperBound(final double upperBound)
 242:   {
 243:     this.upperBound = upperBound;
 244:   }
 245: 
 246:   /**
 247:    * Creates the shape list used when drawing the scale. The list returned must
 248:    * contain exactly 6 elements.
 249:    *
 250:    * @return
 251:    */
 252:   protected ShapeList createShapeList()
 253:   {
 254:     final ShapeList shapes = new ShapeList();
 255:     //this.shapes.setShape(0, createDiagonalCross(3.0f, 0.5f));
 256:     shapes.setShape(0, new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
 257:     shapes.setShape(1, ShapeUtilities.createDownTriangle(4.0f));
 258:     shapes.setShape(2, ShapeUtilities.createUpTriangle(4.0f));
 259:     shapes.setShape(3, ShapeUtilities.createDiamond(4.0f));
 260:     shapes.setShape(4, new Rectangle2D.Double(-4.0, -4.0, 8.0, 8.0));
 261:     shapes.setShape(5, new Ellipse2D.Double(-4.0, -4.0, 8.0, 8.0));
 262:     //this.shapes.setShape(5, createDiagonalCross(3.0f, 0.5f));
 263:     return shapes;
 264:   }
 265: 
 266:   /**
 267:    * Returns the lower bound of the highlighted range.  A <code>null</code>
 268:    * value indicates that no range is set for highlighting.
 269:    *
 270:    * @return The lower bound (possibly <code>null</code>).
 271:    */
 272:   public Number getRangeLowerBound()
 273:   {
 274:     return this.rangeLowerBound;
 275:   }
 276: 
 277:   /**
 278:    * Sets the lower bound for the range that is highlighted on the scale.
 279:    *
 280:    * @param bound the lower bound (<code>null</code> permitted).
 281:    */
 282:   public void setRangeLowerBound(final Number bound)
 283:   {
 284:     this.rangeLowerBound = bound;
 285:   }
 286: 
 287:   /**
 288:    * Returns the upper bound of the highlighted range.  A <code>null</code>
 289:    * value indicates that no range is set for highlighting.
 290:    *
 291:    * @return The upper bound (possibly <code>null</code>).
 292:    */
 293:   public Number getRangeUpperBound()
 294:   {
 295:     return this.rangeUpperBound;
 296:   }
 297: 
 298:   /**
 299:    * Sets the upper bound for the range that is highlighted on the scale.
 300:    *
 301:    * @param bound the upper bound (<code>null</code> permitted).
 302:    */
 303:   public void setRangeUpperBound(final Number bound)
 304:   {
 305:     this.rangeUpperBound = bound;
 306:   }
 307: 
 308:   /**
 309:    * Returns a flag that controls whether or not a border is drawn around the
 310:    * scale.
 311:    *
 312:    * @return A boolean.
 313:    */
 314:   public boolean isDrawBorder()
 315:   {
 316:     return this.drawBorder;
 317:   }
 318: 
 319:   /**
 320:    * Sets a flag that controls whether or not a border is drawn around the
 321:    * scale.
 322:    *
 323:    * @param flag the flag.
 324:    */
 325:   public void setDrawBorder(final boolean flag)
 326:   {
 327:     this.drawBorder = flag;
 328:   }
 329: 
 330:   /**
 331:    * Returns the flag that controls whether the tick marks are drawn.
 332:    *
 333:    * @return A boolean.
 334:    */
 335:   public boolean isDrawTickMarks()
 336:   {
 337:     return this.drawTickMarks;
 338:   }
 339: 
 340:   /**
 341:    * Sets the flag that controls whether the tick marks are drawn.
 342:    *
 343:    * @param flag a boolean.
 344:    */
 345:   public void setDrawTickMarks(final boolean flag)
 346:   {
 347:     this.drawTickMarks = flag;
 348:   }
 349: 
 350:   /**
 351:    * Returns a flag that controls whether or not scale values are drawn.
 352:    *
 353:    * @return a boolean.
 354:    */
 355:   public boolean isDrawScaleValues()
 356:   {
 357:     return this.drawScaleValues;
 358:   }
 359: 
 360:   /**
 361:    * Sets a flag that controls whether or not scale values are drawn.
 362:    *
 363:    * @param flag the flag.
 364:    */
 365:   public void setDrawScaleValues(final boolean flag)
 366:   {
 367:     this.drawScaleValues = flag;
 368:   }
 369: 
 370:   /**
 371:    * Returns the font used to display the scale values.
 372:    *
 373:    * @return A font (never <code>null</code>).
 374:    */
 375:   public Font getScaleValueFont()
 376:   {
 377:     return this.scaleValueFont;
 378:   }
 379: 
 380:   /**
 381:    * Sets the font used to display the scale values.
 382:    *
 383:    * @param font the font (<code>null</code> not permitted).
 384:    */
 385:   public void setScaleValueFont(final Font font)
 386:   {
 387:     if (font == null)
 388:     {
 389:       throw new IllegalArgumentException("Null 'font' argument.");
 390:     }
 391:     this.scaleValueFont = font;
 392:   }
 393: 
 394:   /**
 395:    * Returns the color used to draw the scale values (if they are visible).
 396:    *
 397:    * @return A paint (never <code>null</code>).
 398:    */
 399:   public Paint getScaleValuePaint()
 400:   {
 401:     return this.scaleValuePaint;
 402:   }
 403: 
 404:   /**
 405:    * Sets the color used to draw the scale values.
 406:    *
 407:    * @param paint the paint (<code>null</code> not permitted).
 408:    */
 409:   public void setScaleValuePaint(final Paint paint)
 410:   {
 411:     if (paint == null)
 412:     {
 413:       throw new IllegalArgumentException("Null 'paint' argument.");
 414:     }
 415:     this.scaleValuePaint = paint;
 416:   }
 417: 
 418:   /**
 419:    * Returns the shape used to indicate the value of a response.
 420:    *
 421:    * @param index the value index (zero-based).
 422:    * @return The shape.
 423:    */
 424:   public Shape getShape(final int index)
 425:   {
 426:     return this.shapes.getShape(index);
 427:   }
 428: 
 429:   /**
 430:    * Sets the shape used to mark a particular value in the dataset.
 431:    *
 432:    * @param index the value index (zero-based).
 433:    * @param shape the shape (<code>null</code> not permitted).
 434:    */
 435:   public void setShape(final int index, final Shape shape)
 436:   {
 437:     this.shapes.setShape(index, shape);
 438:   }
 439: 
 440:   /**
 441:    * Returns a flag that controls whether the shape for a particular value
 442:    * should be filled.
 443:    *
 444:    * @param index the value index (zero-based).
 445:    * @return A boolean.
 446:    */
 447:   public boolean isShapeFilled(final int index)
 448:   {
 449:     boolean result = false;
 450:     final Boolean b = this.fillShapes.getBoolean(index);
 451:     if (b != null)
 452:     {
 453:       result = b.booleanValue();
 454:     }
 455:     return result;
 456:   }
 457: 
 458:   /**
 459:    * Sets the flag that controls whether the shape for a particular value should
 460:    * be filled.
 461:    *
 462:    * @param index the value index (zero-based).
 463:    * @param fill  the flag.
 464:    */
 465:   public void setShapeFilled(final int index, final boolean fill)
 466:   {
 467:     this.fillShapes.setBoolean(index, BooleanUtilities.valueOf(fill));
 468:   }
 469: 
 470:   /**
 471:    * Returns the paint used to highlight the range.
 472:    *
 473:    * @return A {@link Paint} object (never <code>null</code>).
 474:    */
 475:   public Paint getRangePaint()
 476:   {
 477:     return this.rangePaint;
 478:   }
 479: 
 480:   /**
 481:    * Sets the paint used to highlight the range (if one is specified).
 482:    *
 483:    * @param paint the paint (<code>null</code> not permitted).
 484:    */
 485:   public void setRangePaint(final Paint paint)
 486:   {
 487:     if (paint == null)
 488:     {
 489:       throw new IllegalArgumentException("Null 'paint' argument.");
 490:     }
 491:     this.rangePaint = paint;
 492:   }
 493: 
 494:   public Paint getBorderPaint()
 495:   {
 496:     return borderPaint;
 497:   }
 498: 
 499:   public void setBorderPaint(final Paint borderPaint)
 500:   {
 501:     if (borderPaint == null)
 502:     {
 503:       throw new IllegalArgumentException("Null 'paint' argument.");
 504:     }
 505:     this.borderPaint = borderPaint;
 506:   }
 507: 
 508:   /**
 509:    * Returns the default shape, which is used, if a shape for a certain value is
 510:    * not defined.
 511:    *
 512:    * @return the default shape, never null.
 513:    */
 514:   public Shape getDefaultShape()
 515:   {
 516:     return defaultShape;
 517:   }
 518: 
 519:   /**
 520:    * Redefines the default shape.
 521:    *
 522:    * @param defaultShape the default shape
 523:    * @throws NullPointerException if the given shape is null.
 524:    */
 525:   public void setDefaultShape(final Shape defaultShape)
 526:   {
 527:     if (defaultShape == null)
 528:     {
 529:       throw new NullPointerException("The default shape must not be null.");
 530:     }
 531:     this.defaultShape = defaultShape;
 532:   }
 533: 
 534:   public Paint getTickMarkPaint()
 535:   {
 536:     return tickMarkPaint;
 537:   }
 538: 
 539:   public void setTickMarkPaint(final Paint tickMarkPaint)
 540:   {
 541:     if (tickMarkPaint == null)
 542:     {
 543:       throw new NullPointerException();
 544:     }
 545:     this.tickMarkPaint = tickMarkPaint;
 546:   }
 547: 
 548:   public Number[] getValues()
 549:   {
 550:     return (Number[]) values.clone();
 551:   }
 552: 
 553:   public Paint getFillPaint()
 554:   {
 555:     return fillPaint;
 556:   }
 557: 
 558:   public void setFillPaint(final Paint fillPaint)
 559:   {
 560:     if (fillPaint == null)
 561:     {
 562:       throw new NullPointerException();
 563:     }
 564:     this.fillPaint = fillPaint;
 565:   }
 566: 
 567:   public Stroke getOutlineStroke()
 568:   {
 569:     return outlineStroke;
 570:   }
 571: 
 572:   public void setOutlineStroke(final Stroke outlineStroke)
 573:   {
 574:     if (outlineStroke == null)
 575:     {
 576:       throw new NullPointerException();
 577:     }
 578:     this.outlineStroke = outlineStroke;
 579:   }
 580: 
 581:   public double getUpperMargin()
 582:   {
 583:     return upperMargin;
 584:   }
 585: 
 586:   public void setUpperMargin(final double upperMargin)
 587:   {
 588:     this.upperMargin = upperMargin;
 589:   }
 590: 
 591:   public double getLowerMargin()
 592:   {
 593:     return lowerMargin;
 594:   }
 595: 
 596:   public void setLowerMargin(final double lowerMargin)
 597:   {
 598:     this.lowerMargin = lowerMargin;
 599:   }
 600: 
 601:   /**
 602:    * Draws the survey scale.
 603:    *
 604:    * @param g2   the graphics device.
 605:    * @param area the area.
 606:    */
 607:   public void draw(final Graphics2D g2, final Rectangle2D area)
 608:   {
 609: 
 610:     if (isDrawBorder())
 611:     {
 612:       drawBorder(g2, area);
 613:     }
 614: 
 615:     drawRangeArea(area, g2);
 616: 
 617:     // draw tick marks...
 618:     if (isDrawTickMarks())
 619:     {
 620:       drawTickMarks(g2, area);
 621:     }
 622: 
 623:     // draw scale values...
 624:     if (isDrawScaleValues())
 625:     {
 626:       drawScaleValues(g2, area);
 627:     }
 628: 
 629:     drawValues(g2, area);
 630:   }
 631: 
 632:   protected void drawValues(final Graphics2D g2,
 633:                             final Rectangle2D area)
 634:   {
 635: 
 636:     // draw data values...
 637:     final Number[] values = getValues();
 638:     if (values.length == 0)
 639:     {
 640:       return;
 641:     }
 642: 
 643:     final double y = area.getCenterY();
 644: 
 645:     final Stroke outlineStroke = getOutlineStroke();
 646:     final Shape defaultShape = getDefaultShape();
 647: 
 648:     g2.setPaint(getFillPaint());
 649:     for (int i = 0; i < values.length; i++)
 650:     {
 651:       final Number n = values[i];
 652:       if (n == null)
 653:       {
 654:         continue;
 655:       }
 656: 
 657:       final double v = n.doubleValue();
 658:       final double x = valueToJava2D(v, area);
 659:       Shape valueShape = getShape(i);
 660:       if (valueShape == null)
 661:       {
 662:         valueShape = defaultShape;
 663:       }
 664:       if (isShapeFilled(i))
 665:       {
 666:         g2.translate(x, y);
 667:         g2.fill(valueShape);
 668:         g2.translate(-x, -y);
 669:       }
 670:       else
 671:       {
 672:         g2.setStroke(outlineStroke);
 673:         g2.translate(x, y);
 674:         g2.draw(valueShape);
 675:         g2.translate(-x, -y);
 676:       }
 677:     }
 678:   }
 679: 
 680:   protected void drawScaleValues(final Graphics2D g2, final Rectangle2D area)
 681:   {
 682:     g2.setPaint(getScaleValuePaint());
 683:     g2.setFont(getScaleValueFont());
 684: 
 685:     final int highest = getHighest();
 686:     for (int i = getLowest(); i <= highest; i++)
 687:     {
 688:       final double x = valueToJava2D(i, area);
 689:       final double y = area.getCenterY();
 690:       TextUtilities.drawAlignedString(String.valueOf(i), g2, (float) x,
 691:               (float) y, TextAnchor.CENTER);
 692:     }
 693:   }
 694: 
 695:   protected void drawTickMarks(final Graphics2D g2, final Rectangle2D area)
 696:   {
 697:     g2.setPaint(getTickMarkPaint());
 698:     g2.setStroke(new BasicStroke(0.1f));
 699: 
 700:     final int highest = getHighest();
 701:     for (int i = getLowest(); i <= highest; i++)
 702:     {
 703:       for (int j = 0; j < 10; j++)
 704:       {
 705:         final double xx = valueToJava2D(i + j / 10.0, area);
 706:         final Line2D mark = new Line2D.Double(xx, area.getCenterY() - 2.0, xx,
 707:                 area.getCenterY() + 2.0);
 708:         g2.draw(mark);
 709:       }
 710:     }
 711:     final double xx = valueToJava2D(highest, area);
 712:     final Line2D mark = new Line2D.Double(xx, area.getCenterY() - 2.0, xx,
 713:             area.getCenterY() + 2.0);
 714:     g2.draw(mark);
 715:   }
 716: 
 717:   protected void drawRangeArea(final Rectangle2D area, final Graphics2D g2)
 718:   {
 719:     final Number rangeUpperBound = getRangeUpperBound();
 720:     final Number rangeLowerBound = getRangeLowerBound();
 721:     if (rangeLowerBound == null || rangeUpperBound == null)
 722:     {
 723:       return;
 724:     }
 725:     final double x0 = valueToJava2D(rangeLowerBound.doubleValue(), area);
 726:     final double x1 = valueToJava2D(rangeUpperBound.doubleValue(), area);
 727:     final Rectangle2D rangeArea = new Rectangle2D.Double(x0, area.getY(),
 728:             (x1 - x0), area.getHeight());
 729:     g2.setPaint(getRangePaint());
 730:     g2.fill(rangeArea);
 731:   }
 732: 
 733:   protected void drawBorder(final Graphics2D g2, final Rectangle2D area)
 734:   {
 735:     g2.setStroke(getOutlineStroke());
 736:     g2.setPaint(getBorderPaint());
 737:     g2.draw(area);
 738:   }
 739: 
 740:   /**
 741:    * Translates a data value to Java2D coordinates.
 742:    *
 743:    * @param value      the value.
 744:    * @param area       the area.
 745:    * @param lowerBound the lower bound.
 746:    * @param upperBound the upper bound.
 747:    * @return The Java2D coordinate.
 748:    */
 749:   private double valueToJava2D(final double value,
 750:                                final Rectangle2D area)
 751:   {
 752: 
 753:     final double upperBound = getUpperBound();
 754:     final double lowerBound = getLowerBound();
 755:     return area.getMinX() + ((value - lowerBound) /
 756:             (upperBound - lowerBound) * area .getWidth());
 757: 
 758:   }
 759: 
 760:   private void writeObject(final ObjectOutputStream out)
 761:      throws IOException
 762:   {
 763:     out.defaultWriteObject();
 764:     final SerializerHelper helper = SerializerHelper.getInstance();
 765:     helper.writeObject(scaleValuePaint, out);
 766:     helper.writeObject(rangePaint, out);
 767:     helper.writeObject(fillPaint, out);
 768:     helper.writeObject(outlineStroke, out);
 769:     helper.writeObject(defaultShape, out);
 770:     helper.writeObject(tickMarkPaint, out);
 771:     helper.writeObject(borderPaint, out);
 772:     final int size = shapes.size();
 773:     out.writeInt(size);
 774:     for (int i = 0; i < size; i++)
 775:     {
 776:       final Shape s = shapes.getShape(i);
 777:       helper.writeObject(s, out);
 778:     }
 779:   }
 780: 
 781:  private void readObject(final ObjectInputStream in)
 782:      throws IOException, ClassNotFoundException
 783:  {
 784:    in.defaultReadObject();
 785:    final SerializerHelper helper = SerializerHelper.getInstance();
 786:    scaleValuePaint = (Paint) helper.readObject(in);
 787:    rangePaint = (Paint) helper.readObject(in);
 788:    fillPaint = (Paint) helper.readObject(in);
 789:    outlineStroke = (Stroke) helper.readObject(in);
 790:    defaultShape = (Shape) helper.readObject(in);
 791:    tickMarkPaint = (Paint) helper.readObject(in);
 792:    borderPaint = (Paint) helper.readObject(in);
 793:    shapes = new ShapeList();
 794: 
 795:    final int size = in.readInt();
 796:    for (int i = 0; i < size; i++)
 797:    {
 798:      final Shape s = (Shape) helper.readObject(in);
 799:      shapes.setShape(i, s);
 800:    }
 801: 
 802:  }
 803: 
 804: }