1:
88:
89: package ;
90:
91: import ;
92: import ;
93: import ;
94: import ;
95: import ;
96: import ;
97: import ;
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106:
107: import ;
108: import ;
109: import ;
110: import ;
111: import ;
112: import ;
113: import ;
114: import ;
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120: import ;
121: import ;
122: import ;
123: import ;
124:
125:
128: public class CategoryAxis extends Axis implements Cloneable, Serializable {
129:
130:
131: private static final long serialVersionUID = 5886554608114265863L;
132:
133:
136: public static final double DEFAULT_AXIS_MARGIN = 0.05;
137:
138:
142: public static final double DEFAULT_CATEGORY_MARGIN = 0.20;
143:
144:
145: private double lowerMargin;
146:
147:
148: private double upperMargin;
149:
150:
151: private double categoryMargin;
152:
153:
154: private int maximumCategoryLabelLines;
155:
156:
160: private float maximumCategoryLabelWidthRatio;
161:
162:
163: private int categoryLabelPositionOffset;
164:
165:
169: private CategoryLabelPositions categoryLabelPositions;
170:
171:
172: private Map tickLabelFontMap;
173:
174:
175: private transient Map tickLabelPaintMap;
176:
177:
178: private Map categoryLabelToolTips;
179:
180:
183: public CategoryAxis() {
184: this(null);
185: }
186:
187:
192: public CategoryAxis(String label) {
193:
194: super(label);
195:
196: this.lowerMargin = DEFAULT_AXIS_MARGIN;
197: this.upperMargin = DEFAULT_AXIS_MARGIN;
198: this.categoryMargin = DEFAULT_CATEGORY_MARGIN;
199: this.maximumCategoryLabelLines = 1;
200: this.maximumCategoryLabelWidthRatio = 0.0f;
201:
202: setTickMarksVisible(false);
203:
204: this.categoryLabelPositionOffset = 4;
205: this.categoryLabelPositions = CategoryLabelPositions.STANDARD;
206: this.tickLabelFontMap = new HashMap();
207: this.tickLabelPaintMap = new HashMap();
208: this.categoryLabelToolTips = new HashMap();
209:
210: }
211:
212:
220: public double getLowerMargin() {
221: return this.lowerMargin;
222: }
223:
224:
233: public void setLowerMargin(double margin) {
234: this.lowerMargin = margin;
235: notifyListeners(new AxisChangeEvent(this));
236: }
237:
238:
246: public double getUpperMargin() {
247: return this.upperMargin;
248: }
249:
250:
259: public void setUpperMargin(double margin) {
260: this.upperMargin = margin;
261: notifyListeners(new AxisChangeEvent(this));
262: }
263:
264:
271: public double getCategoryMargin() {
272: return this.categoryMargin;
273: }
274:
275:
285: public void setCategoryMargin(double margin) {
286: this.categoryMargin = margin;
287: notifyListeners(new AxisChangeEvent(this));
288: }
289:
290:
297: public int getMaximumCategoryLabelLines() {
298: return this.maximumCategoryLabelLines;
299: }
300:
301:
309: public void setMaximumCategoryLabelLines(int lines) {
310: this.maximumCategoryLabelLines = lines;
311: notifyListeners(new AxisChangeEvent(this));
312: }
313:
314:
321: public float getMaximumCategoryLabelWidthRatio() {
322: return this.maximumCategoryLabelWidthRatio;
323: }
324:
325:
333: public void setMaximumCategoryLabelWidthRatio(float ratio) {
334: this.maximumCategoryLabelWidthRatio = ratio;
335: notifyListeners(new AxisChangeEvent(this));
336: }
337:
338:
346: public int getCategoryLabelPositionOffset() {
347: return this.categoryLabelPositionOffset;
348: }
349:
350:
358: public void setCategoryLabelPositionOffset(int offset) {
359: this.categoryLabelPositionOffset = offset;
360: notifyListeners(new AxisChangeEvent(this));
361: }
362:
363:
371: public CategoryLabelPositions getCategoryLabelPositions() {
372: return this.categoryLabelPositions;
373: }
374:
375:
383: public void setCategoryLabelPositions(CategoryLabelPositions positions) {
384: if (positions == null) {
385: throw new IllegalArgumentException("Null 'positions' argument.");
386: }
387: this.categoryLabelPositions = positions;
388: notifyListeners(new AxisChangeEvent(this));
389: }
390:
391:
400: public Font getTickLabelFont(Comparable category) {
401: if (category == null) {
402: throw new IllegalArgumentException("Null 'category' argument.");
403: }
404: Font result = (Font) this.tickLabelFontMap.get(category);
405:
406: if (result == null) {
407: result = getTickLabelFont();
408: }
409: return result;
410: }
411:
412:
421: public void setTickLabelFont(Comparable category, Font font) {
422: if (category == null) {
423: throw new IllegalArgumentException("Null 'category' argument.");
424: }
425: if (font == null) {
426: this.tickLabelFontMap.remove(category);
427: }
428: else {
429: this.tickLabelFontMap.put(category, font);
430: }
431: notifyListeners(new AxisChangeEvent(this));
432: }
433:
434:
443: public Paint getTickLabelPaint(Comparable category) {
444: if (category == null) {
445: throw new IllegalArgumentException("Null 'category' argument.");
446: }
447: Paint result = (Paint) this.tickLabelPaintMap.get(category);
448:
449: if (result == null) {
450: result = getTickLabelPaint();
451: }
452: return result;
453: }
454:
455:
464: public void setTickLabelPaint(Comparable category, Paint paint) {
465: if (category == null) {
466: throw new IllegalArgumentException("Null 'category' argument.");
467: }
468: if (paint == null) {
469: this.tickLabelPaintMap.remove(category);
470: }
471: else {
472: this.tickLabelPaintMap.put(category, paint);
473: }
474: notifyListeners(new AxisChangeEvent(this));
475: }
476:
477:
486: public void addCategoryLabelToolTip(Comparable category, String tooltip) {
487: if (category == null) {
488: throw new IllegalArgumentException("Null 'category' argument.");
489: }
490: this.categoryLabelToolTips.put(category, tooltip);
491: notifyListeners(new AxisChangeEvent(this));
492: }
493:
494:
505: public String getCategoryLabelToolTip(Comparable category) {
506: if (category == null) {
507: throw new IllegalArgumentException("Null 'category' argument.");
508: }
509: return (String) this.categoryLabelToolTips.get(category);
510: }
511:
512:
521: public void removeCategoryLabelToolTip(Comparable category) {
522: if (category == null) {
523: throw new IllegalArgumentException("Null 'category' argument.");
524: }
525: this.categoryLabelToolTips.remove(category);
526: notifyListeners(new AxisChangeEvent(this));
527: }
528:
529:
536: public void clearCategoryLabelToolTips() {
537: this.categoryLabelToolTips.clear();
538: notifyListeners(new AxisChangeEvent(this));
539: }
540:
541:
552: public double getCategoryJava2DCoordinate(CategoryAnchor anchor,
553: int category,
554: int categoryCount,
555: Rectangle2D area,
556: RectangleEdge edge) {
557:
558: double result = 0.0;
559: if (anchor == CategoryAnchor.START) {
560: result = getCategoryStart(category, categoryCount, area, edge);
561: }
562: else if (anchor == CategoryAnchor.MIDDLE) {
563: result = getCategoryMiddle(category, categoryCount, area, edge);
564: }
565: else if (anchor == CategoryAnchor.END) {
566: result = getCategoryEnd(category, categoryCount, area, edge);
567: }
568: return result;
569:
570: }
571:
572:
585: public double getCategoryStart(int category, int categoryCount,
586: Rectangle2D area,
587: RectangleEdge edge) {
588:
589: double result = 0.0;
590: if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) {
591: result = area.getX() + area.getWidth() * getLowerMargin();
592: }
593: else if ((edge == RectangleEdge.LEFT)
594: || (edge == RectangleEdge.RIGHT)) {
595: result = area.getMinY() + area.getHeight() * getLowerMargin();
596: }
597:
598: double categorySize = calculateCategorySize(categoryCount, area, edge);
599: double categoryGapWidth = calculateCategoryGapSize(categoryCount, area,
600: edge);
601:
602: result = result + category * (categorySize + categoryGapWidth);
603: return result;
604:
605: }
606:
607:
620: public double getCategoryMiddle(int category, int categoryCount,
621: Rectangle2D area, RectangleEdge edge) {
622:
623: return getCategoryStart(category, categoryCount, area, edge)
624: + calculateCategorySize(categoryCount, area, edge) / 2;
625:
626: }
627:
628:
641: public double getCategoryEnd(int category, int categoryCount,
642: Rectangle2D area, RectangleEdge edge) {
643:
644: return getCategoryStart(category, categoryCount, area, edge)
645: + calculateCategorySize(categoryCount, area, edge);
646:
647: }
648:
649:
659: protected double calculateCategorySize(int categoryCount, Rectangle2D area,
660: RectangleEdge edge) {
661:
662: double result = 0.0;
663: double available = 0.0;
664:
665: if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) {
666: available = area.getWidth();
667: }
668: else if ((edge == RectangleEdge.LEFT)
669: || (edge == RectangleEdge.RIGHT)) {
670: available = area.getHeight();
671: }
672: if (categoryCount > 1) {
673: result = available * (1 - getLowerMargin() - getUpperMargin()
674: - getCategoryMargin());
675: result = result / categoryCount;
676: }
677: else {
678: result = available * (1 - getLowerMargin() - getUpperMargin());
679: }
680: return result;
681:
682: }
683:
684:
694: protected double calculateCategoryGapSize(int categoryCount,
695: Rectangle2D area,
696: RectangleEdge edge) {
697:
698: double result = 0.0;
699: double available = 0.0;
700:
701: if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) {
702: available = area.getWidth();
703: }
704: else if ((edge == RectangleEdge.LEFT)
705: || (edge == RectangleEdge.RIGHT)) {
706: available = area.getHeight();
707: }
708:
709: if (categoryCount > 1) {
710: result = available * getCategoryMargin() / (categoryCount - 1);
711: }
712:
713: return result;
714:
715: }
716:
717:
728: public AxisSpace reserveSpace(Graphics2D g2, Plot plot,
729: Rectangle2D plotArea,
730: RectangleEdge edge, AxisSpace space) {
731:
732:
733: if (space == null) {
734: space = new AxisSpace();
735: }
736:
737:
738: if (!isVisible()) {
739: return space;
740: }
741:
742:
743: double tickLabelHeight = 0.0;
744: double tickLabelWidth = 0.0;
745: if (isTickLabelsVisible()) {
746: g2.setFont(getTickLabelFont());
747: AxisState state = new AxisState();
748:
749: refreshTicks(g2, state, plotArea, edge);
750: if (edge == RectangleEdge.TOP) {
751: tickLabelHeight = state.getMax();
752: }
753: else if (edge == RectangleEdge.BOTTOM) {
754: tickLabelHeight = state.getMax();
755: }
756: else if (edge == RectangleEdge.LEFT) {
757: tickLabelWidth = state.getMax();
758: }
759: else if (edge == RectangleEdge.RIGHT) {
760: tickLabelWidth = state.getMax();
761: }
762: }
763:
764:
765: Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge);
766: double labelHeight = 0.0;
767: double labelWidth = 0.0;
768: if (RectangleEdge.isTopOrBottom(edge)) {
769: labelHeight = labelEnclosure.getHeight();
770: space.add(labelHeight + tickLabelHeight
771: + this.categoryLabelPositionOffset, edge);
772: }
773: else if (RectangleEdge.isLeftOrRight(edge)) {
774: labelWidth = labelEnclosure.getWidth();
775: space.add(labelWidth + tickLabelWidth
776: + this.categoryLabelPositionOffset, edge);
777: }
778: return space;
779:
780: }
781:
782:
785: public void configure() {
786:
787: }
788:
789:
805: public AxisState draw(Graphics2D g2,
806: double cursor,
807: Rectangle2D plotArea,
808: Rectangle2D dataArea,
809: RectangleEdge edge,
810: PlotRenderingInfo plotState) {
811:
812:
813: if (!isVisible()) {
814: return new AxisState(cursor);
815: }
816:
817: if (isAxisLineVisible()) {
818: drawAxisLine(g2, cursor, dataArea, edge);
819: }
820:
821:
822: AxisState state = new AxisState(cursor);
823: state = drawCategoryLabels(g2, plotArea, dataArea, edge, state,
824: plotState);
825: state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state);
826:
827: return state;
828:
829: }
830:
831:
847: protected AxisState drawCategoryLabels(Graphics2D g2,
848: Rectangle2D dataArea,
849: RectangleEdge edge,
850: AxisState state,
851: PlotRenderingInfo plotState) {
852:
853:
854:
855: return drawCategoryLabels(g2, dataArea, dataArea, edge, state,
856: plotState);
857: }
858:
859:
873: protected AxisState drawCategoryLabels(Graphics2D g2,
874: Rectangle2D plotArea,
875: Rectangle2D dataArea,
876: RectangleEdge edge,
877: AxisState state,
878: PlotRenderingInfo plotState) {
879:
880: if (state == null) {
881: throw new IllegalArgumentException("Null 'state' argument.");
882: }
883:
884: if (isTickLabelsVisible()) {
885: List ticks = refreshTicks(g2, state, plotArea, edge);
886: state.setTicks(ticks);
887:
888: int categoryIndex = 0;
889: Iterator iterator = ticks.iterator();
890: while (iterator.hasNext()) {
891:
892: CategoryTick tick = (CategoryTick) iterator.next();
893: g2.setFont(getTickLabelFont(tick.getCategory()));
894: g2.setPaint(getTickLabelPaint(tick.getCategory()));
895:
896: CategoryLabelPosition position
897: = this.categoryLabelPositions.getLabelPosition(edge);
898: double x0 = 0.0;
899: double x1 = 0.0;
900: double y0 = 0.0;
901: double y1 = 0.0;
902: if (edge == RectangleEdge.TOP) {
903: x0 = getCategoryStart(categoryIndex, ticks.size(),
904: dataArea, edge);
905: x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,
906: edge);
907: y1 = state.getCursor() - this.categoryLabelPositionOffset;
908: y0 = y1 - state.getMax();
909: }
910: else if (edge == RectangleEdge.BOTTOM) {
911: x0 = getCategoryStart(categoryIndex, ticks.size(),
912: dataArea, edge);
913: x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,
914: edge);
915: y0 = state.getCursor() + this.categoryLabelPositionOffset;
916: y1 = y0 + state.getMax();
917: }
918: else if (edge == RectangleEdge.LEFT) {
919: y0 = getCategoryStart(categoryIndex, ticks.size(),
920: dataArea, edge);
921: y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,
922: edge);
923: x1 = state.getCursor() - this.categoryLabelPositionOffset;
924: x0 = x1 - state.getMax();
925: }
926: else if (edge == RectangleEdge.RIGHT) {
927: y0 = getCategoryStart(categoryIndex, ticks.size(),
928: dataArea, edge);
929: y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,
930: edge);
931: x0 = state.getCursor() + this.categoryLabelPositionOffset;
932: x1 = x0 - state.getMax();
933: }
934: Rectangle2D area = new Rectangle2D.Double(x0, y0, (x1 - x0),
935: (y1 - y0));
936: Point2D anchorPoint = RectangleAnchor.coordinates(area,
937: position.getCategoryAnchor());
938: TextBlock block = tick.getLabel();
939: block.draw(g2, (float) anchorPoint.getX(),
940: (float) anchorPoint.getY(), position.getLabelAnchor(),
941: (float) anchorPoint.getX(), (float) anchorPoint.getY(),
942: position.getAngle());
943: Shape bounds = block.calculateBounds(g2,
944: (float) anchorPoint.getX(), (float) anchorPoint.getY(),
945: position.getLabelAnchor(), (float) anchorPoint.getX(),
946: (float) anchorPoint.getY(), position.getAngle());
947: if (plotState != null && plotState.getOwner() != null) {
948: EntityCollection entities
949: = plotState.getOwner().getEntityCollection();
950: if (entities != null) {
951: String tooltip = getCategoryLabelToolTip(
952: tick.getCategory());
953: entities.add(new CategoryLabelEntity(tick.getCategory(),
954: bounds, tooltip, null));
955: }
956: }
957: categoryIndex++;
958: }
959:
960: if (edge.equals(RectangleEdge.TOP)) {
961: double h = state.getMax() + this.categoryLabelPositionOffset;
962: state.cursorUp(h);
963: }
964: else if (edge.equals(RectangleEdge.BOTTOM)) {
965: double h = state.getMax() + this.categoryLabelPositionOffset;
966: state.cursorDown(h);
967: }
968: else if (edge == RectangleEdge.LEFT) {
969: double w = state.getMax() + this.categoryLabelPositionOffset;
970: state.cursorLeft(w);
971: }
972: else if (edge == RectangleEdge.RIGHT) {
973: double w = state.getMax() + this.categoryLabelPositionOffset;
974: state.cursorRight(w);
975: }
976: }
977: return state;
978: }
979:
980:
990: public List refreshTicks(Graphics2D g2,
991: AxisState state,
992: Rectangle2D dataArea,
993: RectangleEdge edge) {
994:
995: List ticks = new java.util.ArrayList();
996:
997:
998: if (dataArea.getHeight() <= 0.0 || dataArea.getWidth() < 0.0) {
999: return ticks;
1000: }
1001:
1002: CategoryPlot plot = (CategoryPlot) getPlot();
1003: List categories = plot.getCategoriesForAxis(this);
1004: double max = 0.0;
1005:
1006: if (categories != null) {
1007: CategoryLabelPosition position
1008: = this.categoryLabelPositions.getLabelPosition(edge);
1009: float r = this.maximumCategoryLabelWidthRatio;
1010: if (r <= 0.0) {
1011: r = position.getWidthRatio();
1012: }
1013:
1014: float l = 0.0f;
1015: if (position.getWidthType() == CategoryLabelWidthType.CATEGORY) {
1016: l = (float) calculateCategorySize(categories.size(), dataArea,
1017: edge);
1018: }
1019: else {
1020: if (RectangleEdge.isLeftOrRight(edge)) {
1021: l = (float) dataArea.getWidth();
1022: }
1023: else {
1024: l = (float) dataArea.getHeight();
1025: }
1026: }
1027: int categoryIndex = 0;
1028: Iterator iterator = categories.iterator();
1029: while (iterator.hasNext()) {
1030: Comparable category = (Comparable) iterator.next();
1031: TextBlock label = createLabel(category, l * r, edge, g2);
1032: if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) {
1033: max = Math.max(max, calculateTextBlockHeight(label,
1034: position, g2));
1035: }
1036: else if (edge == RectangleEdge.LEFT
1037: || edge == RectangleEdge.RIGHT) {
1038: max = Math.max(max, calculateTextBlockWidth(label,
1039: position, g2));
1040: }
1041: Tick tick = new CategoryTick(category, label,
1042: position.getLabelAnchor(), position.getRotationAnchor(),
1043: position.getAngle());
1044: ticks.add(tick);
1045: categoryIndex = categoryIndex + 1;
1046: }
1047: }
1048: state.setMax(max);
1049: return ticks;
1050:
1051: }
1052:
1053:
1063: protected TextBlock createLabel(Comparable category, float width,
1064: RectangleEdge edge, Graphics2D g2) {
1065: TextBlock label = TextUtilities.createTextBlock(category.toString(),
1066: getTickLabelFont(category), getTickLabelPaint(category), width,
1067: this.maximumCategoryLabelLines, new G2TextMeasurer(g2));
1068: return label;
1069: }
1070:
1071:
1080: protected double calculateTextBlockWidth(TextBlock block,
1081: CategoryLabelPosition position,
1082: Graphics2D g2) {
1083:
1084: RectangleInsets insets = getTickLabelInsets();
1085: Size2D size = block.calculateDimensions(g2);
1086: Rectangle2D box = new Rectangle2D.Double(0.0, 0.0, size.getWidth(),
1087: size.getHeight());
1088: Shape rotatedBox = ShapeUtilities.rotateShape(box, position.getAngle(),
1089: 0.0f, 0.0f);
1090: double w = rotatedBox.getBounds2D().getWidth() + insets.getTop()
1091: + insets.getBottom();
1092: return w;
1093:
1094: }
1095:
1096:
1105: protected double calculateTextBlockHeight(TextBlock block,
1106: CategoryLabelPosition position,
1107: Graphics2D g2) {
1108:
1109: RectangleInsets insets = getTickLabelInsets();
1110: Size2D size = block.calculateDimensions(g2);
1111: Rectangle2D box = new Rectangle2D.Double(0.0, 0.0, size.getWidth(),
1112: size.getHeight());
1113: Shape rotatedBox = ShapeUtilities.rotateShape(box, position.getAngle(),
1114: 0.0f, 0.0f);
1115: double h = rotatedBox.getBounds2D().getHeight()
1116: + insets.getTop() + insets.getBottom();
1117: return h;
1118:
1119: }
1120:
1121:
1129: public Object clone() throws CloneNotSupportedException {
1130: CategoryAxis clone = (CategoryAxis) super.clone();
1131: clone.tickLabelFontMap = new HashMap(this.tickLabelFontMap);
1132: clone.tickLabelPaintMap = new HashMap(this.tickLabelPaintMap);
1133: clone.categoryLabelToolTips = new HashMap(this.categoryLabelToolTips);
1134: return clone;
1135: }
1136:
1137:
1144: public boolean equals(Object obj) {
1145: if (obj == this) {
1146: return true;
1147: }
1148: if (!(obj instanceof CategoryAxis)) {
1149: return false;
1150: }
1151: if (!super.equals(obj)) {
1152: return false;
1153: }
1154: CategoryAxis that = (CategoryAxis) obj;
1155: if (that.lowerMargin != this.lowerMargin) {
1156: return false;
1157: }
1158: if (that.upperMargin != this.upperMargin) {
1159: return false;
1160: }
1161: if (that.categoryMargin != this.categoryMargin) {
1162: return false;
1163: }
1164: if (that.maximumCategoryLabelWidthRatio
1165: != this.maximumCategoryLabelWidthRatio) {
1166: return false;
1167: }
1168: if (that.categoryLabelPositionOffset
1169: != this.categoryLabelPositionOffset) {
1170: return false;
1171: }
1172: if (!ObjectUtilities.equal(that.categoryLabelPositions,
1173: this.categoryLabelPositions)) {
1174: return false;
1175: }
1176: if (!ObjectUtilities.equal(that.categoryLabelToolTips,
1177: this.categoryLabelToolTips)) {
1178: return false;
1179: }
1180: if (!ObjectUtilities.equal(this.tickLabelFontMap,
1181: that.tickLabelFontMap)) {
1182: return false;
1183: }
1184: if (!equalPaintMaps(this.tickLabelPaintMap, that.tickLabelPaintMap)) {
1185: return false;
1186: }
1187: return true;
1188: }
1189:
1190:
1195: public int hashCode() {
1196: if (getLabel() != null) {
1197: return getLabel().hashCode();
1198: }
1199: else {
1200: return 0;
1201: }
1202: }
1203:
1204:
1211: private void writeObject(ObjectOutputStream stream) throws IOException {
1212: stream.defaultWriteObject();
1213: writePaintMap(this.tickLabelPaintMap, stream);
1214: }
1215:
1216:
1224: private void readObject(ObjectInputStream stream)
1225: throws IOException, ClassNotFoundException {
1226: stream.defaultReadObject();
1227: this.tickLabelPaintMap = readPaintMap(stream);
1228: }
1229:
1230:
1243: private Map readPaintMap(ObjectInputStream in)
1244: throws IOException, ClassNotFoundException {
1245: boolean isNull = in.readBoolean();
1246: if (isNull) {
1247: return null;
1248: }
1249: Map result = new HashMap();
1250: int count = in.readInt();
1251: for (int i = 0; i < count; i++) {
1252: Comparable category = (Comparable) in.readObject();
1253: Paint paint = SerialUtilities.readPaint(in);
1254: result.put(category, paint);
1255: }
1256: return result;
1257: }
1258:
1259:
1270: private void writePaintMap(Map map, ObjectOutputStream out)
1271: throws IOException {
1272: if (map == null) {
1273: out.writeBoolean(true);
1274: }
1275: else {
1276: out.writeBoolean(false);
1277: Set keys = map.keySet();
1278: int count = keys.size();
1279: out.writeInt(count);
1280: Iterator iterator = keys.iterator();
1281: while (iterator.hasNext()) {
1282: Comparable key = (Comparable) iterator.next();
1283: out.writeObject(key);
1284: SerialUtilities.writePaint((Paint) map.get(key), out);
1285: }
1286: }
1287: }
1288:
1289:
1298: private boolean equalPaintMaps(Map map1, Map map2) {
1299: if (map1.size() != map2.size()) {
1300: return false;
1301: }
1302: Set keys = map1.keySet();
1303: Iterator iterator = keys.iterator();
1304: while (iterator.hasNext()) {
1305: Comparable key = (Comparable) iterator.next();
1306: Paint p1 = (Paint) map1.get(key);
1307: Paint p2 = (Paint) map2.get(key);
1308: if (!PaintUtilities.equal(p1, p2)) {
1309: return false;
1310: }
1311: }
1312: return true;
1313: }
1314:
1315: }