1 package org.catacomb.graph.gui;
2
3 import org.catacomb.be.Position;
4 import org.catacomb.datalish.Box;
5 import org.catacomb.interlish.interact.ClickListener;
6 import org.catacomb.interlish.structure.ModeSettable;
7 import org.catacomb.report.E;
8
9
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.RenderingHints;
13
14 import java.awt.Color;
15
16 public class WorldCanvas extends BaseCanvas implements ModeSettable {
17
18 static final long serialVersionUID = 1001;
19
20
21 public static final String PAN = "pan";
22 public static final String ZOOM = "zoom";
23 public static final String BOX = "box";
24 public static final String ROLL = "roll";
25 public static final String TURN = "turn";
26 public static final String MULTI = "all";
27
28 public static final String ZOOMIN = "zoomIn";
29 public static final String ZOOMOUT = "zoomOut";
30
31
32 protected WorldTransform wt;
33 protected Painter painter;
34 protected PaintInstructor paintInstructor;
35 protected Mouse mouse;
36
37
38 private BoxSelectionHandler boxSelectionHandler;
39 private PanHandler panHandler;
40 private TurnZoomHandler turnZoomHandler;
41 private ClickZoomHandler clickZoomHandler;
42 private RollHandler rollHandler;
43 private TurntableHandler turntableHandler;
44
45 private MouseHandler[] handlers;
46
47 private boolean antialias = false;
48 private boolean tooltips = false;
49
50 Box reframeBox;
51
52 private boolean userAntialias;
53
54
55 public WorldCanvas(int w, int h) {
56 this(w, h, true);
57 }
58
59
60 public WorldCanvas(int w, int h, boolean interactive) {
61 super(w, h);
62
63
64 mouse = new Mouse(this, interactive);
65
66
67 wt = new WorldTransform();
68 wt.setWidth(w);
69 wt.setHeight(h);
70
71 painter = new Painter(wt);
72
73 addWorldHandlers();
74
75 setMouseMode("pan");
76 }
77
78
79 public boolean isAntialiasing() {
80 return antialias;
81 }
82
83 public void setAntialias(boolean b) {
84 userAntialias = b;
85 antialias = b;
86 repaint();
87 }
88
89 public void restoreAA() {
90 setAntialias(userAntialias);
91 }
92
93
94 public void setMode(String dom, String mod) {
95
96 if (dom.equals("antialias")) {
97 antialias = (mod.equals("true"));
98
99 } else if (dom.equals("mouse")) {
100 setMouseMode(mod);
101
102 } else {
103 E.error("unrecognized mode " + dom);
104 }
105 repaint();
106 }
107
108
109
110 public void setMode(String dom, boolean b) {
111 if (dom.equals("antialias")) {
112 antialias = b;
113
114 } else if (dom.equals("labels")) {
115 tooltips = b;
116
117 } else if (dom.equals("showAll")) {
118 reframe();
119
120 } else {
121 E.error("unrecognized mode " + dom);
122 }
123 repaint();
124 }
125
126
127 public void syncSize() {
128 wt.setWidth(getWidth());
129 wt.setHeight(getHeight());
130 }
131
132
133 public void reluctantReframe() {
134 if (reframeBox == null) {
135 reframe();
136 } else if (paintInstructor != null) {
137 Box box = paintInstructor.getLimitBox();
138 if (box != null && box.differentFrom(reframeBox, 0.15)) {
139 frameToBox(box);
140 }
141 }
142 }
143
144
145 public void reframe() {
146 if (paintInstructor == null) {
147 E.shortWarning("no paint instructor?");
148 } else {
149 Box box = paintInstructor.getLimitBox();
150 frameToBox(box);
151 }
152 }
153
154
155 protected void frameToBox(Box box) {
156 if (box == null) {
157 E.warning("no limit box returned from " + paintInstructor.getClass().getName());
158
159
160 } else if (box.hasData()) {
161 reframeBox = box.makeCopy();
162 box.pad();
163 painter.reframe(box);
164 repaint();
165
166 } else {
167
168 }
169
170 }
171
172
173
174 public boolean showTooltips() {
175 return tooltips;
176 }
177
178
179 public void setMode(int imode) {
180 E.missing();
181 }
182
183
184 public void addRangeListener(RangeListener rl) {
185 wt.addRangeListener(rl);
186 }
187
188
189
190 public Painter getPainter() {
191 return painter;
192 }
193
194
195 WorldTransform getWorldTransform() {
196 return wt;
197 }
198
199
200 public void prependHandler(MouseHandler mhandler) {
201 mouse.prependHandler(mhandler);
202 }
203
204
205 public void setClickListener(ClickListener cl) {
206 mouse.setClickListener(cl);
207 }
208
209 public void setRotationListener(RotationListener rl) {
210 wt.setRotationListener(rl);
211 }
212
213
214
215 public void addWorldHandlers() {
216 panHandler = new PanHandler();
217 addHandler(panHandler);
218
219 clickZoomHandler = new ClickZoomHandler();
220 addHandler(clickZoomHandler);
221
222 boxSelectionHandler = new BoxSelectionHandler();
223 addHandler(boxSelectionHandler);
224
225 turnZoomHandler = new TurnZoomHandler();
226 addHandler(turnZoomHandler);
227
228
229 rollHandler = new RollHandler();
230 addHandler(rollHandler);
231
232 turntableHandler = new TurntableHandler();
233 addHandler(turntableHandler);
234
235
236 MouseHandler[] ha = { panHandler, clickZoomHandler, boxSelectionHandler,
237 turnZoomHandler, rollHandler, turntableHandler
238 };
239 handlers = ha;
240 }
241
242
243
244 public void setMouseMode(String s) {
245 for (int i = 0; i < handlers.length; i++) {
246 handlers[i].deactivate();
247 }
248
249 if (s == null) {
250 E.error("null mouse mode ");
251
252 } else if (s.equals(MULTI)) {
253 for (int i = 0; i < handlers.length; i++) {
254 handlers[i].activate();
255 }
256
257 } else if (s.equals(PAN)) {
258 panHandler.simpleActivate();
259
260 } else if (s.equals(ZOOM)) {
261 clickZoomHandler.activateInOut();
262
263 } else if (s.equals(BOX)) {
264 boxSelectionHandler.simpleActivate();
265
266 } else if (s.equals(ROLL)) {
267 rollHandler.simpleActivate();
268
269 } else if (s.equals(TURN)) {
270 turntableHandler.simpleActivate();
271
272 } else if (s.equals(ZOOMIN)) {
273 clickZoomHandler.activateIn();
274
275 } else if (s.equals(ZOOMOUT)) {
276 clickZoomHandler.activateOut();
277
278 } else {
279 E.error("unhandled mouse mode " + s);
280 }
281 }
282
283
284 public void setXRange(double[] lh) {
285 setXRange(lh[0], lh[1]);
286 }
287
288
289 public void setYRange(double[] lh) {
290 setYRange(lh[0], lh[1]);
291 }
292
293
294
295 public void ensureCovers(double[] xr, double[] yr) {
296 wt.ensureCovers(xr[0], yr[0], xr[1], yr[1]);
297 wt.notifyRangeChange();
298 }
299
300
301 public void setXRange(double low, double high) {
302 wt.setXRange(low, high);
303 wt.notifyRangeChange();
304 }
305
306
307 public void setYRange(double low, double high) {
308 wt.setYRange(low, high);
309 wt.notifyRangeChange();
310 }
311
312
313 public void setFixedAspectRatio(double ar) {
314 wt.setFixedAspectRatio(ar);
315 }
316
317
318 public double[] getXRange() {
319 return wt.getXRange();
320 }
321
322
323 public double[] getYRange() {
324 return wt.getYRange();
325 }
326
327
328 public void viewAction(String s) {
329 if (s.equals("frame")) {
330 reframe();
331 }
332 }
333
334
335
336 public void addHandler(MouseHandler mh) {
337 mouse.addHandler(mh);
338 }
339
340
341 public void fixRanges() {
342 wt.fixRanges();
343 }
344
345
346
347 public void setPaintInstructor(PaintInstructor pi) {
348 paintInstructor = pi;
349 }
350
351
352 public void paintComponent(Graphics g0) {
353 wt.setWidth(getWidth());
354 wt.setHeight(getHeight());
355
356 g0.setColor(getDataBackground());
357 g0.fillRect(0, 0, getWidth(), getHeight());
358 Graphics2D g = (Graphics2D)g0;
359
360
361 painter.setGraphics(g);
362
363 prePaint(g);
364
365 paint2D(g);
366
367 postPaint(g);
368
369 mouse.echoPaint(g);
370
371 }
372
373
374 public void prePaint(Graphics2D g) {
375
376 }
377
378 public void postPaint(Graphics2D g) {
379
380 }
381
382
383 public void applyAAPreference(Graphics2D g) {
384 if (antialias) {
385 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
386 } else {
387 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
388 }
389
390 }
391
392
393 public void paint2D(Graphics2D g) {
394
395 E.info("pw oainting ");
396
397 if (paintInstructor != null) {
398
399 applyAAPreference(g);
400
401 paintInstructor.instruct(painter);
402 }
403
404 }
405
406
407
408 void boxSelected(int x0, int y0, int x1, int y1) {
409 wt.setCanvasSize(getWidth(), getHeight());
410 wt.boxSelected(x0, y0, x1, y1);
411 repaint();
412 }
413
414 void initializeZoom(int xc, int yc) {
415 wt.initializeZoom(xc, yc);
416 }
417
418 void dragZoom(double fx, double fy, int xc, int yc) {
419 antialias = false;
420 wt.dragZoom(fx, fy, xc, yc);
421 }
422
423
424 void zoom(double fac, int xc, int yc) {
425 wt.zoom(fac, xc, yc);
426 repaint();
427 }
428
429
430 void zoom(double xfac, double yfac, int xc, int yc) {
431 wt.zoom(xfac, yfac, xc, yc);
432 repaint();
433 }
434
435
436 void trialPan(int xfrom, int yfrom, int xto, int yto) {
437 antialias = false;
438 wt.trialPan(xfrom, yfrom, xto, yto);
439 repaint();
440 }
441
442
443 void permanentPan(int xfrom, int yfrom, int xto, int yto) {
444 wt.permanentPan(xfrom, yfrom, xto, yto);
445 repaint();
446 }
447
448
449 void dragRollRotate(int px, int py) {
450 antialias = false;
451 wt.dragRollRotate(px, py);
452 repaint();
453 }
454
455 void dragZRotate(int px, int py) {
456 antialias = false;
457 wt.dragZRotate(px, py);
458 repaint();
459 }
460
461 public void turn(double d) {
462 wt.initializeRotation(getWidth() / 2, getHeight() / 2);
463 wt.zRotate(d / 180. * Math.PI);
464 repaint();
465 }
466
467 void initializeRotation(int px, int py) {
468 wt.initializeRotation(px, py);
469 }
470
471
472 void initializeRotation(double x, double y, double z) {
473 wt.initializeRotationLocal(x, y, z);
474 }
475
476
477 public void setColorRange(double cmin, double cmax) {
478 painter.setColorRange(cmin, cmax);
479 }
480
481 public void setColorTable(Color[] ac) {
482 painter.setColorTable(ac);
483 }
484
485
486 public int[] getIntPosition(Position pos) {
487 return wt.getIntPosition(pos.getX(), pos.getY());
488 }
489
490
491 public double[][] getProjectionMatrix() {
492 return wt.getProjectionMatrix();
493 }
494
495 public void setRollCenter(double x, double y, double z) {
496 rollHandler.setRollCenter(x, y, z);
497 }
498
499
500 public double[] get2Center() {
501 return wt.get2Center();
502 }
503
504 public double[] get3Center() {
505 return wt.get3Center();
506 }
507
508
509
510
511 public double[] getFourMatrix() {
512 double[][] pm = wt.getProjectionMatrix();
513
514
515
516 double[] cen2 = wt.get2Center();
517
518 double[] ret = new double[16];
519
520 double sf = 3. * wt.getScale();
521
522 for (int i = 0; i < 3; i++) {
523 for (int j = 0; j < 3; j++) {
524 ret[4 * i + j] = sf * pm[i][j];
525 }
526 ret[4 * i + 3] = cen2[i];
527 }
528 ret[15] = 1.;
529 return ret;
530 }
531
532
533 public void setFourMatrix(double[] fm) {
534 double[][] pm = new double[3][3];
535 double[] cen = new double[3];
536
537 for (int i = 0; i < 3; i++) {
538 for (int j = 0; j < 3; j++) {
539 pm[i][j]= fm[4 * i + j];
540 }
541 cen[i] = fm[4 * i + 3];
542 }
543
544 double m3xx, m3xy, m3xz, m3yx, m3yy, m3yz, m3zx, m3zy, m3zz;
545 m3xx = pm[0][0];
546 m3xy = pm[0][1];
547 m3xz = pm[0][2];
548 m3yx = pm[1][0];
549 m3yy = pm[1][1];
550 m3yz = pm[1][2];
551 m3zx = pm[2][0];
552 m3zy = pm[2][1];
553 m3zz = pm[2][2];
554
555 double det = (m3xx * (m3yy * m3zz - m3zy * m3yz) -
556 m3xy * (m3yx * m3zz - m3zx * m3yz) +
557 m3xz * (m3yx * m3zy - m3zx * m3yy));
558
559 double rdet = Math.pow(det, 1./3.);
560 for (int i = 0; i < 3; i++) {
561 for (int j = 0; j < 3; j++) {
562 pm[i][j] /= rdet;
563 }
564 }
565
566 double[] c0 = {0., 0., 0.};
567
568 for (int i = 0; i < 3; i++) {
569 cen[i] /= rdet;
570 }
571
572 wt.setProjectionMatrix(pm);
573 wt.set3Center(c0);
574 wt.set2Center(cen);
575
576 wt.setScale(0.3 * rdet);
577
578 repaint();
579
580 }
581 }