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