1 package org.xpilot.jxpmap; 2 3 import java.awt.AWTEvent; 4 import java.awt.BasicStroke; 5 import java.awt.Color; 6 import java.awt.Graphics2D; 7 import java.awt.Point; 8 import java.awt.Polygon; 9 import java.awt.Rectangle; 10 import java.awt.Shape; 11 import java.awt.Stroke; 12 import java.awt.TexturePaint; 13 import java.awt.RenderingHints; 14 import java.awt.event.InputEvent; 15 import java.awt.event.MouseEvent; 16 import java.awt.geom.AffineTransform; 17 import java.awt.geom.Line2D; 18 import java.awt.image.BufferedImage; 19 import java.io.IOException; 20 import java.io.PrintWriter; 21 import java.util.ArrayList; 22 import java.util.Iterator; 23 import java.util.Map; 24 import java.util.HashMap; 25 26 27 public class MapPolygon extends MapObject { 28 29 protected Polygon polygon; 30 protected PolygonStyle currentStyle; 31 protected ArrayList edgeStyles; 32 protected Map styles; 33 deepClone(Map context)34 public Object deepClone (Map context) { 35 36 MapPolygon clone = (MapPolygon)super.deepClone(context); 37 38 clone.polygon = new Polygon(polygon.xpoints, 39 polygon.ypoints, 40 polygon.npoints); 41 42 if (styles != null) { 43 Map m = new HashMap(); 44 for (Iterator i = styles.keySet().iterator(); i.hasNext();) { 45 String key = (String)i.next(); 46 m.put(key, ((PolygonStyle)styles.get(key)).deepClone(context)); 47 } 48 clone.styles = m; 49 } 50 51 if (edgeStyles != null) { 52 ArrayList l = new ArrayList(); 53 for (Iterator i = edgeStyles.iterator(); i.hasNext();) 54 l.add(((LineStyle)i.next()).deepClone(context)); 55 clone.edgeStyles = l; 56 } 57 58 return clone; 59 } 60 copy()61 public MapObject copy() { 62 MapPolygon copy = (MapPolygon)super.copy(); 63 copy.polygon = new Polygon(polygon.xpoints, 64 polygon.ypoints, 65 polygon.npoints); 66 if (styles != null) 67 copy.styles = new HashMap(styles); 68 if (edgeStyles != null) 69 copy.edgeStyles = new ArrayList(edgeStyles); 70 return copy; 71 } 72 MapPolygon()73 protected MapPolygon () {} 74 MapPolygon(Polygon p, PolygonStyle defStyle)75 public MapPolygon(Polygon p, PolygonStyle defStyle) { 76 this.polygon = p; 77 setDefaultStyle(defStyle); 78 } 79 MapPolygon(Polygon p, Map styles, ArrayList edgeStyles)80 public MapPolygon (Polygon p, Map styles, ArrayList edgeStyles) { 81 this.polygon = p; 82 this.styles = styles; 83 this.edgeStyles = edgeStyles; 84 } 85 86 getCreateHandler(Runnable r)87 public CanvasEventHandler getCreateHandler (Runnable r) { 88 return new CreateHandler(r); 89 } 90 createPopup()91 protected MapObjectPopup createPopup() { 92 return new PolygonPopup(this); 93 } 94 getPolygon()95 public Polygon getPolygon() { 96 return polygon; 97 } 98 getStyles()99 public Map getStyles() { 100 return styles; 101 } 102 setStyles(Map m)103 public void setStyles(Map m) { 104 this.styles = m; 105 } 106 getDefaultStyle()107 public PolygonStyle getDefaultStyle() { 108 return getStyle("default"); 109 } 110 setDefaultStyle(PolygonStyle style)111 public void setDefaultStyle(PolygonStyle style) { 112 if (style == null) throw new NullPointerException(); 113 if (styles == null) styles = new HashMap(); 114 styles.put("default", style); 115 } 116 getStyle(String name)117 public PolygonStyle getStyle(String name) { 118 if (styles == null) return null; 119 return (PolygonStyle)styles.get(name); 120 } 121 getCurrentStyle()122 public PolygonStyle getCurrentStyle() { 123 if (currentStyle == null) 124 currentStyle = getDefaultStyle(); 125 return currentStyle; 126 } 127 setCurrentStyle(PolygonStyle style)128 public void setCurrentStyle(PolygonStyle style) { 129 currentStyle = style; 130 } 131 getBounds()132 public Rectangle getBounds () { 133 return polygon.getBounds(); 134 } 135 contains(Point p)136 public boolean contains (Point p) { 137 return polygon.contains(p); 138 } 139 140 getZOrder()141 public int getZOrder () { 142 return 20; 143 } 144 getPreviewShape()145 public Shape getPreviewShape () { 146 return polygon; 147 } 148 149 moveTo(int x, int y)150 public void moveTo (int x, int y) { 151 Rectangle r = getBounds(); 152 polygon.translate(x - r.x, y - r.y); 153 } 154 155 rotate(double angle)156 public void rotate (double angle) { 157 double cx = getBounds().getCenterX(); 158 double cy = getBounds().getCenterY(); 159 AffineTransform at = AffineTransform.getTranslateInstance(cx, cy); 160 at.rotate(angle); 161 at.translate(-cx, -cy); 162 Point p = new Point(); 163 for (int i = 0; i < polygon.npoints; i++) { 164 p.x = polygon.xpoints[i]; 165 p.y = polygon.ypoints[i]; 166 at.transform(p, p); 167 polygon.xpoints[i] = p.x; 168 polygon.ypoints[i] = p.y; 169 } 170 } 171 172 isCounterClockwise()173 public boolean isCounterClockwise () { 174 175 long xi,yi,xj,yj,area = 0; 176 int i, j; 177 178 for (i = polygon.npoints - 1, j = 0; j < polygon.npoints; i = j, j++) { 179 xi = polygon.xpoints[i]; 180 xj = polygon.xpoints[j]; 181 yi = polygon.ypoints[i]; 182 yj = polygon.ypoints[j]; 183 area += xi * yj - xj * yi; 184 } 185 186 return (area > 0); 187 } 188 189 setEdgeStyle(int index, LineStyle style)190 public void setEdgeStyle (int index, LineStyle style) { 191 if (edgeStyles == null) { 192 if (style == null) return; 193 edgeStyles = new ArrayList(polygon.npoints); 194 for (int i = 0; i < polygon.npoints; i++) 195 edgeStyles.add(null); 196 } 197 edgeStyles.set(index, style); 198 } 199 200 getEdgeStyle(int index)201 public LineStyle getEdgeStyle (int index) { 202 if (edgeStyles == null) return getDefaultStyle().getDefaultEdgeStyle(); 203 return (LineStyle)edgeStyles.get(index); 204 } 205 206 printXml(PrintWriter out)207 public void printXml (PrintWriter out) throws IOException { 208 209 if (polygon.npoints < 2) return; 210 211 out.print("<Polygon x=\""); 212 out.print(polygon.xpoints[0]); 213 out.print("\" y=\""); 214 out.print(polygon.ypoints[0]); 215 out.print("\" style=\""); 216 out.print(getStyle("default").getId()); 217 out.println("\">"); 218 219 for (Iterator i = getStyles().entrySet().iterator(); i.hasNext();) { 220 Map.Entry e = (Map.Entry)i.next(); 221 if ("default".equals(e.getKey())) continue; 222 if ("".equals(e.getValue())) continue; 223 out.print("<Style state=\""); 224 out.print(e.getKey()); 225 out.print("\" id=\""); 226 out.print(((PolygonStyle)e.getValue()).getId()); 227 out.println("\"/>"); 228 } 229 230 LineStyle cls = null; 231 232 if (isCounterClockwise()) { 233 for (int i = 1; i <= polygon.npoints; i++) { 234 int x = polygon.xpoints[i % polygon.npoints] - 235 polygon.xpoints[i - 1]; 236 int y = polygon.ypoints[i % polygon.npoints] - 237 polygon.ypoints[i - 1]; 238 if (x != 0 || y != 0) { 239 out.print("<Offset x=\""); 240 out.print(x); 241 out.print("\" y=\""); 242 out.print(y); 243 if (edgeStyles != null) { 244 LineStyle ls = getEdgeStyle(i - 1); 245 if (ls != cls) { 246 out.print("\" style=\""); 247 out.print((ls != null) ? ls.getId() : 248 getDefaultStyle().getDefaultEdgeStyle().getId()); 249 cls = ls; 250 } 251 } 252 out.println("\"/>"); 253 } 254 } 255 } else { 256 for (int i = polygon.npoints; i > 0; i--) { 257 int x = polygon.xpoints[i - 1] - 258 polygon.xpoints[i % polygon.npoints]; 259 int y = polygon.ypoints[i - 1] - 260 polygon.ypoints[i % polygon.npoints]; 261 if (x != 0 || y != 0) { 262 out.print("<Offset x=\""); 263 out.print(x); 264 out.print("\" y=\""); 265 out.print(y); 266 if (edgeStyles != null) { 267 LineStyle ls = getEdgeStyle(i - 1); 268 if (ls != cls) { 269 out.print("\" style=\""); 270 out.print((ls != null) ? ls.getId() : 271 getDefaultStyle().getDefaultEdgeStyle().getId()); 272 cls = ls; 273 } 274 } 275 out.println("\"/>"); 276 } 277 } 278 } 279 280 out.println("</Polygon>"); 281 282 } 283 284 paint(Graphics2D g, float scale)285 public void paint (Graphics2D g, float scale) { 286 287 PolygonStyle style = getCurrentStyle(); 288 if (!style.isVisible()) return; 289 290 Polygon p = polygon; 291 boolean fastRendering = 292 g.getRenderingHint(RenderingHints.KEY_RENDERING) 293 == RenderingHints.VALUE_RENDER_SPEED; 294 295 if (!fastRendering) { 296 if (style.getFillStyle() == PolygonStyle.FILL_COLOR) { 297 g.setColor(style.getColor()); 298 g.fillPolygon(p); 299 300 } else if (style.getFillStyle() == PolygonStyle.FILL_TEXTURED) { 301 BufferedImage img = style.getTexture().getImage(); 302 if (img != null) { 303 Rectangle b = polygon.getBounds(); 304 g.setPaint(new TexturePaint(img, new Rectangle( 305 b.x, b.y + b.height, 306 img.getWidth() * 64, -img.getHeight() * 64))); 307 g.fill(p); 308 } 309 } 310 } 311 312 if (edgeStyles == null) { 313 LineStyle def = style.getDefaultEdgeStyle(); 314 if (def.getStyle() != LineStyle.STYLE_HIDDEN) { 315 g.setColor(def.getColor()); 316 g.setStroke(def.getStroke(scale)); 317 g.draw(p); 318 } else if (fastRendering) { 319 g.setColor(Color.darkGray); 320 g.draw(p); 321 } 322 } else { 323 for (int i = 0; i < p.npoints;) { 324 int begin = i; 325 LineStyle ls = getEdgeStyle(i++); 326 327 while (i < p.npoints && getEdgeStyle(i) == ls) i++; 328 if (ls == null) ls = style.getDefaultEdgeStyle(); 329 if (i == p.npoints && 330 ls == style.getDefaultEdgeStyle() && 331 begin == 0) edgeStyles = null; 332 333 if (ls.getStyle() != LineStyle.STYLE_HIDDEN) { 334 g.setColor(ls.getColor()); 335 g.setStroke(ls.getStroke(scale)); 336 337 int nump = i - begin + 1; 338 int[] xp = new int[nump]; 339 int[] yp = new int[nump]; 340 int aclen = nump; 341 342 if (begin + nump > p.npoints) { 343 aclen--; 344 xp[aclen] = p.xpoints[0]; 345 yp[aclen] = p.ypoints[0]; 346 } 347 348 System.arraycopy(p.xpoints, begin, xp, 0, aclen); 349 System.arraycopy(p.ypoints, begin, yp, 0, aclen); 350 351 g.drawPolyline(xp, yp, nump); 352 } 353 } 354 } 355 356 if (isSelected()) { 357 //g.setStroke(SELECTED_STROKE); 358 g.setColor(Color.white); 359 int sz = (int)(5 / scale); 360 int off = sz / 2; 361 for (int i = 0; i < p.npoints; i++) { 362 /* 363 g.drawArc( 364 p.xpoints[i] - off, 365 p.ypoints[i] - off, 366 sz, sz, 0, 360); 367 */ 368 g.fillRect( 369 p.xpoints[i] - off, 370 p.ypoints[i] - off, 371 sz, sz); 372 } 373 } 374 } 375 376 getPropertyEditor(MapCanvas canvas)377 public EditorPanel getPropertyEditor (MapCanvas canvas) { 378 return new PolygonPropertyEditor(canvas, this); 379 } 380 getRotateHandler()381 public CanvasEventHandler getRotateHandler() { 382 return new RotateHandler(); 383 } 384 385 checkAwtEvent(MapCanvas canvas, AWTEvent evt)386 public boolean checkAwtEvent (MapCanvas canvas, AWTEvent evt) { 387 388 if (canvas.getMode() != MapCanvas.MODE_ERASE 389 && canvas.getMode() != MapCanvas.MODE_EDIT) 390 return super.checkAwtEvent(canvas, evt); 391 392 if (evt.getID() == MouseEvent.MOUSE_PRESSED 393 || evt.getID() == MouseEvent.MOUSE_CLICKED) { 394 395 MouseEvent me = (MouseEvent)evt; 396 Rectangle b = getBounds(); 397 Point p = me.getPoint(); 398 Polygon pl = polygon; 399 Rectangle larger = 400 new Rectangle(b.x - 20 * 64, 401 b.y - 20 * 64, 402 b.width + 40 * 64, 403 b.height + 40 * 64); 404 Point[] wraps = canvas.computeWraps(larger, p); 405 if (wraps.length == 0) return false; 406 407 double thresholdSq = 100 / (canvas.getScale() * canvas.getScale()); 408 if ((me.getModifiers() & InputEvent.BUTTON1_MASK) != 0 409 && me.getID() == MouseEvent.MOUSE_PRESSED) { 410 for (int pi = 0; pi < wraps.length; pi++) { 411 Point wp = wraps[pi]; 412 for (int i = 0; i < pl.npoints; i++) { 413 if (Point.distanceSq 414 (wp.x, wp.y, pl.xpoints[i], 415 pl.ypoints[i]) < thresholdSq) { 416 417 canvas.setSelectedObject(this); 418 if (canvas.getMode() == MapCanvas.MODE_ERASE) { 419 canvas.removePolygonPoint(this, i); 420 } else if (canvas.getMode() == MapCanvas.MODE_EDIT) { 421 canvas.setCanvasEventHandler 422 (new PolygonPointMoveHandler(me, i)); 423 } 424 return true; 425 } 426 } 427 } 428 } 429 430 if (canvas.getMode() == MapCanvas.MODE_EDIT) { 431 432 for (int pi = 0; pi < wraps.length; pi++) { 433 Point wp = wraps[pi]; 434 for (int i = 0; i < pl.npoints; i++) { 435 int ni = (i + 1) % pl.npoints; 436 if (Line2D.ptSegDistSq(pl.xpoints[i], 437 pl.ypoints[i], 438 pl.xpoints[ni], 439 pl.ypoints[ni], 440 wp.x, wp.y) < thresholdSq) { 441 442 canvas.setSelectedObject(this); 443 if ((me.getModifiers() & 444 InputEvent.BUTTON1_MASK) != 0) { 445 446 if (me.getID() == MouseEvent.MOUSE_PRESSED) { 447 canvas.insertPolygonPoint(this, i + 1, p); 448 canvas.setCanvasEventHandler 449 (new PolygonPointMoveHandler 450 (me, i + 1)); 451 return true; 452 } 453 454 } else { 455 456 if (me.getID() == MouseEvent.MOUSE_CLICKED) { 457 EditorDialog.show 458 (canvas, new EdgePropertyEditor 459 (canvas, this, i), 460 true, 461 EditorDialog.OK_CANCEL); 462 return true; 463 } 464 } 465 } 466 } 467 } 468 } 469 } 470 471 return super.checkAwtEvent(canvas, evt); 472 } 473 474 removePoint(int i)475 public void removePoint (int i) { 476 477 int pc = polygon.npoints - 1; 478 int[] xps = remove(polygon.xpoints, i); 479 int[] yps = remove(polygon.ypoints, i); 480 481 polygon = new Polygon(xps, yps, pc); 482 483 if (edgeStyles != null) { 484 if (i == 0) edgeStyles.remove(edgeStyles.size() - 1); 485 else edgeStyles.remove(i - 1); 486 } 487 } 488 489 getNumPoints()490 public int getNumPoints() { 491 return polygon.npoints; 492 } 493 494 getPoint(int i)495 public Point getPoint (int i) { 496 if (i < 0) throw new IllegalArgumentException("i = " + i); 497 return new Point(polygon.xpoints[i], polygon.ypoints[i]); 498 } 499 setPoint(int i, int x, int y)500 public void setPoint (int i, int x, int y) { 501 if (i < 0 || i >= polygon.npoints) 502 throw new IllegalArgumentException("i = " + i); 503 polygon.xpoints[i] = x; 504 polygon.ypoints[i] = y; 505 polygon.invalidate(); 506 } 507 insertPoint(int i, Point p)508 public void insertPoint (int i, Point p) { 509 if (i < 0) throw new IllegalArgumentException("i = " + i); 510 int pc = polygon.npoints + 1; 511 int xps[] = insert(p.x, polygon.xpoints, i); 512 int yps[] = insert(p.y, polygon.ypoints, i); 513 514 polygon = new Polygon(xps, yps, pc); 515 516 if (edgeStyles != null) { 517 LineStyle es = getEdgeStyle(i - 1); 518 edgeStyles.add(i - 1, es); 519 } 520 } 521 522 remove(int a[], int p)523 private static int[] remove (int a[], int p) { 524 525 if (p >= a.length || p < 0) 526 throw new ArrayIndexOutOfBoundsException(p); 527 528 int rv[] = new int[a.length - 1]; 529 if (p > 0) System.arraycopy(a, 0, rv, 0, p); 530 if (p < rv.length) System.arraycopy(a, p + 1, rv, p, rv.length - p); 531 532 return rv; 533 } 534 535 insert(int i, int a[], int p)536 private static int[] insert (int i, int a[], int p) { 537 538 if (p > a.length || p < 0) throw new ArrayIndexOutOfBoundsException(p); 539 540 int rv[] = new int[a.length + 1]; 541 System.arraycopy(a, 0, rv, 0, p); 542 rv[p] = i; 543 if (p < a.length) System.arraycopy(a, p, rv, p + 1, a.length - p); 544 545 return rv; 546 } 547 548 549 private class CreateHandler extends CanvasEventAdapter { 550 551 private Runnable cmd; 552 private Polygon poly; 553 private Point latest, first; 554 private Stroke stroke; 555 private boolean remove; 556 557 CreateHandler(Runnable cmd)558 public CreateHandler (Runnable cmd) { 559 this.cmd = cmd; 560 } 561 562 mousePressed(MouseEvent me)563 public void mousePressed (MouseEvent me) { 564 565 if (poly == null) { 566 poly = new Polygon(); 567 first = me.getPoint(); 568 poly.addPoint(first.x, first.y); 569 poly.addPoint(0, 0); 570 return; 571 } 572 573 MapCanvas c = (MapCanvas)me.getSource(); 574 Graphics2D g = (Graphics2D)c.getGraphics(); 575 g.setXORMode(Color.black); 576 g.setColor(Color.white); 577 if (stroke == null) stroke = getPreviewStroke(c.getScale()); 578 //g.setStroke(stroke); 579 580 if (remove) { 581 c.drawShape(g, poly); 582 remove = false; 583 } 584 585 latest = me.getPoint(); 586 587 if (poly.npoints > 2) { 588 if ((me.getModifiers() & InputEvent.BUTTON1_MASK) == 0) { 589 poly.addPoint(latest.x, latest.y); 590 MapPolygon.this.polygon = 591 new Polygon(poly.xpoints, 592 poly.ypoints, 593 poly.npoints - 1); 594 setStyles(c.getModel().getDefaultPolygonStyles()); 595 c.addMapObject(MapPolygon.this); 596 c.setCanvasEventHandler(newInstance().getCreateHandler(cmd)); 597 if (cmd != null) cmd.run(); 598 return; 599 } 600 } 601 602 poly.addPoint(latest.x, latest.y); 603 c.drawShape(g, poly); 604 remove = true; 605 } 606 607 mouseMoved(MouseEvent me)608 public void mouseMoved (MouseEvent me) { 609 610 if (poly == null) return; 611 612 MapCanvas c = (MapCanvas)me.getSource(); 613 Graphics2D g = (Graphics2D)c.getGraphics(); 614 g.setXORMode(Color.black); 615 g.setColor(Color.white); 616 if (stroke == null) stroke = getPreviewStroke(c.getScale()); 617 //g.setStroke(stroke); 618 if (remove) c.drawShape(g, poly); 619 620 int li = poly.npoints - 1; 621 poly.xpoints[li] = me.getX(); 622 poly.ypoints[li] = me.getY(); 623 624 c.drawShape(g, poly); 625 remove = true; 626 } 627 628 } 629 630 631 private class PolygonPointMoveHandler extends CanvasEventAdapter { 632 633 634 private int index; 635 private Line2D.Float l1, l2; 636 private boolean virgin; 637 private Stroke stroke; 638 639 PolygonPointMoveHandler(MouseEvent me, int index)640 public PolygonPointMoveHandler (MouseEvent me, int index) { 641 642 this.index = index; 643 virgin = true; 644 645 int ip = index - 1; 646 if (ip < 0) ip += polygon.npoints; 647 Point prev = new Point(polygon.xpoints[ip], polygon.ypoints[ip]); 648 l1 = new Line2D.Float(prev, me.getPoint()); 649 650 int in = (index + 1) % polygon.npoints; 651 Point next = new Point(polygon.xpoints[in], polygon.ypoints[in]); 652 l2 = new Line2D.Float(next, me.getPoint()); 653 654 655 float dash[] = { 10.0f }; 656 stroke = new BasicStroke(1, BasicStroke.CAP_BUTT, 657 BasicStroke.JOIN_MITER, 658 10.0f, dash, 0.0f); 659 } 660 661 mouseDragged(MouseEvent evt)662 public void mouseDragged (MouseEvent evt) { 663 664 MapCanvas c = (MapCanvas)evt.getSource(); 665 Graphics2D g = (Graphics2D)c.getGraphics(); 666 g.setXORMode(Color.black); 667 g.setColor(Color.white); 668 //g.setStroke(stroke); 669 670 if (!virgin) drawPreview(g, c); 671 else virgin = false; 672 673 l1.x2 = l2.x2 = evt.getX(); 674 l1.y2 = l2.y2 = evt.getY(); 675 676 drawPreview(g, c); 677 } 678 679 mouseReleased(MouseEvent evt)680 public void mouseReleased (MouseEvent evt) { 681 682 MapCanvas c = (MapCanvas)evt.getSource(); 683 c.movePolygonPoint(MapPolygon.this, index, evt.getX(), evt.getY()); 684 c.setCanvasEventHandler(null); 685 } 686 687 drawPreview(Graphics2D g, MapCanvas c)688 private void drawPreview (Graphics2D g, MapCanvas c) { 689 c.drawShape(g, l1); 690 c.drawShape(g, l2); 691 } 692 } 693 694 695 private class RotateHandler extends CanvasEventAdapter { 696 697 private double cx, cy, angle; 698 private Stroke stroke; 699 private Shape origShape; 700 private Shape previewShape; 701 private AffineTransform backTx; 702 private boolean firstTime; 703 RotateHandler()704 public RotateHandler() { 705 cx = getBounds().getCenterX(); 706 cy = getBounds().getCenterY(); 707 origShape = AffineTransform.getTranslateInstance( 708 -cx , -cy).createTransformedShape(polygon); 709 backTx = AffineTransform.getTranslateInstance(cx, cy); 710 updatePreviewShape(); 711 firstTime = true; 712 } 713 mouseMoved(MouseEvent me)714 public void mouseMoved(MouseEvent me) { 715 MapCanvas c = (MapCanvas)me.getSource(); 716 if (!firstTime) drawPreview(c); 717 angle = 2 * Math.PI * (cx - me.getX()) / (800 / c.getScale()); 718 updatePreviewShape(); 719 drawPreview(c); 720 firstTime = false; 721 } 722 mousePressed(MouseEvent me)723 public void mousePressed(MouseEvent me) { 724 MapCanvas c = (MapCanvas)me.getSource(); 725 if (!firstTime) drawPreview(c); 726 c.rotatePolygon(MapPolygon.this, angle); 727 c.setCanvasEventHandler(null); 728 } 729 updatePreviewShape()730 private void updatePreviewShape() { 731 AffineTransform at = AffineTransform.getRotateInstance(angle); 732 at.preConcatenate(backTx); 733 previewShape = at.createTransformedShape(origShape); 734 } 735 drawPreview(MapCanvas c)736 private void drawPreview(MapCanvas c) { 737 Graphics2D g = (Graphics2D)c.getGraphics(); 738 g.setXORMode(Color.black); 739 g.setColor(Color.white); 740 if (stroke == null) stroke = getPreviewStroke(c.getScale()); 741 //g.setStroke(stroke); 742 c.drawShape(g, previewShape); 743 } 744 } 745 } 746