1 /* -------------------------------------------------------------------
2 GeoVISTA Center (Penn State, Dept. of Geography)
3 Java source file for the class Map
4 Copyright (c), 2002, GeoVISTA Center
5 All Rights Reserved.
6 Original Author: Frank Hardisty
7 $Author: dxg231 $
8 $Id: MapCanvas.java,v 1.11 2003/09/04 21:11:59 dxg231 Exp $
9 $Date: 2003/09/04 21:11:59 $
10 Reference: Document no:
11 ___ ___
12 ------------------------------------------------------------------- *
13 */
14 package edu.psu.geovista.app.map;
15
16 import edu.psu.geovista.app.coordinator.*;
17 import edu.psu.geovista.data.condition.*;
18 import edu.psu.geovista.data.geog.*;
19 import edu.psu.geovista.symbolization.*;
20 import edu.psu.geovista.ui.*;
21 import edu.psu.geovista.ui.Fisheyes;
22 import edu.psu.geovista.ui.cursor.*;
23 import edu.psu.geovista.ui.event.*;
24
25 import java.awt.*;
26 import java.awt.event.*;
27 import java.awt.geom.*;
28
29 import java.util.*;
30
31 import javax.swing.*;
32
33 /***
34 * This class handles the rendering of layer-independent objects like
35 * tooltips and the image used for buffering, and manages the layers,
36 * which render themselves to the image.
37 *
38 * This class also transforms spatial data into user space.
39 *
40 * This class is intended to be used inside other components like the
41 * GeoMap or the PlotMatrix.
42 */
43 public class MapCanvas
44 extends JPanel
45 implements ComponentListener,
46 ActionListener, MouseListener,
47 MouseMotionListener,
48 SelectionListener,
49 IndicationListener,
50 DataSetListener,
51 SpatialExtentListener,
52 ExcentricLabelClient {
53 private static final int CLASSIFIER_TYPE_BIVARIATE = 0;
54 private static final int CLASSIFIER_TYPE_UNIVARIATE = 1;
55 public static int MODE_SELECT = 0; //default mode
56 public static int MODE_ZOOM_IN = 1;
57 public static int MODE_ZOOM_OUT = 2;
58 public static int MODE_PAN = 3;
59 public static int MODE_EXCENTRIC = 4;
60 public static int MODE_FISHEYE = 5;
61 public static int MODE_MAGNIFYING = 6;
62 transient private int mouseX1;
63 transient private int mouseX2;
64 transient private int mouseY1;
65 transient private int mouseY2;
66 private transient DataSetForApps dataSet;
67
68 //private transient Vector userSpaceSpatialData = new Vector();
69 private transient Vector spatialDataTypes = new Vector();
70 private transient Vector shapeLayers;
71 private transient int indication = Integer.MIN_VALUE;
72 private transient int activeLayer;
73 private transient ShapeTransformer transformer;
74 private transient int[] classification;
75 private transient int[] conditionArray;
76
77 //todo: add this
78 //private int[] focus;
79 private transient int[] selectedObservations;
80 private transient Color[] objectColors;
81 private transient String[] variableNames;
82 private transient int currColorColumnX = -1;
83 private transient int currColorColumnY = -1;
84
85 //Colors
86 private transient double[] dataColorX;
87 private transient double[] dataColorY;
88 private transient Color colorSelection = Color.yellow;
89 private transient boolean selOriginalColorMode = true;
90 private transient Color colorIndication = Color.blue;
91
92 //todo: add these as functional types
93 //private Color colorNull = Color.darkGray;
94 //private Color colorOutOfFocus = Color.black;
95 //private Color colorNotInStudyArea = Color.black;
96 protected transient BivariateColorSymbolClassificationSimple
97 bivarColorClasser =
98 new BivariateColorSymbolClassificationSimple();
99
100 //private Color colorLine;
101 //private float lineWidth;
102 private transient Rectangle2D savedSrc = null;
103 private transient Image drawingBuff;
104 private transient Image[] drawingBuff2;
105 private transient AffineTransform panningXForm = new AffineTransform();
106 private transient Rectangle2D spatialDataFullExtent;
107 protected transient ExcentricLabels exLabels;
108 private transient String tipText = "";
109 private transient Font tipFont;
110 private transient boolean drawTip = true;
111 private transient boolean drawBox = false;
112 private transient int mode;
113 private transient GeoCursors cursors = new GeoCursors();
114 private transient float[] dash = new float[] {
115 5f, 7f, 5f};
116 private transient BasicStroke dashStroke = new BasicStroke( (float) 2.0,
117 BasicStroke.CAP_ROUND,
118 BasicStroke.JOIN_ROUND,
119 (float) 10.0, dash, 0);
120 private transient BasicStroke solidStroke = new BasicStroke(2f);
121 protected transient boolean autofit = false;
122 private transient boolean fitOnce = false;
123 protected Fisheyes fisheyes;
124
125 public MapCanvas() {
126 super();
127 this.setPreferredSize(new Dimension(300, 300));
128 shapeLayers = new Vector();
129 this.addComponentListener(this);
130 this.transformer = new ShapeAffineTransform();
131 this.addMouseListener(this);
132 this.addMouseMotionListener(this);
133 mouseX1 = -2;
134 this.drawTip = true;
135 this.mode = this.MODE_SELECT;
136
137 int greyAmt = 170;
138 Color bgColor = new Color(greyAmt, greyAmt, greyAmt);
139 this.setBackground(bgColor);
140
141 //this.exLabels = new ExcentricLabels();
142 //this.fisheyes = new Fisheyes();
143 //fisheyes.setLensType(Fisheyes.LENS_GAUSSIAN);
144 }
145
146
147 /****
148 * Set colors for observations. Normally this method is called by other components
149 * that classify or cluster data observations and assign colors.
150 */
151 public void setObservationColors(Color[] obsColors) {
152 if (this.shapeLayers.size() < 1 || this.dataSet == null) {
153 return;
154 }
155
156 if (this.dataSet.getNumObservations() != obsColors.length)
157 {
158 System.out.println("###ERROR: obsColors.length != number of observations!!!" +
159 this.dataSet.getNumObservations()+" != "+obsColors.length);
160 return;
161 }
162
163 this.objectColors = obsColors;
164
165 LayerShape ls = (LayerShape) this.shapeLayers.get(this.activeLayer);
166 ls.setObjectColors(this.objectColors);
167
168 paintDrawingBuff();
169 this.repaint();
170 }
171
172
173 private void sendSpatialDataToLayer(LayerShape l, Shape[] spatialData) {
174 l.setSpatialData(spatialData);
175 l.setParentSize(this.getHeight(), this.getWidth());
176 }
177
178 public Shape[] findUserSpaceSpatialData(Shape[] originalShapes,
179 Rectangle2D dest, boolean useSavedSrc) {
180 Shape[] originalData = originalShapes;
181
182 //two cases for finding src rectangle: second or later set of shapes, or first.
183 Rectangle2D src = null;
184
185 if (useSavedSrc && (savedSrc != null)) {
186 src = this.savedSrc;
187 }
188 else {
189 src = findFullExtentRect(originalShapes);
190
191 //src = this.savedSrc;
192 }
193
194 AffineTransform xForm = AffineTransformModifier.makeGeogAffineTransform(src,
195 dest,
196 true,
197 true);
198 Shape[] returnShapes = this.transformer.makeTransformedShapes(
199 originalShapes, xForm);
200
201 return returnShapes;
202 }
203
204 private Rectangle2D findFullExtentRect(Shape[] someShapes) {
205 Shape[] someData = someShapes;
206 double xMax;
207 double xMin;
208 double yMax;
209 double yMin;
210 xMax = Double.MAX_VALUE * -1;
211 xMin = Double.MAX_VALUE;
212 yMax = Double.MAX_VALUE * -1;
213 yMin = Double.MAX_VALUE;
214
215 for (int i = 0; i < someData.length; i++) {
216 Rectangle2D bounding = someData[i].getBounds2D();
217
218 if (bounding.getMaxX() > xMax) {
219 xMax = bounding.getMaxX();
220 }
221
222 if (bounding.getMinX() < xMin) {
223 xMin = bounding.getMinX();
224 }
225
226 if (bounding.getMaxY() > yMax) {
227 yMax = bounding.getMaxY();
228 }
229
230 if (bounding.getMinY() < yMin) {
231 yMin = bounding.getMinY();
232 }
233 }
234
235 Rectangle2D src = new Rectangle2D.Double(xMin, yMin, xMax - xMin,
236 yMax - yMin);
237 this.savedSrc = src;
238
239 //this.spatialDataFullExtent = src;
240 return src;
241 }
242
243 public Shape[] findFullExtentSpatialData(Shape[] originalShapes,
244 boolean useSavedSrc) {
245 Rectangle2D dest = new Rectangle2D.Float(0, 0, this.getWidth(),
246 this.getHeight());
247 Shape[] returnShapes = this.findUserSpaceSpatialData(originalShapes, dest,
248 useSavedSrc);
249
250 return returnShapes;
251 }
252
253 private void zoomNewExtent(Rectangle2D dest) {
254 for (Enumeration e = this.shapeLayers.elements(); e.hasMoreElements(); ) {
255 LayerShape ls = (LayerShape) e.nextElement();
256 Shape[] originalShapes = ls.getOriginalSpatialData();
257 Shape[] returnShapes = this.findUserSpaceSpatialData(originalShapes, dest,
258 ls.getIsAuxiliary());
259 this.sendSpatialDataToLayer(ls, returnShapes);
260 }
261
262 paintDrawingBuff();
263 this.repaint();
264 }
265
266 public void zoomFullExtent() {
267 for (Enumeration e = this.shapeLayers.elements(); e.hasMoreElements(); ) {
268 LayerShape ls = (LayerShape) e.nextElement();
269
270 //start print centroids
271 // System.out.println("Centroids:");
272 // for (int i = 0; i < this.dataSet.getNumObservations(); i++){
273 // Point p = ls.findCentroid(i);
274 // System.out.println(p.x + ","+p.y);
275 // }
276 //end print centroids
277 Shape[] originalShapes = ls.getOriginalSpatialData();
278 Shape[] returnShapes = this.findFullExtentSpatialData(originalShapes,
279 ls.getIsAuxiliary());
280 this.sendSpatialDataToLayer(ls, returnShapes);
281 }
282
283 paintDrawingBuff();
284 this.repaint();
285
286 LayerShape activeLayer = (LayerShape)this.shapeLayers.get(this.activeLayer);
287 Rectangle2D rect = this.findFullExtentRect(activeLayer.getSpatialData());
288 this.fireSpatialExtentChanged(rect);
289 }
290
291 public void spatialExtentChanged(SpatialExtentEvent e) {
292 Rectangle2D rect = e.getSpatialExtent();
293 this.zoomNewExtent(rect);
294 }
295
296 public void zoomIn(int x1, int x2, int y1, int y2) {
297 if (x1 > x2) {
298 int temp = x1;
299 x1 = x2;
300 x2 = temp;
301 }
302
303 if (y1 > y2) {
304 int temp = y1;
305 y1 = y2;
306 y2 = temp;
307 }
308
309 int diffX = x2 - x1;
310 int diffY = y2 - y1;
311 int boxTolerance = 10;
312
313 if ( (diffX < boxTolerance) && (diffY < boxTolerance)) { //accidental box, should have been a click
314 x2 = x1;
315 y2 = y1;
316 }
317
318 if ( (x1 == x2) && (y1 == y2)) {
319 //single click, we want to zoom in a bit with the click as the center
320 float scaleFactor = 0.45f;
321 int center = x1;
322 x1 = center - (int) ( (float)this.getWidth() * scaleFactor);
323 x2 = center + (int) ( (float)this.getWidth() * scaleFactor);
324 center = y1;
325 y1 = center - (int) ( (float)this.getHeight() * scaleFactor);
326 y2 = center + (int) ( (float)this.getHeight() * scaleFactor);
327 }
328
329 Rectangle2D src = new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1);
330 Rectangle2D dest = new Rectangle2D.Float(0, 0, this.getWidth(),
331 this.getHeight());
332 AffineTransform xForm = AffineTransformModifier.makeZoomingAffineTransform(
333 src, dest);
334
335 for (Enumeration e = this.shapeLayers.elements(); e.hasMoreElements(); ) {
336 LayerShape ls = (LayerShape) e.nextElement();
337
338 Shape[] originalShapes = ls.getSpatialData();
339 Shape[] returnShapes = this.transformer.makeTransformedShapes(
340 originalShapes, xForm);
341
342 this.sendSpatialDataToLayer(ls, returnShapes);
343 }
344
345 paintDrawingBuff();
346 this.repaint();
347
348 LayerShape activeLayer = (LayerShape)this.shapeLayers.get(this.activeLayer);
349 Rectangle2D rect = this.findFullExtentRect(activeLayer.getSpatialData());
350 this.fireSpatialExtentChanged(rect);
351 }
352
353 public void zoomOut(int x1, int x2, int y1, int y2) {
354 if (x1 > x2) {
355 int temp = x1;
356 x1 = x2;
357 x2 = temp;
358 }
359
360 if (y1 > y2) {
361 int temp = y1;
362 y1 = y2;
363 y2 = temp;
364 }
365
366 Rectangle2D src = new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1);
367 Rectangle2D dest = new Rectangle2D.Float(0, 0, this.getWidth(),
368 this.getHeight());
369 AffineTransform xForm = AffineTransformModifier.makeZoomingAffineTransform(
370 dest, src);
371
372 for (Enumeration e = this.shapeLayers.elements(); e.hasMoreElements(); ) {
373 LayerShape ls = (LayerShape) e.nextElement();
374
375 Shape[] originalShapes = ls.getSpatialData();
376 Shape[] returnShapes = this.transformer.makeTransformedShapes(
377 originalShapes, xForm);
378
379 this.sendSpatialDataToLayer(ls, returnShapes);
380 }
381
382 paintDrawingBuff();
383 this.repaint();
384
385 LayerShape activeLayer = (LayerShape)this.shapeLayers.get(this.activeLayer);
386 Rectangle2D rect = this.findFullExtentRect(activeLayer.getSpatialData());
387 this.fireSpatialExtentChanged(rect);
388 }
389
390 public void pan(int x1, int x2, int y1, int y2) {
391 int xDiff = x2 - x1;
392 int yDiff = y2 - y1;
393
394 Rectangle2D dest = new Rectangle2D.Float(0 + xDiff, 0 + yDiff,
395 this.getWidth(), this.getHeight());
396 Rectangle2D src = new Rectangle2D.Float(0, 0, this.getWidth(),
397 this.getHeight());
398 AffineTransform xForm = AffineTransformModifier.makeGeogAffineTransform(src,
399 dest,
400 false,
401 false);
402
403 for (Enumeration e = this.shapeLayers.elements(); e.hasMoreElements(); ) {
404 LayerShape ls = (LayerShape) e.nextElement();
405
406 Shape[] originalShapes = ls.getSpatialData();
407 Shape[] returnShapes = this.transformer.makeTransformedShapes(
408 originalShapes, xForm);
409
410 this.sendSpatialDataToLayer(ls, returnShapes);
411 }
412
413 paintDrawingBuff();
414 this.repaint();
415
416 LayerShape activeLayer = (LayerShape)this.shapeLayers.get(this.activeLayer);
417 Rectangle2D rect = this.findFullExtentRect(activeLayer.getSpatialData());
418 this.fireSpatialExtentChanged(rect);
419 }
420
421 public void panBuff(int x1, int x2, int y1, int y2) {
422 int xDiff = x2 - x1;
423 int yDiff = y2 - y1;
424
425 //AffineTransform panningXForm = new AffineTransform();
426 panningXForm = panningXForm.getTranslateInstance(xDiff, yDiff);
427 }
428
429 private void sendColorsToLayers(int numObs) {
430 if (this.shapeLayers.size() < 1) {
431 return;
432 }
433
434 if (this.dataColorX == null) {
435 return;
436 }
437
438 if (this.dataColorY == null) {
439 return;
440 }
441
442 if ( (this.objectColors == null) || (this.objectColors.length != numObs)) {
443 this.objectColors = new Color[numObs];
444 }
445
446 this.objectColors = this.bivarColorClasser.symbolize(this.dataColorX,
447 this.dataColorY);
448
449 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
450 ls.setObjectColors(this.objectColors);
451 paintDrawingBuff();
452 this.repaint();
453 } //end method
454
455 private void makeToolTip(int arrayIndex) {
456 if (arrayIndex < 0) {
457 tipText = "";
458 }
459 else if (this.currColorColumnX == this.currColorColumnY) {
460 String xVal = String.valueOf(dataSet.getNumericValueAsDouble(
461 this.currColorColumnX, arrayIndex));
462 String s = "";
463 String[] observationNames = this.dataSet.getObservationNames();
464
465 if (observationNames != null) {
466 s = s + "Name = " + observationNames[arrayIndex] + "\n";
467 }
468
469 s = s + variableNames[currColorColumnX - 1] + " = " + xVal;
470
471 this.tipText = s;
472 }
473 else if ( (this.currColorColumnX > 0) && (this.currColorColumnY > 0)) {
474 //setting multi-line tool tip
475 //b.setToolTipText("<html>ToolTip : 1st Line<br>2nd Line<br> 3rd Line </html>");
476 String xVal = String.valueOf(dataSet.getNumericValueAsDouble(
477 this.currColorColumnX, arrayIndex));
478 String yVal = String.valueOf(dataSet.getNumericValueAsDouble(
479 this.currColorColumnY, arrayIndex));
480 String s = "";
481 String[] observationNames = this.dataSet.getObservationNames();
482
483 if (observationNames != null) {
484 s = s + "Name = " + observationNames[arrayIndex] + "\n";
485 }
486
487 s = s + variableNames[currColorColumnX - 1] + " = " + xVal + "\n" +
488 variableNames[currColorColumnY - 1] + " = " + yVal;
489
490 this.tipText = s;
491 } //if
492 }
493
494 //start component event handling
495 //note: this class only listens to itself
496 public void componentHidden(ComponentEvent e) {
497
498 }
499
500 protected void tickleColors() {
501 //egregious hack
502 this.setCurrColorColumnX(this.currColorColumnX);
503 this.setCurrColorColumnY(this.currColorColumnY);
504 }
505
506 public void componentShown(ComponentEvent e) {
507 this.componentResized(e);
508 System.out.println("showing component");
509
510 // LayerShape aLayer = (LayerShape) this.shapeLayers.get(this.activeLayer);
511 // if (aLayer.colorsRecieved == false){
512 // this.sendColorsToLayers(this.dataColorX.length);
513 //
514 // }
515 }
516
517 public void componentMoved(ComponentEvent e) {
518
519 }
520
521 private void autoFitShapes() {
522 for (int i = 0; i < this.shapeLayers.size(); i++) {
523 LayerShape ls = (LayerShape)this.shapeLayers.get(i);
524 Integer layerTypeInt = (Integer)this.spatialDataTypes.get(i);
525 int layerType = layerTypeInt.intValue();
526
527 if (layerType == DataSetForApps.SPATIAL_TYPE_POLYGON) {
528 Shape[] originalShapes = ls.getOriginalSpatialData();
529 boolean useSavedSrc = ls.getIsAuxiliary();
530 Shape[] userShapes = this.findFullExtentSpatialData(originalShapes,
531 useSavedSrc);
532 this.sendSpatialDataToLayer(ls, userShapes);
533
534 //this.sendColorsToLayers(this.dataSet.getNumObservations());
535 }
536 else if (layerType == DataSetForApps.SPATIAL_TYPE_POINT) {
537 Shape[] originalShapes = ls.getOriginalSpatialData();
538 boolean useSavedSrc = ls.getIsAuxiliary();
539 Shape[] userShapes = this.findFullExtentSpatialData(originalShapes,
540 useSavedSrc);
541 LayerPoint lp = new LayerPoint();
542 Point2D[] points = lp.shapesToPoints(userShapes);
543 userShapes = lp.findShapesForPoints(points);
544
545 //userSpaceSpatialData.add(userShapes);
546 this.sendSpatialDataToLayer(ls, userShapes);
547 this.sendColorsToLayers(this.dataSet.getNumObservations());
548 } //end if layerType
549 } //next layer
550
551 this.fitOnce = true;
552 }
553
554 public void componentResized(ComponentEvent e) {
555 if ( (this.shapeLayers.size() > 0) && (this.getWidth() > 0) &&
556 (this.getHeight() > 0)) {
557 this.drawingBuff = this.createImage(this.getWidth(), this.getHeight());
558
559 for (int i = 0; i < this.shapeLayers.size(); i++) {
560 LayerShape ls = (LayerShape)this.shapeLayers.get(i);
561 ls.setParentSize(this.getHeight(), this.getWidth());
562 } //next layer
563
564 if (this.autofit || !this.fitOnce) {
565 this.autoFitShapes();
566 } //end if autofit
567
568 if (this.fisheyes != null) {
569 float width = (float)this.getWidth();
570 this.fisheyes.setLensRadius(width / 5f);
571
572 //System.out.println(this.fisheyes.getLensRadius());
573 }
574 //hack
575 //this.sendColorsToLayers(this.dataColorX.length);
576 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
577 ls.setObjectColors(this.objectColors);
578 //previous line results in sending colors to layers
579 paintDrawingBuff();
580 //this.repaint();
581 } //end if layers exist and size is > 0
582 //System.out.println("resizing component");
583 }
584
585 //end component event handling
586 //start accessors
587 public void setMode(int mode) {
588 if (mode == this.MODE_SELECT) {
589 this.fisheyes = null;
590 this.exLabels = null;
591 this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
592 }
593 else if (mode == this.MODE_PAN) {
594 this.setCursor(cursors.getCursor(GeoCursors.CURSOR_PAN));
595 }
596 else if (mode == this.MODE_ZOOM_IN) {
597 this.setCursor(cursors.getCursor(GeoCursors.CURSOR_ZOOM_IN));
598 }
599 else if (mode == this.MODE_ZOOM_OUT) {
600 this.setCursor(cursors.getCursor(GeoCursors.CURSOR_ZOOM_OUT));
601 }
602 else if (mode == this.MODE_EXCENTRIC) {
603 this.exLabels = new ExcentricLabels();
604 this.initExcentricLabels();
605 //this.exLabels.setVisible(true);
606 this.fisheyes = null;
607 this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
608 }
609 else if (mode == this.MODE_FISHEYE) {
610 this.exLabels = null;
611 this.fisheyes = new Fisheyes();
612 fisheyes.setLensType(Fisheyes.LENS_GAUSSIAN);
613 this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
614 }
615
616 else {
617 throw new IllegalArgumentException(
618 "MapCanvas.setMode, ecountered unknown mode");
619 }
620
621 this.mode = mode;
622 }
623
624 public void setBivarColorClasser(BivariateColorSymbolClassification
625 bivarColorClasser) {
626 this.bivarColorClasser = (BivariateColorSymbolClassificationSimple)
627 bivarColorClasser;
628
629 if (this.dataSet != null) {
630 this.sendColorsToLayers(this.dataSet.getNumObservations());
631 }
632 }
633
634 public void setAuxiliarySpatialData(Object[] spatialDataIn) {
635 //System.out.println("got spatial data 1");
636 if (spatialDataIn == null) {
637 return;
638 }
639 DataSetForApps auxData = new DataSetForApps();
640 auxData.setDataObject(spatialDataIn);
641 this.setAuxiliarySpatialData(auxData);
642 }
643
644 public void setAuxiliarySpatialData(DataSetForApps auxData) {
645 //System.out.println("got spatial data 2");
646 if (auxData == null) {
647 return;
648 }
649 LayerShape ls = null;
650 int layerType = auxData.getSpatialType();
651
652 if (layerType == DataSetForApps.SPATIAL_TYPE_POLYGON) {
653 ls = new LayerPolygon();
654 ls.setOriginalSpatialData(auxData.getShapeData());
655 spatialDataTypes.add(new Integer(DataSetForApps.SPATIAL_TYPE_POLYGON));
656
657 Shape[] userShapes = auxData.getShapeData();
658 userShapes = this.findFullExtentSpatialData(userShapes, true);
659 this.sendSpatialDataToLayer(ls, userShapes);
660 }
661 else if (layerType == DataSetForApps.SPATIAL_TYPE_POINT) {
662 LayerPoint lp = new LayerPoint();
663 Shape[] pointShapesOriginal = lp.pointsToShapes(auxData.getPoint2DData());
664 Shape[] pointShapesUser = this.findFullExtentSpatialData(
665 pointShapesOriginal, true);
666 Point2D[] userSpacePoints = lp.shapesToPoints(pointShapesUser);
667 Shape[] circleShapes = lp.findShapesForPoints(userSpacePoints);
668 ls.setOriginalSpatialData(pointShapesOriginal);
669 spatialDataTypes.add(new Integer(DataSetForApps.SPATIAL_TYPE_POINT));
670
671 //userSpaceSpatialData.add(circleShapes);
672 lp.setSpatialData(circleShapes);
673 ls = lp;
674 }
675 else {
676 throw new IllegalArgumentException(
677 "unexpected layer type ecountered in MapCanvas.setAuxiliarySpatialData");
678 }
679
680 //ok, default behaviours here:
681 //new layer goes on top of previous layer
682 //so add it to the end
683 //new layer has no fill
684 ls.setIsAuxiliary(true);
685 this.shapeLayers.add(ls);
686 ls.setParentSize(this.getHeight(), this.getWidth());
687 this.paintDrawingBuff();
688 this.repaint();
689 }
690
691 public void setDataSet(Object[] dataSetIn) {
692 String[] attributeArrays = (String[]) dataSetIn[0];
693 int len = attributeArrays.length;
694 this.dataSet = new DataSetForApps();
695 this.dataSet.setDataObject(dataSetIn);
696
697 if (dataSetIn[len + 1] == null) {
698 this.dataSet.setObservationNames(null);
699 }
700 else if (dataSetIn[len + 1] instanceof String[]) {
701 this.dataSet.setObservationNames( (String[]) dataSetIn[len + 1]);
702 }
703
704 this.setDataSet(this.dataSet);
705 this.initExcentricLabels();
706
707 //this.sendColorsToLayers(this.dataSet.getNumObservations());
708 }
709
710 public void setDataSet(DataSetForApps dataSet) {
711 this.dataColorX = null;
712 this.dataColorY = null;
713 this.currColorColumnX = -1;
714 this.currColorColumnY = -1;
715
716 this.dataSet = dataSet;
717 this.shapeLayers.removeAllElements();
718 this.variableNames = this.dataSet.getAttributeNamesNumeric();
719
720 int layerType = dataSet.getSpatialType();
721 LayerShape ls = null;
722 String[] attNames = dataSet.getAttributeNamesNumeric();
723 int numAttributes = attNames.length;
724
725 if (layerType == DataSetForApps.SPATIAL_TYPE_POLYGON) {
726 ls = new LayerPolygon();
727 ls.setOriginalSpatialData(dataSet.getShapeData());
728 spatialDataTypes.add(new Integer(DataSetForApps.SPATIAL_TYPE_POLYGON));
729
730 Shape[] userShapes = dataSet.getShapeData();
731 userShapes = this.findFullExtentSpatialData(userShapes, false);
732
733 //userSpaceSpatialData.add(userShapes);
734 this.sendSpatialDataToLayer(ls, userShapes);
735 }
736 else if (layerType == DataSetForApps.SPATIAL_TYPE_POINT) {
737 LayerPoint lp = new LayerPoint();
738 Shape[] pointShapesOriginal = lp.pointsToShapes(dataSet.getPoint2DData());
739 Shape[] pointShapesUser = this.findFullExtentSpatialData(
740 pointShapesOriginal, false);
741 Point2D[] userSpacePoints = lp.shapesToPoints(pointShapesUser);
742 Shape[] circleShapes = lp.findShapesForPoints(userSpacePoints);
743 lp.setOriginalSpatialData(pointShapesOriginal);
744 spatialDataTypes.add(new Integer(DataSetForApps.SPATIAL_TYPE_POINT));
745
746 //userSpaceSpatialData.add(circleShapes);
747 lp.setSpatialData(circleShapes);
748 ls = lp;
749 }
750 //System.out.println("activeLayer = " + activeLayer);
751
752 shapeLayers.add(ls);
753
754 //set default data to get color from
755 if ( (this.drawingBuff == null) && (this.getWidth() > 0) &&
756 (this.getHeight() > 0)) {
757 this.drawingBuff = this.createImage(this.getWidth(), this.getHeight());
758 }
759
760 if (this.drawingBuff != null) {
761 }
762
763 //resizing will autofit if this.autofit = true
764 //resizing resizes the drawing buffer, and repaints it
765 boolean realAutofit = this.autofit;
766 this.autofit = true;
767 this.componentResized(new ComponentEvent(this, 0));
768 this.autofit = realAutofit;
769
770 //this.sendColorsToLayers(this.dataSet.getNumObservations());
771 //paintDrawingBuff();
772 //repaint();
773 }
774
775 public void setTransformer(ShapeTransformer transformer) {
776 this.transformer = transformer;
777 }
778
779 public void setCurrColorColumnX(int currColorColumnX) {
780 if ( (this.dataSet != null) &&
781 (currColorColumnX <= dataSet.getNumberNumericAttributes())) {
782 this.currColorColumnX = currColorColumnX;
783 //XXX getNumericDataAsDouble has changed...
784 this.dataColorX = this.dataSet.getNumericDataAsDouble(currColorColumnX -
785 1);
786 this.sendColorsToLayers(this.dataColorX.length);
787 }
788 }
789
790 public int getCurrColorColumnX() {
791 return this.currColorColumnX;
792 }
793
794 public Color[] getColors() {
795 if (this.shapeLayers.size() == 0) {
796 return new Color[0];
797 }
798
799 LayerShape ls = (LayerShape)this.shapeLayers.elementAt(this.activeLayer);
800
801 return ls.getColors();
802 }
803
804 public void setCurrColorColumnY(int currColorColumnY) {
805 if ( (this.dataSet != null) &&
806 (currColorColumnY <= dataSet.getNumberNumericAttributes())) {
807 this.currColorColumnY = currColorColumnY;
808 //XXX getNumericDataAsDouble has changed...
809 this.dataColorY = this.dataSet.getNumericDataAsDouble(currColorColumnY -
810 1);
811 this.sendColorsToLayers(this.dataColorY.length);
812 }
813 }
814
815 public int getCurrColorColumnY() {
816 return this.currColorColumnY;
817 }
818
819 public void setIndication(int indication) {
820 if (fisheyes != null) {
821 //if we have fisheyes, this is too expensive!!!
822 //bail
823 return;
824 }
825
826 if (indication != this.indication) {
827 this.indication = indication;
828
829 if (shapeLayers.size() > 0) {
830 LayerShape ls = (LayerShape) shapeLayers.get(this.activeLayer);
831 ls.setIndication(indication);
832
833 if (indication >= 0 && indication < dataSet.getNumObservations()) {
834 this.drawTip = true;
835
836 Point p = ls.findCentroid(indication);
837 this.mouseX2 = (int) p.getX();
838 this.mouseY2 = (int) p.getY();
839 }
840 else {
841 this.drawTip = false;
842 }
843
844 this.makeToolTip(indication);
845 } //if we have at least one layer
846
847 //paintDrawingBuff();
848 this.repaint();
849 } //if indication is new
850 }
851
852 public void setSelectedObservations(Vector selectedObservations) {
853 this.selectedObservations = new int[selectedObservations.size()];
854
855 int i = 0;
856
857 for (Enumeration e = selectedObservations.elements(); e.hasMoreElements(); ) {
858 Integer bigIint = (Integer) e.nextElement();
859 this.selectedObservations[i] = bigIint.intValue();
860 i++;
861 }
862
863 this.setSelectedObservationsInt(this.selectedObservations);
864 }
865
866 public Vector getSelectedObservations() {
867 Vector v = new Vector();
868
869 for (int i = 0; i < selectedObservations.length; i++) {
870 v.add(new Integer(selectedObservations[i]));
871 }
872
873 return v;
874 }
875
876 public void setSelections(int[] selections) {
877 Vector v = new Vector();
878
879 for (int i = 0; i < selections.length; i++) {
880 if (selections[i] == 1) {
881 v.add(new Integer(i));
882 }
883 }
884
885 this.selectedObservations = new int[v.size()];
886
887 int i = 0;
888
889 for (Enumeration e = v.elements(); e.hasMoreElements(); ) {
890 Integer bigIint = (Integer) e.nextElement();
891 this.selectedObservations[i] = bigIint.intValue();
892 i++;
893 }
894
895 this.setSelectedObservationsInt(this.selectedObservations);
896 }
897
898 public int[] getSelections() {
899 int[] selections = new int[this.dataColorX.length];
900 if (this.selectedObservations == null) {
901 this.selectedObservations = new int[0];
902 }
903 for (int i = 0; i < this.selectedObservations.length; i++) {
904 selections[this.selectedObservations[i]] = 1;
905 }
906
907 return selections;
908 }
909
910 public void selectionChanged(SelectionEvent e) {
911 int[] sel = e.getSelection();
912 this.setSelectedObservationsInt(sel);
913 }
914
915 public void indicationChanged(IndicationEvent e) {
916 if (this == e.getSource()) {
917 return;
918 }
919
920 int indication = e.getIndication();
921 this.setIndication(indication);
922 }
923
924 public void dataSetChanged(DataSetEvent e) {
925 this.setDataSet(e.getDataSet());
926 }
927
928 public void setSelectedObservationsInt(int[] selectedObservations) {
929 this.selectedObservations = selectedObservations;
930
931 if (selectedObservations == null) {
932 return;
933 }
934
935 if ( (shapeLayers.size() > 0) && (this.drawingBuff != null)) {
936 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
937 ls.setSelectedObservations(this.selectedObservations);
938 paintDrawingBuff();
939 this.repaint();
940 }
941 else if ( (shapeLayers.size() > 0) && (this.drawingBuff == null) &&
942 (this.selectedObservations.length > 1)) { //means we have data but are not visible yet
943
944 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
945 ls.setSelectedObservations(this.selectedObservations);
946 }
947 }
948
949 public int[] getSelectedObservationsInt() {
950 return this.selectedObservations;
951 }
952
953 public void setColorSelection(Color colorSelection) {
954 this.colorSelection = colorSelection;
955
956 if (shapeLayers.size() > 0) {
957 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
958 LayerShape ls = (LayerShape) e.nextElement();
959 ls.setColorSelection(colorSelection);
960 }
961
962 paintDrawingBuff();
963 this.repaint();
964 }
965 }
966
967 public boolean getSelOriginalColorMode() {
968 return selOriginalColorMode;
969 }
970
971 public void setSelOriginalColorMode(boolean selOriginalColorMode) {
972 this.selOriginalColorMode = selOriginalColorMode;
973 if (shapeLayers == null) {
974 return;
975 }
976 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
977 LayerShape ls = (LayerShape) e.nextElement();
978 ls.setSelOriginalColorMode(selOriginalColorMode);
979 }
980
981 paintDrawingBuff();
982 this.repaint();
983
984 }
985
986 public void setBackground(Color c) {
987 super.setBackground(c);
988 if (shapeLayers == null) {
989 return;
990 }
991 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
992 LayerShape ls = (LayerShape) e.nextElement();
993 ls.setColorBackground(c);
994 }
995
996 paintDrawingBuff();
997 this.repaint();
998
999 }
1000
1001 /***
1002 * put your documentation comment here
1003 * @param conditionArray
1004 */
1005 public void setConditionArray(int[] conditionArray) {
1006 if (shapeLayers.size() > 0 && drawingBuff != null) {
1007 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
1008 LayerShape ls = (LayerShape) e.nextElement();
1009 ls.setConditionArray(conditionArray);
1010 }
1011
1012 paintDrawingBuff();
1013 this.repaint();
1014 }
1015 }
1016
1017 //end accessors
1018 public void actionPerformed(ActionEvent e) {
1019 //* this method used for testing only...
1020 String source = e.getSource().toString();
1021 String command = e.getActionCommand();
1022
1023 if (e.getSource()instanceof ConditionManager) {
1024 ConditionManager cm = (ConditionManager) e.getSource();
1025 int[] conditionArray = cm.getConditionResults();
1026 this.setConditionArray(conditionArray);
1027 }
1028
1029 //*/
1030 }
1031
1032 //start mouse event handling
1033
1034 /***
1035 * Draws a bounding box for selection.
1036 * @param e
1037 */
1038 public void mouseDragged(MouseEvent e) {
1039 this.drawBox = true;
1040 this.drawTip = false;
1041
1042 if (mode == this.MODE_PAN) {
1043 Cursor grabCur = cursors.getCursor(GeoCursors.CURSOR_GRAB);
1044
1045 if (this.getCursor() != grabCur) {
1046 this.setCursor(grabCur);
1047 }
1048 }
1049
1050 mouseX2 = e.getX();
1051 mouseY2 = e.getY();
1052
1053 if (mode == this.MODE_PAN) {
1054 panBuff(mouseX1, mouseX2, mouseY1, mouseY2);
1055 }
1056
1057 repaint();
1058 }
1059
1060 /***
1061 * Activates a tool tip.
1062 * @param e
1063 */
1064 public void mouseMoved(MouseEvent e) {
1065 if (this.shapeLayers.size() < 1) {
1066 return;
1067 }
1068
1069 if (fisheyes != null) {
1070 fisheyes.setFocus(e.getX(), e.getY());
1071 repaint();
1072 }
1073
1074 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
1075 int indic = ls.findIndication(e.getX(), e.getY());
1076
1077 if (indic != indication) {
1078 this.setIndication(indic);
1079
1080 int xClass = -1;
1081 int yClass = -1;
1082
1083 if (indic > 0) {
1084 xClass = this.bivarColorClasser.getClassX(indic);
1085 yClass = this.bivarColorClasser.getClassY(indic);
1086 }
1087
1088 this.fireIndicationChanged(indic, xClass, yClass);
1089 }
1090
1091 mouseX2 = e.getX();
1092 mouseY2 = e.getY();
1093 }
1094
1095 /***
1096 * Inits selection bounding box.
1097 * @param e
1098 */
1099 public void mousePressed(MouseEvent e) {
1100 mouseX1 = e.getX();
1101 mouseY1 = e.getY();
1102 mouseX2 = e.getX();
1103 mouseY2 = e.getY();
1104 }
1105
1106 /***
1107 * Makes selection.
1108 * @param e
1109 */
1110 public void mouseReleased(MouseEvent e) {
1111 if (this.dataSet == null) {
1112 return;
1113 }
1114
1115 if (mode == this.MODE_PAN) {
1116 this.setCursor(cursors.getCursor(GeoCursors.CURSOR_PAN));
1117 }
1118
1119 panningXForm.setToIdentity();
1120
1121 mouseX2 = e.getX();
1122 mouseY2 = e.getY();
1123
1124 if (mode == this.MODE_SELECT) {
1125 if (mouseX1 > mouseX2) {
1126 int temp = mouseX1;
1127 mouseX1 = mouseX2;
1128 mouseX2 = temp;
1129 }
1130
1131 if (mouseY1 > mouseY2) {
1132 int temp = mouseY1;
1133 mouseY1 = mouseY2;
1134 mouseY2 = temp;
1135 }
1136
1137 if (e.isShiftDown()) {
1138 this.makeSelectionShift(mouseX1, mouseX2 + 1, mouseY1, mouseY2 + 1);
1139 }
1140 else {
1141 this.makeSelection(mouseX1, mouseX2 + 1, mouseY1, mouseY2 + 1);
1142 }
1143 }
1144 else if (mode == this.MODE_ZOOM_IN) {
1145 this.zoomIn(mouseX1, mouseX2, mouseY1, mouseY2);
1146 }
1147 else if (mode == this.MODE_ZOOM_OUT) {
1148 this.zoomOut(mouseX1, mouseX2, mouseY1, mouseY2);
1149 }
1150 else if (mode == this.MODE_PAN) {
1151 this.pan(mouseX1, mouseX2, mouseY1, mouseY2);
1152 }
1153
1154 this.drawBox = false;
1155 repaint();
1156 }
1157
1158 /***
1159 * makes crosshair cursor
1160 * @param e
1161 */
1162 public void mouseEntered(MouseEvent e) {
1163 }
1164
1165 /***
1166 * resets cursor
1167 * @param e
1168 */
1169 public void mouseExited(MouseEvent e) {
1170 e.consume();
1171 this.drawTip = false; //prevents toolip from drawing
1172 this.drawBox = false;
1173 this.repaint();
1174 this.setIndication( -1);
1175 this.fireIndicationChanged( -1, 0, 0);
1176
1177 if (fisheyes != null) {
1178 fisheyes.setFocus( -1000f, -1000f);
1179 }
1180 }
1181
1182 /***
1183 * pop up a detail map
1184 * @param e
1185 */
1186 public void mouseClicked(MouseEvent e) {
1187 if ( (e.getSource() == this) && (e.getClickCount() > 1)) { // This is a double-click or triple...
1188
1189 //if (dataIndices[0] != dataIndices[1]) { //why this??? I guess we don't want to pop up one from the
1190 //diagonal if we are a scatterplot
1191 GeoMap detailMap = new GeoMap();
1192 detailMap.setBackground(this.getBackground());
1193 detailMap.setDataSet(this.dataSet.getDataObjectOriginal());
1194 detailMap.setBivarColorClasser(this.bivarColorClasser);
1195 detailMap.setSelectedObservations(this.getSelectedObservationsInt()); //need to do this here because
1196
1197 //otherwise the selection won't "take"
1198 detailMap.setXVariable(currColorColumnX);
1199 detailMap.setXChooserMode(GeoMap.VARIABLE_CHOOSER_MODE_FIXED);
1200 detailMap.setYVariable(currColorColumnY);
1201 detailMap.setYChooserMode(GeoMap.VARIABLE_CHOOSER_MODE_FIXED);
1202
1203 JFrame dummyFrame = new JFrame();
1204 JDialog detailMapFrame = new JDialog(dummyFrame, "Detail Map", true);
1205
1206 detailMapFrame.setLocation(300, 300);
1207 detailMapFrame.setSize(300, 300);
1208 detailMapFrame.getContentPane().setLayout(new BorderLayout());
1209 detailMapFrame.getContentPane().add(detailMap, BorderLayout.CENTER);
1210
1211 CoordinationManager cm = new CoordinationManager();
1212 cm.addBean(this);
1213 cm.addBean(detailMap);
1214
1215 detailMapFrame.show();
1216
1217 //}//end dataIndeces
1218 } //end if doubleclick
1219 } //end method
1220
1221 private void makeSelection(int x1, int x2, int y1, int y2) {
1222 int xDiff = Math.abs(x2 - x1);
1223 int yDiff = Math.abs(y2 - y1);
1224 int minPixels = 3;
1225
1226 if ( (xDiff < minPixels) && (yDiff < minPixels)) {
1227 return;
1228 }
1229
1230 if (shapeLayers.size() > 0) {
1231 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
1232 ls.findSelection(x1, x2, y1, y2);
1233 this.selectedObservations = ls.getSelectedObservations();
1234
1235 //let's try just redrawing the selection
1236 //for (int i = 0; i < selectedObservations.length; i++) {
1237 ls.setSelectedObservations(selectedObservations);
1238
1239 this.fireActionPerformed(LayerShape.COMMAND_SELECTION);
1240 this.fireSelectionChanged(this.selectedObservations);
1241
1242 //unfortunately, we need to completely redraw any aux layers
1243 this.paintAuxLayers();
1244
1245 //XXX shouldn't have to do this
1246 paintDrawingBuff();
1247 this.repaint();
1248 }
1249 } //method
1250
1251 private void makeSelectionShift(int x1, int x2, int y1, int y2) {
1252 if (shapeLayers.size() > 0) {
1253 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
1254 LayerShape ls = (LayerShape) e.nextElement();
1255 ls.findSelectionShift(x1, x2, y1, y2);
1256 this.selectedObservations = ls.getSelectedObservations();
1257 }
1258
1259 this.fireActionPerformed(LayerShape.COMMAND_SELECTION);
1260 paintDrawingBuff();
1261 this.repaint();
1262 }
1263 }
1264
1265 //end mouse event handling
1266
1267 /***
1268 * Attention all layers! paint yourselves onto the buffer.
1269 * @param g
1270 */
1271 private void paintDrawingBuff() {
1272 if (this.drawingBuff == null) {
1273 return;
1274 }
1275
1276 Graphics g = this.drawingBuff.getGraphics();
1277 Graphics2D g2 = (Graphics2D) g;
1278 g.setColor(this.getBackground());
1279 g.fillRect(0, 0, this.getWidth(), this.getHeight());
1280
1281 if (shapeLayers.size() > 0) {
1282 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
1283 LayerShape ls = (LayerShape) e.nextElement();
1284 ls.fisheyes = this.fisheyes;
1285 ls.render(g2); //paint your whole self
1286 } //next element
1287 } //end if
1288 }
1289
1290 /***
1291 * Attention all auxiliary layers! paint yourselves onto the buffer.
1292 * @param g
1293 */
1294 private void paintAuxLayers() {
1295 if (this.drawingBuff == null) {
1296 return;
1297 }
1298
1299 Graphics g = this.drawingBuff.getGraphics();
1300 Graphics2D g2 = (Graphics2D) g;
1301
1302 if (shapeLayers.size() > 0) {
1303 for (Enumeration e = shapeLayers.elements(); e.hasMoreElements(); ) {
1304 LayerShape ls = (LayerShape) e.nextElement();
1305
1306 if (ls.getIsAuxiliary()) { //if you are aux
1307 ls.fisheyes = this.fisheyes;
1308 ls.render(g2); //paint your whole self
1309 } //end if aux
1310 } //next element
1311 } //end if
1312 }
1313
1314 /***
1315 * paints buffer, then drawing box
1316 * @param g
1317 */
1318 public void paintComponent(Graphics g) {
1319 super.paintComponent(g);
1320 Graphics2D g2 = (Graphics2D) g;
1321
1322 if ( (this.drawingBuff == null) || (this.fisheyes != null)) {
1323 this.drawingBuff = this.createImage(this.getWidth(), this.getHeight());
1324 paintDrawingBuff();
1325 }
1326
1327 if (this.drawingBuff != null) {
1328 g2.drawImage(this.drawingBuff, this.panningXForm, this);
1329
1330 //g.drawImage(this.drawingBuff,0,0,this);
1331 }
1332 else {
1333 g.fillRect(0, 0, this.getWidth(), this.getHeight());
1334 }
1335
1336 if ( (this.indication != Integer.MIN_VALUE) && (shapeLayers.size() > 0) &&
1337 (this.mode != this.MODE_PAN) && (this.fisheyes == null)) {
1338 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
1339 ls.renderObservation(indication, g2);
1340 }
1341
1342 drawSelectionBox(g2);
1343
1344 //this.toolTip.paint(g);
1345 if (this.drawTip && (exLabels != null) &&
1346 (this.exLabels.isVisible() == false)) {
1347 drawTooltip(g2, this.tipText, this.mouseX2, this.mouseY2, Color.lightGray);
1348 }
1349
1350 if (exLabels != null) {
1351 exLabels.paint(g2, getBounds());
1352 }
1353 }
1354
1355 /***
1356 * Helper function to draw a "tooltip" on the given graphics object.
1357 *
1358 * @param g2 The Graphics2D Object to draw on.
1359 * @param text The (multiline) text of the tooltip.
1360 * @param x The x coordinate.
1361 * @param y The y coordinate.
1362 * @param col The background color.
1363 */
1364 private void drawTooltip(Graphics2D g2, String text, int x, int y, Color col) {
1365 if (!drawTip) {
1366 return;
1367 }
1368
1369 int i;
1370 int mheight;
1371 int mwidth = 0;
1372 int numLines;
1373 int lineHeight;
1374 Font f = g2.getFont();
1375 tipFont = f.deriveFont(9f);
1376 g2.setFont(tipFont);
1377
1378 StringTokenizer tok = new StringTokenizer(text, "\n");
1379 numLines = tok.countTokens();
1380
1381 String[] lines = new String[numLines];
1382
1383 for (i = 0; i < numLines; i++) {
1384 lines[i] = tok.nextToken();
1385
1386 int tempwidth = g2.getFontMetrics().stringWidth(lines[i]) + 6;
1387
1388 if (tempwidth > mwidth) {
1389 mwidth = tempwidth;
1390 }
1391 }
1392
1393 lineHeight = g2.getFontMetrics().getHeight();
1394 mheight = (numLines * lineHeight) + 2;
1395
1396 x += 10;
1397 y += 10;
1398
1399 //if we are too close to the right side....
1400 if ( (x + mwidth) > this.getWidth()) {
1401 x -= (mwidth + 20);
1402 }
1403
1404 //if we are too close to the bottom...
1405 if ( (y + mheight) > this.getHeight()) {
1406 y -= (mheight + 20);
1407 }
1408
1409 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
1410 0.7f);
1411 g2.setComposite(ac);
1412
1413 g2.setStroke(new BasicStroke(0.5f));
1414 g2.setColor(new Color(0.2f, 0.2f, 0.2f, 0.7f));
1415
1416 //g2.drawRect(x, y, mwidth, mheight);
1417 g2.setColor(col);
1418 g2.fillRect(x + 1, y + 1, mwidth - 1, mheight - 1);
1419
1420 g2.setColor(Color.black);
1421
1422 ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
1423 g2.setComposite(ac);
1424
1425 for (i = 0; i < numLines; i++) {
1426 g2.drawString(lines[i], x + 3, (y + ( (i + 1) * lineHeight)) - 4);
1427 }
1428 }
1429
1430 private void drawSelectionBox(Graphics2D g2) {
1431 //draw selection box
1432 if (!drawBox) {
1433 return;
1434 }
1435
1436 Stroke tempStroke = g2.getStroke();
1437 Stroke boxStroke = null;
1438
1439 if (this.mode == this.MODE_SELECT) {
1440 boxStroke = this.dashStroke;
1441 }
1442 else if ( (this.mode == this.MODE_ZOOM_IN) ||
1443 (this.mode == this.MODE_ZOOM_OUT)) {
1444 boxStroke = this.solidStroke;
1445 }
1446 else {
1447 return;
1448 }
1449
1450 g2.setStroke(boxStroke);
1451 g2.setPaintMode();
1452 g2.setColor(Color.black);
1453 g2.setXORMode(Color.white);
1454
1455 //let's take drawing the selection rectangle by cases
1456 //not elegant, but the alternative is introducing more class variables
1457 int selectX = 0;
1458 int selectY = 0;
1459 int selectWidth = 0;
1460 int selectHeight = 0;
1461
1462 if ( (mouseX1 <= mouseX2) && (mouseY1 <= mouseY2)) {
1463 selectX = mouseX1;
1464 selectY = mouseY1;
1465 selectWidth = mouseX2 - mouseX1;
1466 selectHeight = mouseY2 - mouseY1;
1467 }
1468
1469 if ( (mouseX2 < mouseX1) && (mouseY1 <= mouseY2)) {
1470 selectX = mouseX2;
1471 selectY = mouseY1;
1472 selectWidth = mouseX1 - mouseX2;
1473 selectHeight = mouseY2 - mouseY1;
1474 }
1475
1476 if ( (mouseX1 <= mouseX2) && (mouseY2 < mouseY1)) {
1477 selectX = mouseX1;
1478 selectY = mouseY2;
1479 selectWidth = mouseX2 - mouseX1;
1480 selectHeight = mouseY1 - mouseY2;
1481 }
1482
1483 if ( (mouseX2 < mouseX1) && (mouseY2 < mouseY1)) {
1484 selectX = mouseX2;
1485 selectY = mouseY2;
1486 selectWidth = mouseX1 - mouseX2;
1487 selectHeight = mouseY1 - mouseY2;
1488 }
1489
1490 g2.drawRect(selectX, selectY, selectWidth, selectHeight);
1491 g2.setStroke(tempStroke);
1492 }
1493
1494 //start excentric labeling stuff
1495 private void initExcentricLabels() {
1496 if (exLabels != null) {
1497 this.exLabels = new ExcentricLabels();
1498 exLabels.setComponent(this);
1499 exLabels.setOpaque(true);
1500
1501 Color halfWhite = new Color(255, 255, 255, 123);
1502 exLabels.setBackgroundColor(halfWhite);
1503 this.addMouseListener(exLabels);
1504 }
1505 }
1506
1507 public String getObservationLabel(int i) {
1508 String[] labels = this.dataSet.getObservationNames();
1509 String label = labels[i];
1510
1511 return label;
1512 }
1513
1514 public Shape getShapeAt(int i) {
1515 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
1516 Shape shp = ls.getSpatialData()[i];
1517
1518 return shp;
1519 }
1520
1521 public int[] pickAll(Rectangle2D hitBox) {
1522 LayerShape ls = (LayerShape)this.shapeLayers.get(this.activeLayer);
1523 int[] selObs = ls.findSelection(hitBox);
1524
1525 return selObs;
1526 }
1527
1528 //end excentric labeling stuff
1529
1530 /***
1531 * implements ActionListener
1532 */
1533 public void addActionListener(ActionListener l) {
1534 listenerList.add(ActionListener.class, l);
1535 }
1536
1537 /***
1538 * removes an ActionListener from the button
1539 */
1540 public void removeActionListener(ActionListener l) {
1541 listenerList.remove(ActionListener.class, l);
1542 }
1543
1544 /***
1545 * Notify all listeners that have registered interest for
1546 * notification on this event type. The event instance
1547 * is lazily created using the parameters passed into
1548 * the fire method.
1549 * @see EventListenerList
1550 */
1551 protected void fireActionPerformed(String command) {
1552 // Guaranteed to return a non-null array
1553 Object[] listeners = listenerList.getListenerList();
1554 ActionEvent e = null;
1555
1556 // Process the listeners last to first, notifying
1557 // those that are interested in this event
1558 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1559 if (listeners[i] == ActionListener.class) {
1560 // Lazily create the event:
1561 if (e == null) {
1562 e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command);
1563 }
1564
1565 ( (ActionListener) listeners[i + 1]).actionPerformed(e);
1566 }
1567 }
1568 }
1569
1570 /***
1571 * adds an IndicationListener
1572 */
1573 public void addIndicationListener(IndicationListener l) {
1574 listenerList.add(IndicationListener.class, l);
1575 }
1576
1577 /***
1578 * removes an IndicationListener from the component
1579 */
1580 public void removeIndicationListener(IndicationListener l) {
1581 listenerList.remove(IndicationListener.class, l);
1582 }
1583
1584 /***
1585 * Notify all listeners that have registered interest for
1586 * notification on this event type. The event instance
1587 * is lazily created using the parameters passed into
1588 * the fire method.
1589 * @see EventListenerList
1590 */
1591 private void fireIndicationChanged(int newIndication, int xClass, int yClass) {
1592 // Guaranteed to return a non-null array
1593 Object[] listeners = listenerList.getListenerList();
1594 IndicationEvent e = null;
1595
1596 // Process the listeners last to first, notifying
1597 // those that are interested in this event
1598 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1599 if (listeners[i] == IndicationListener.class) {
1600 // Lazily create the event:
1601 if (e == null) {
1602 e = new IndicationEvent(this, newIndication, xClass, yClass);
1603 }
1604
1605 ( (IndicationListener) listeners[i + 1]).indicationChanged(e);
1606 }
1607 } //next i
1608 }
1609
1610 /***
1611 * adds an SelectionListener
1612 */
1613 public void addSelectionListener(SelectionListener l) {
1614 //System.out.println("mapCan, selection listeners = " + listenerList.getListenerCount(SelectionListener.class));
1615 listenerList.add(SelectionListener.class, l);
1616 }
1617
1618 /***
1619 * removes an SelectionListener from the component
1620 */
1621 public void removeSelectionListener(SelectionListener l) {
1622 //System.out.println("mapCan, removing a selection listener");
1623 listenerList.remove(SelectionListener.class, l);
1624 }
1625
1626 /***
1627 * Notify all listeners that have registered interest for
1628 * notification on this event type. The event instance
1629 * is lazily created using the parameters passed into
1630 * the fire method.
1631 * @see EventListenerList
1632 */
1633 private void fireSelectionChanged(int[] newSelection) {
1634 // Guaranteed to return a non-null array
1635 Object[] listeners = listenerList.getListenerList();
1636 SelectionEvent e = null;
1637
1638 // Process the listeners last to first, notifying
1639 // those that are interested in this event
1640 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1641 if (listeners[i] == SelectionListener.class) {
1642 // Lazily create the event:
1643 if (e == null) {
1644 e = new SelectionEvent(this, newSelection);
1645 }
1646
1647 ( (SelectionListener) listeners[i + 1]).selectionChanged(e);
1648 }
1649 } //next i
1650 }
1651
1652 /***
1653 * adds an SpatialExtentListener
1654 */
1655 public void addSpatialExtentListener(SpatialExtentListener l) {
1656 listenerList.add(SpatialExtentListener.class, l);
1657 }
1658
1659 /***
1660 * removes an SpatialExtentListener from the component
1661 */
1662 public void removeSpatialExtentListener(SpatialExtentListener l) {
1663 listenerList.remove(SpatialExtentListener.class, l);
1664 }
1665
1666 /***
1667 * Notify all listeners that have registered interest for
1668 * notification on this event type. The event instance
1669 * is lazily created using the parameters passed into
1670 * the fire method.
1671 * @see EventListenerList
1672 */
1673 private void fireSpatialExtentChanged(Rectangle2D newSpatialExtent) {
1674 // Guaranteed to return a non-null array
1675 Object[] listeners = listenerList.getListenerList();
1676 SpatialExtentEvent e = null;
1677
1678 // Process the listeners last to first, notifying
1679 // those that are interested in this event
1680 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1681 if (listeners[i] == SpatialExtentListener.class) {
1682 // Lazily create the event:
1683 if (e == null) {
1684 e = new SpatialExtentEvent(this, newSpatialExtent);
1685 }
1686
1687 ( (SpatialExtentListener) listeners[i + 1]).spatialExtentChanged(e);
1688 }
1689 } //next i
1690 }
1691 }
This page was automatically generated by Maven