checkpoint
[slipway.git] / src / edu / berkeley / obits / gui / Gui.java
1 package edu.berkeley.obits.gui;
2
3 import static edu.berkeley.obits.device.atmel.AtmelDevice.Constants.*;
4 import static edu.berkeley.obits.device.atmel.AtmelDevice.Util.*;
5 import edu.berkeley.obits.*;
6 import edu.berkeley.obits.device.atmel.*;
7 import java.awt.*;
8 import java.awt.geom.*;
9 import java.awt.event.*;
10 import java.awt.color.*;
11 import org.ibex.util.*;
12 import java.io.*;
13 import java.util.*;
14 import javax.swing.*;
15
16 public class Gui extends ZoomingPanel implements KeyListener, MouseMotionListener {
17
18     Graphics2D g;
19     G gg;
20
21     public static int SIZE = 92;
22     public static int RINGS = 3;
23     public static int BEVEL = 5;
24     public static int CORE_SIZE = 64;
25     public static int CORE_OFFSET = 10;
26     public static int HOFF = 52;
27
28     public static int RED  = 0xff0000;
29     public static int BLUE = 0x0000ff;
30
31     public static final P YLUT_OUTPUT_POINT  = new P(SIZE-CORE_OFFSET-CORE_SIZE+51 - 2, CORE_OFFSET + 41 - 3);
32     public static final P XLUT_OUTPUT_POINT  = new P(SIZE-CORE_OFFSET-CORE_SIZE+17 - 2, CORE_OFFSET + 41 - 3);
33
34     At40k at40k;
35
36     private HashSet<Cell> cells = new HashSet<Cell>();
37     private Cell[][] ca = new Cell[128][];
38
39     public static final Color nonselectedcell = new Color(0xcc, 0xcc, 0xcc);
40     public static final Color selectedcell = new Color(0x44, 0x44, 0xff);
41
42     public Gui(At40k at40k) {
43         this.at40k = at40k;
44         for(int i=0; i<ca.length; i++)
45             ca[i] = new Cell[128];
46         for(int x=0; x<7; x++)
47             for(int y=0; y<7; y++)
48                 new Cell(x,y, at40k.cell(x+7, y+7));
49     }
50     
51
52     public class Cell {
53         At40k.Cell cell;
54         boolean in = false;
55         int _x, _y;
56         public Cell(int x, int y, At40k.Cell cell) {
57             _x = x;
58             _y = y;
59             ca[_x][_y] = this;
60             this.cell = cell;
61             cells.add(this);
62         }
63         public void draw() {
64             gg.color(in ? selectedcell : nonselectedcell);
65             g.fillRect(0, 0, SIZE, SIZE);
66
67             drawHwires();
68             drawVwires();
69             drawLocal();
70
71             AffineTransform t = g.getTransform();
72             g.transform(rotateInnerTransform());
73             drawMux();
74             drawRegister();
75             drawInternalRouting();
76             drawBuffer();
77             g.setTransform(t);
78
79             drawGates();
80             drawBorder();
81         }
82         public void drawBuffer() {
83             if (!cell.out_relevant()) return;
84             gg.color(Color.black);
85             gg.line(21, 64, 28, 60);
86             gg.line(21, 64, 28, 68);
87             gg.line(28, 60, 28, 68);
88
89             gg.color(Color.magenta);
90             if (cell.oe() == V4) {
91                 gg.line(16, 53, 25, 53);
92                 gg.line(25, 53, 25, 62);
93             } else if (cell.oe() == H4) {
94                 gg.line(25, 76, 25, 67);
95             }
96             
97         }
98         public void drawHwires() {
99             gg.color(Color.magenta);
100             for(int i=0; i<5; i++)
101                 if (cell.hwire(i).isDriven())
102                     gg.line(0, SIZE-(2*(1+RINGS)+2*i), SIZE, SIZE-(2*(1+RINGS)+2*i));
103             int plane = cell.zi();
104             if (plane >= L0 && plane <= L4 && cell.hx(plane)) {
105                 P p1 = new P(38, 18);
106                 p1 = rotateInner(p1);
107                 if (cell.zi_to_xlut_relevant() && cell.xlut_relevant())
108                     route(new P(84, 84 - 2*(plane-L0)), p1, 3);
109                 p1 = new P(64, 18);
110                 p1 = rotateInner(p1);
111                 if (cell.zi_to_ylut_relevant() && cell.ylut_relevant())
112                     route(new P(84, 84 - 2*(plane-L0)), p1, 3);
113             }
114             plane = cell.wi();
115             if (plane >= L0 && plane <= L4 && cell.hx(plane)) {
116                 P p1 = new P(38, 18);
117                 p1 = rotateInner(p1);
118                 if (cell.zi_to_xlut_relevant() && cell.xlut_relevant())
119                     route(new P(84, 84 - 2*(plane-L0)), p1, 3);
120                 p1 = rotateInner(new P(64, 18));
121                 if (cell.zi_to_ylut_relevant() && cell.ylut_relevant())
122                     route(new P(84, 84 - 2*(plane-L0)), p1, 3);
123             }
124         }
125         public void drawVwires() {
126             gg.color(Color.magenta);
127             for(int i=0; i<5; i++)
128                 if (cell.vwire(i).isDriven())
129                     gg.line(2*(1+RINGS)+2*i, 0, 2*(1+RINGS)+2*i, SIZE);
130             int plane = cell.zi();
131             if (plane >= L0 && plane <= L4 && cell.vx(plane)) {
132                 P p1 = new P(38, 18);
133                 p1 = rotateInner(p1);
134                 if (cell.zi_to_xlut_relevant() && cell.xlut_relevant())
135                     route(new P(17 - 2*(plane-L0), 8), p1, 3);
136                 p1 = new P(64, 18);
137                 p1 = rotateInner(p1);
138                 if (cell.zi_to_ylut_relevant() && cell.ylut_relevant())
139                     route(new P(17 - 2*(plane-L0), 8), p1, 3);
140             }
141             plane = cell.wi();
142             if (plane >= L0 && plane <= L4 && cell.vx(plane)) {
143                 P p1 = new P(38, 18);
144                 p1 = rotateInner(p1);
145                 if (cell.zi_to_xlut_relevant() && cell.xlut_relevant())
146                     route(new P(17 - 2*(plane-L0), 8), p1, 3);
147                 p1 = new P(64, 18);
148                 p1 = rotateInner(p1);
149                 if (cell.zi_to_ylut_relevant() && cell.ylut_relevant())
150                     route(new P(17 - 2*(plane-L0), 8), p1, 3);
151             }
152         }
153             public P corner(int corner, int ring) {
154                 switch(corner) {
155                     case NW: return new P(0    +2*ring,  SIZE -2*xring);
156                     case SW: return new P(0    +2*ring,  0    +2*xring);
157                     case NE: return new P(SIZE -2*ring,  SIZE -2*xring);
158                     case SE: return new P(SIZE -2*ring,  0    +2*xring);
159                     default: return null;
160                 }
161             }
162
163         public void drawInternalRouting() {
164             gg.color(new Color(0, 107, 51));
165             if (cell.fb_relevant()) {
166                 if (cell.f()) {
167                     gg.line(51, 74, 37, 74);
168                     gg.line(37, 74, 50, 12);
169                 } else if (cell.c() == XLUT) {
170                     gg.line(32, 52, 50, 52);
171                     gg.line(50, 52, 50, 12);
172                 } else if (cell.c() == YLUT) {
173                     gg.line(68, 52, 50, 52);
174                     gg.line(50, 52, 50, 12);
175                 } else {
176                     gg.line(50, 56, 41, 56);
177                     gg.line(41, 56, 50, 12);
178                 }
179                 if (cell.xlut_relevant()) {
180                     gg.line(52, 12, XLUT_OUTPUT_POINT.getX(), 12);
181                     gg.line(XLUT_OUTPUT_POINT.getX(), 12, XLUT_OUTPUT_POINT.getX(), 32);
182                 }
183                 if (cell.ylut_relevant()) {
184                     gg.line(52, 12, YLUT_OUTPUT_POINT.getX(), 12);
185                     gg.line(YLUT_OUTPUT_POINT.getX(), 12, YLUT_OUTPUT_POINT.getX(), 32);
186                 }
187             }
188         }
189
190         public void drawLocal() {
191             if (!cell.ylut_relevant() && !cell.xlut_relevant()) return;
192             P in   = new P(HOFF, 0);
193             P join = new P(HOFF, CORE_OFFSET);
194             in = rotateOuter(in);
195             join = rotateInner(join);
196             int rot = rot();
197             switch(rot) {
198                 case 0: case 2:
199                     join = new P(in.getX(), join.getY());
200                     break;
201                 case 1: case 3:
202                     join = new P(join.getX(), in.getY());
203                     break;
204             }
205
206             P xi  = corner(cell.xi(), xring);
207             P xi2 = null;
208             gg.color(new Color(0xff, 0x00, 0x00));
209             int xring = 4;
210             if (cell.xi_relevant() && cell.xlut_relevant())
211                 switch(cell.xi()) {
212                     case NW:
213                         xi2 = new P(-BEVEL, SIZE+BEVEL);
214                         xi = translate(xi, 0, -3);
215                         xi2 = translate(xi2, 0, -3);
216                         gg.line(xi2, xi);
217                         break;
218                         
219                     case SW:
220                         xi2 = new P(-BEVEL, -BEVEL);
221                         xi = translate(xi, 0, 3);
222                         xi2 = translate(xi2, 0, 3);
223                         gg.line(xi2, xi);
224                         break;
225                         
226                     case NE:
227                         xi2 = new P(SIZE+BEVEL, SIZE+BEVEL);
228                         xi = translate(xi, 0, -3);
229                         xi2 = translate(xi2, 0, -3);
230                         gg.line(xi2, xi);
231                         break;
232                         
233                     case SE:
234                         xi2 = new P(SIZE+BEVEL, -BEVEL);
235                         xi = translate(xi, 0, 3);
236                         xi2 = translate(xi2, 0, 3);
237                         gg.line(xi2, xi);
238                         break;
239                 }
240
241             if (cell.xlut_relevant()) {
242                 P c;
243                 gg.color(BLUE);
244                 if (cell.yi_to_xlut_relevant())
245                     route(in, rotateInner(new P(SIZE - CORE_OFFSET - CORE_SIZE/2 - CORE_SIZE / 6, 20)), 5);
246
247                 gg.color(RED);
248                 if (cell.xi_to_xlut_relevant() && xi != null)
249                     route(xi, rotateInner(new P(SIZE - CORE_OFFSET - CORE_SIZE/2 - CORE_SIZE / 3, 20)), 4);
250
251                 P xo   = XLUT_OUTPUT_POINT;
252                 P xout = new P(SIZE-CORE_OFFSET-CORE_SIZE+17 - 2, CORE_OFFSET + CORE_SIZE - 3);
253                 xo = rotateInner(xo);
254                 xout = rotateInner(xout);
255                 gg.color(new Color(0xff, 0xcc, 0xcc));
256                 xring = 6;
257                 if (cell.ne() != null && cell.ne().xi()==SW && cell.ne().xi_relevant() && cell.ne().xlut_relevant()) {
258                     gg.line(xo, xout);
259                     P xoo = new P(SIZE-2*xring, SIZE-2*xring);
260                     P xoo2 = new P(SIZE, SIZE);
261                     xoo = translate(xoo, -3, 0);
262                     xoo2 = translate(xoo2, -3, 0);
263                     gg.line(xoo2, xoo);
264                     route(xout, xoo, xring);
265                 }
266                 if (cell.nw() != null && cell.nw().xi()==SE && cell.nw().xi_relevant() && cell.nw().xlut_relevant()) {
267                     gg.line(xo, xout);
268                     P xoo = new P(0+2*xring, SIZE-2*xring);
269                     P xoo2 = new P(0, SIZE);
270                     xoo = translate(xoo, 3, 0);
271                     xoo2 = translate(xoo2, 3, 0);
272                     gg.line(xoo2, xoo);
273                     route(xout, xoo, xring);
274                 }
275                 if (cell.se() != null && cell.se().xi()==NW && cell.se().xi_relevant() && cell.se().xlut_relevant()) {
276                     gg.line(xo, xout);
277                     P xoo = new P(SIZE-2*xring, 0+2*xring);
278                     P xoo2 = new P(SIZE, 0);
279                     xoo = translate(xoo, -3, 0);
280                     xoo2 = translate(xoo2, -3, 0);
281                     gg.line(xoo2, xoo);
282                     route(xout, xoo, xring);
283                 }
284                 if (cell.sw() != null && cell.sw().xi()==NE && cell.sw().xi_relevant() && cell.sw().xlut_relevant()) {
285                     gg.line(xo, xout);
286                     P xoo = new P(0+2*xring, 0+2*xring);
287                     P xoo2 = new P(0, 0);
288                     xoo = translate(xoo, 3, 0);
289                     xoo2 = translate(xoo2, 3, 0);
290                     gg.line(xoo2, xoo);
291                     route(xout, xoo, xring);
292                 }
293             }
294
295             if (cell.ylut_relevant()) {
296                 gg.color(new Color(0x00, 0x00, 0xff));
297                 P c;
298                 if (cell.yi_to_ylut_relevant()) {
299                     c   = new P(SIZE - CORE_OFFSET - CORE_SIZE/2 + CORE_SIZE / 6, 20);
300                     c = rotateInner(c);
301                     route(in, c, 5);
302                 }
303                 gg.color(new Color(0xff, 0x00, 0x00));
304                 if (cell.xi_to_ylut_relevant()) {
305                     c = rotateInner(new P(SIZE - CORE_OFFSET - CORE_SIZE/2 + CORE_SIZE / 3, 20));
306                     if (xi != null)
307                         route(xi, c, 4);
308                 }
309
310                 P yo   = rotateInner(YLUT_OUTPUT_POINT);
311                 P yout = rotateInner(new P(SIZE-CORE_OFFSET-CORE_SIZE+51 - 2, CORE_OFFSET + CORE_SIZE - 3));
312                 gg.color(0xbbbbff);
313                 if (cell.north() != null && cell.north().yi()==SOUTH && cell.north().yi_relevant() && cell.north().ylut_relevant()) {
314                     gg.line(yo, yout);
315                     route(yout, new P(SIZE-40, SIZE+ 0), 2);
316                 }
317                 if (cell.east() != null  && cell.east().yi()==WEST && cell.east().yi_relevant() && cell.east().ylut_relevant()) {
318                     gg.line(yo, yout);
319                     route(yout, new P(SIZE+ 0,      40), 2);
320                 }
321                 if (cell.south() != null && cell.south().yi()==NORTH && cell.south().yi_relevant() && cell.south().ylut_relevant()) {
322                     gg.line(yo, yout);
323                     route(yout, new P(     40,       0), 2);
324                 }
325                 if (cell.west() != null  && cell.west().yi()==EAST && cell.west().yi_relevant() && cell.west().ylut_relevant()) {
326                     gg.line(yo, yout);
327                     route(yout, new P(      0, SIZE-40), 2);
328                 }
329             }
330
331         }
332
333
334         private AffineTransform rotateOuterTransform() {
335             int rot = rot();
336             AffineTransform a = new AffineTransform();
337             a.rotate((Math.PI/2) * rot);
338             switch(rot) {
339                 case 0: break;
340                 case 1: a.translate(0,  -SIZE); break;
341                 case 2: a.translate(-SIZE, -SIZE); break;
342                 case 3: a.translate(-SIZE, 0); break;
343             }
344             return a;
345         }
346
347         private P rotateOuter(P p) { return p.transform(rotateOuterTransform()); }
348         private P rotateInner(P p) { return p.transform(rotateInnerTransform()); }
349
350         private AffineTransform rotateInnerTransform() {
351             int rot = rot();            
352             AffineTransform a = new AffineTransform();
353             a.translate(SIZE-CORE_SIZE-CORE_OFFSET, CORE_OFFSET);
354             a.rotate((Math.PI/2) * rot);
355             switch(rot) {
356                 case 0: break;
357                 case 1: a.translate(0,  -CORE_SIZE); break;
358                 case 2: a.translate(-CORE_SIZE, -CORE_SIZE); break;
359                 case 3: a.translate(-CORE_SIZE, 0); break;
360             }
361             a.translate(-1 * (SIZE-CORE_SIZE-CORE_OFFSET), -CORE_OFFSET);
362             return a;
363         }
364
365
366         private P project(P p1, int ring) {
367             double north = Math.abs( (SIZE-(ring*2)) - p1.getY() );
368             double south = Math.abs( (     (ring*2)) - p1.getY() );
369             double east  = Math.abs( (SIZE-(ring*2)) - p1.getX() );
370             double west  = Math.abs( (     (ring*2)) - p1.getX() );
371             if (north < south && north < east && north < west) return new P(p1.x,        SIZE-ring*2);
372             else if (south < east && south < west)             return new P(p1.x,        ring*2);
373             else if (east < west)                              return new P(SIZE-ring*2, p1.y);
374             else                                               return new P(ring*2,      p1.y);
375
376         }
377
378         private void route(P p1, P p2, int ring) {
379             int ringpos = ring * 2;
380             P projected = project(p1, ring);
381             gg.line(p1, projected);
382             p1 = projected;
383
384             projected = project(p2, ring);
385             gg.line(p2, projected);
386             p2 = projected;
387
388             double x1 = p1.getX();
389             double y1 = p1.getY();
390             double x2 = p2.getX();
391             double y2 = p2.getY();
392
393             if (x1==x2 || y1==y2) {
394                 gg.line(p1, p2);
395                 return;
396             }
397
398             if ((x1==SIZE-ring*2 || x1==ring*2) && !(y1==SIZE-ring*2 || y1==ring*2)) {
399                 P p3 = new P(x1, y2 > SIZE/2 ? SIZE-ring*2 : ring*2);
400                 gg.line(p1, p3);
401                 route(p3, p2, ring);
402             } else if ((y1==SIZE-ring*2 || y1==ring*2) && !(x1==SIZE-ring*2 || x1==ring*2)) {
403                 P p3 = new P(x2 > SIZE/2 ? SIZE-ring*2 : ring*2, y1);
404                 gg.line(p1, p3);
405                 route(p3, p2, ring);
406             } else
407                 route(p2, p1, ring);
408
409         }
410         
411         private int rot() {
412             int rot = 0;
413             switch(cell.yi()) {
414                 case SOUTH: rot = 0; break;
415                 case NORTH: rot = 2; break;
416                 case EAST: rot = 1; break;
417                 case WEST: rot = 3; break;
418                 default: {
419                     // FIXME: choose based on xin
420                     if (cell.north() != null && cell.north().yi()==SOUTH) { rot = 0; break; }
421                     if (cell.south() != null && cell.south().yi()==NORTH) { rot = 2; break; }
422                     if (cell.east()  != null && cell.east().yi()==WEST) { rot = 3; break; }
423                     if (cell.west()  != null && cell.west().yi()==EAST) { rot = 1; break; }
424                 }
425             }
426             return rot;
427         }
428         
429         public void drawGates() {
430             AffineTransform t = g.getTransform();
431             try {
432                 g.translate(SIZE-CORE_SIZE-CORE_OFFSET, CORE_OFFSET);
433                 
434                 int rot = rot();
435                 g.rotate((Math.PI/2) * rot);
436                 switch(rot) {
437                     case 0: break;
438                     case 1: g.translate(0,  -CORE_SIZE); break;
439                     case 2: g.translate(-CORE_SIZE, -CORE_SIZE); break;
440                     case 3: g.translate(-CORE_SIZE, 0); break;
441                 }
442
443                 //gg.color(Color.gray);
444                 //g.drawRect(0, 0, CORE_SIZE, CORE_SIZE);
445                 g.scale(1, -1);
446
447                 GeneralPath p = new GeneralPath();
448                 p.moveTo(29.141f, 36.301f);
449                 p.lineTo(29.141f, 36.301f-7.161f);
450                 p.curveTo(27.71f, 11.24f, 23.413f, 9.45f, 14.82f, 0.5f);
451                 p.curveTo(6.229f, 9.45f, 1.932f, 11.24f, 0.5f, 29.141f);
452                 p.lineTo(0.5f, 29.141f+7.161f);
453                 float x = 0.5f;
454                 float y = 29.141f+7.161f;
455                 p.curveTo(5.729f+x, -1.789f+y,
456                           6.444f+x, -2.686f+y,
457                           14.32f+x, -3.58f+y);
458                 p.curveTo(22.697f, 33.616f, 23.413f, 34.512f, 29.141f, 36.301f);
459                 g.translate(0,   -40f);
460                 if (cell.xlut_relevant()) {
461                     gg.color(Color.white);
462                     g.fill(p);
463                     gg.color(Color.red);
464                     g.draw(p);
465                 }
466                 g.translate(34f, 0f);
467                 if (cell.ylut_relevant()) {
468                     gg.color(Color.white);
469                     g.fill(p);
470                     gg.color(Color.blue);
471                     g.draw(p);
472                 }
473             } finally {
474                 g.setTransform(t);
475             }
476         }
477         public void drawMux() {
478             if (!cell.c_relevant()) return;
479             gg.color(Color.black);
480             if (cell.xlut_relevant() && (cell.c() == ZMUX || cell.c() == XLUT)) {
481                 gg.color(new Color(0xff, 0xbb, 0xbb));
482                 gg.line(XLUT_OUTPUT_POINT, new P(XLUT_OUTPUT_POINT.getX(), 52));
483                 gg.line(new P(XLUT_OUTPUT_POINT.getX(), 52), new P(51, 52));
484             }
485             if (cell.ylut_relevant() && (cell.c() == ZMUX || cell.c() == YLUT)) {
486                 gg.color(new Color(0xbb, 0xbb, 0xff));
487                 gg.line(YLUT_OUTPUT_POINT, new P(YLUT_OUTPUT_POINT.getX(), 52));
488                 gg.line(new P(YLUT_OUTPUT_POINT.getX(), 52), new P(51, 52));
489             }
490             gg.line(51, 52, 51, 51+25);
491             if (cell.c() == ZMUX) {
492                 gg.color(Color.black);
493                 gg.line(51, 52, 51, 51+25);
494                 gg.line(46, 54,     46+2, 54+5);
495                 gg.line(46+2, 54+5, 60-2, 54+5);
496                 gg.line(60-2, 54+5, 60,   54);
497                 gg.line(60,   54,   46, 54);
498             }
499         }
500         public void drawRegister() {
501             if (!cell.register_relevant()) return;
502             gg.color(Color.white);
503             g.fillRect(48, 58, 10, 14);
504             gg.color(Color.black);
505             g.drawRect(48, 58, 10, 14);
506             gg.line(57, 70, 54, 68);
507             gg.line(54, 68, 57, 66);
508         }
509         public void drawBorder() {
510             gg.color(Color.gray);
511             //gg.line(0, BEVEL, BEVEL,    0);
512             gg.line(BEVEL, 0, SIZE-BEVEL, 0);
513             //gg.line(SIZE-BEVEL, 0, SIZE, BEVEL);
514             gg.line(SIZE, BEVEL, SIZE, SIZE-BEVEL);
515             //gg.line(SIZE, SIZE-BEVEL, SIZE-BEVEL, SIZE);
516             gg.line(SIZE-BEVEL, SIZE, BEVEL, SIZE);
517             //gg.line(BEVEL, SIZE, 0, SIZE-BEVEL);
518             gg.line(0, SIZE-BEVEL, 0, BEVEL);
519         }
520     }
521
522     public void _paint(Graphics2D g) {
523
524         this.g = g;
525         this.gg = new G(g);
526         g.setStroke(new BasicStroke((float)0.5));
527
528         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
529         g.setRenderingHint(RenderingHints.KEY_RENDERING,    RenderingHints.VALUE_RENDER_QUALITY);
530
531         AffineTransform t  = g.getTransform();
532         for(Cell c : cells) {
533             g.setTransform(t);
534             g.translate(     c._x * SIZE/* + (10 * (c._x/4))*/,      c._y * SIZE/* + (10 * (c._y/4))*/);
535             c.draw();
536         }
537         g.setTransform(t);
538
539         g.setTransform(new AffineTransform());
540
541         gg.color(selectedcell);
542         g.fillRect(getWidth() - 200, 0, 200, 100);
543         gg.color(Color.white);
544         g.drawRect(getWidth() - 200, 0, 200, 100);
545
546         Cell newcell = whichCell(mousex, mousey);
547         int line = 10;
548         if (newcell != null && newcell.cell != null) {
549             g.drawString("selected: " + newcell._x + ","+newcell._y,
550                          getWidth() - 200 + 10, (line += 15));
551             g.drawString("    xlut: " + AtmelSerial.bin8(newcell.cell.xlut()),
552                          getWidth() - 200 + 10, (line += 15));
553             g.drawString("    ylut: " + AtmelSerial.bin8(newcell.cell.ylut()),
554                          getWidth() - 200 + 10, (line += 15));
555             String xi = "??";
556             switch(newcell.cell.xi()) {
557                 case NW : xi = "NW"; break;
558                 case NE : xi = "NE"; break;
559                 case SW : xi = "SW"; break;
560                 case SE : xi = "SE"; break;
561             }
562             g.drawString("      xi: " + xi, getWidth() - 200 + 10, (line += 15));
563             String yi = "??";
564             switch(newcell.cell.yi()) {
565                 case NORTH : yi = "NORTH"; break;
566                 case SOUTH : yi = "SOUTH"; break;
567                 case EAST  : yi = "EAST"; break;
568                 case WEST  : yi = "WEST"; break;
569             }
570             g.drawString("      yi: " + yi, getWidth() - 200 + 10, (line += 15));
571         }
572         this.g = null;
573         this.gg = null;
574     }
575
576
577     public void clear() {
578         Graphics2D g = (Graphics2D)getGraphics();
579         //gg.color(Color.black);
580         //gg.color(Color.lightGray);
581         g.clearRect(0, 0, getWidth(), getHeight());
582     }
583
584     public static final P translate(P p, int dx, int dy) {
585         return new P(p.getX()+dx, p.getY()+dy);
586     }
587
588     public Cell whichCell(int x, int y) {
589         P p = new P(x,y);
590         try {
591             p = p.inverseTransform(transform);
592         } catch (Exception e) {
593             e.printStackTrace();
594         }
595         int col = ((int)p.getX()) / (SIZE + BEVEL);
596         int row = ((int)p.getY()) / (SIZE + BEVEL);
597         for(Cell c : cells)
598             if (c._x == col && c._y == row)
599                 return c;
600         return null;
601     }
602 }