1 /* -------------------------------------------------------------------
2 GeoVISTA Center (Penn State, Dept. of Geography)
3 Java source file for the class SpaceFillCanvas
4 Copyright (c), 2002, GeoVISTA Center
5 All Rights Reserved.
6 Original Author: Frank Hardisty
7 $Author: xpdai $
8 $Id: SpaceFillCanvas.java,v 1.6 2003/09/05 13:02:45 xpdai Exp $
9 $Date: 2003/09/05 13:02:45 $
10 Reference: Document no:
11 ___ ___
12 ------------------------------------------------------------------- *
13
14 */
15 package edu.psu.geovista.app.spacefill;
16
17 import edu.psu.geovista.classification.*;
18 import edu.psu.geovista.data.*;
19 import edu.psu.geovista.data.geog.*;
20 import edu.psu.geovista.symbolization.*;
21 import edu.psu.geovista.ui.event.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import java.awt.geom.*;
26 import java.awt.image.*;
27
28 import java.util.*;
29
30 import javax.swing.*;
31
32
33 public class SpaceFillCanvas extends JPanel implements MouseListener,
34 MouseMotionListener,
35 ComponentListener,
36 SelectionListener
37
38 {
39 private static final int COLUMN_ORIGINAL_DATA = 0; //for use with pixelOrder
40 private static final int COLUMN_ORIGINAL_ORDER = 1; //for use with pixelOrder
41 private static final int COLUMN_DATA_ORDER = 2; //for use with pixelOrder
42 private static final int NUM_DATA_COLUMNS = 3; //for use with pixelOrder
43 public static final String COMMAND_SELECTION = "cmdSel";
44 public static final String COMMAND_COLOR_CLASSFICIATION = "colorClass";
45 transient private AffineTransform xform;
46 transient private int[] classification;
47 transient private int[] focus;
48 transient private int[] pixelColors; //reflected in pixelBuff
49 transient private int[] pixelColorsOriginal; //reflected in pixelBuff
50 transient private String[] observationNames;
51 transient private double[][] pixelOrder; // row, column //reflected in pixelBuff
52 transient private int[][] pixelIndex; //reflected in pixelBuff
53 transient private int[] selectedObservations;
54 transient private int[] conditioning;
55 transient private int[] selectedObservationsOld;
56 transient private int mouseX1;
57 transient private int mouseX2;
58 transient private int mouseY1;
59 transient private int mouseY2;
60 private int indication;
61 private Color[] colors;
62 private int fillOrder;
63 private Object[] data;
64 private DataSetForApps dataSet;
65 private String[] variableNames;
66 private BufferedImage pixelBuff;
67 private Image drawingBuff;
68 private int currOrderColumn;
69 private int currColorColumn;
70
71 //Colors
72 private Color colorSelection;
73 private boolean selOriginalColorMode;
74 private Color colorIndication;
75 private Color colorNull;
76 private Color colorOutOfFocus;
77 private Color colorNotInStudyArea;
78
79 //transient private BivariateColorSymbolClassification bivarColorClasser;
80 transient private ColorSymbolClassification colorClasser;
81 private Shape[] originalSpatialData;
82 private Shape[] drawingShapes;
83 private boolean useDrawingShapes;
84
85 private transient int borderThickness = 1;
86
87 public SpaceFillCanvas() {
88 this.indication = Integer.MIN_VALUE;
89 this.setBorder(BorderFactory.createLineBorder(Color.black,this.borderThickness));
90 ColorSymbolClassificationSimple biColorer = new ColorSymbolClassificationSimple();
91 this.colorClasser = biColorer;
92
93 this.useDrawingShapes = true;
94 this.observationNames = null;
95 this.fillOrder = FillOrder.FILL_ORDER_SCAN_LINE;
96
97 this.selectedObservationsOld = new int[0];
98 this.selectedObservations = new int[0];
99 this.makeBuff(1, 1);
100 this.xform = new AffineTransform();
101 this.initColors();
102 //this.setMinimumSize(new Dimension(50, 50));
103 this.setPreferredSize(new Dimension(300, 300));
104 this.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
105 currOrderColumn = -1;
106 this.currColorColumn = -1;
107 this.addMouseListener(this);
108 addMouseMotionListener(this);
109
110 this.addComponentListener(this);
111
112 //orders to implement (in order): Morton
113 }
114
115 //
116 private void initColors() {
117 //let's set default colors
118 //in some far-off happy day this will be set from user prefs
119 colorSelection = Color.blue;
120 colorIndication = Color.green;
121 colorNull = Color.white;
122 colorOutOfFocus = this.getBackground();
123 colorNotInStudyArea = Color.black;
124 this.colors = null; //new Color[1000];
125 }
126
127 private void makeBuff(int width, int height) {
128 pixelBuff = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
129 }
130
131 private void makeXform() {
132 xform.setToIdentity();
133 double borderWidth = (double)this.borderThickness;
134 //xform.translate(borderWidth,borderWidth);
135 double sx = (double) (this.getWidth())/ (double) pixelBuff.getWidth();
136 double sy = (double) (this.getHeight()) / (double) pixelBuff.getHeight();
137 xform.setToScale(sx, sy);
138
139 }
140
141 private void refreshMembers() {
142 if (data == null) {
143 return;
144 } else if (this.currOrderColumn == -1) { //no numeric data
145
146 return;
147 }
148
149 int len = this.dataSet.getNumObservations();
150
151 //init bufferedImage if need be
152 int height = this.pixelIndex.length; //nRows
153 int width = this.pixelIndex[0].length; //nColumns
154
155 if ((this.pixelBuff.getWidth() != width) ||
156 (this.pixelBuff.getHeight() != height)) {
157 this.makeBuff(width, height);
158 }
159
160 //init pixel order if need be
161 if (pixelOrder == null) {
162 this.pixelOrder = new double[len][this.NUM_DATA_COLUMNS];
163 } else if ((this.pixelOrder.length != len) ||
164 (this.pixelOrder[0].length != this.NUM_DATA_COLUMNS)) {
165 this.pixelOrder = new double[len][this.NUM_DATA_COLUMNS];
166 }
167
168 //init pixel colors if need be
169 if (pixelColors == null) {
170 this.pixelColors = new int[len];
171 this.pixelColorsOriginal = new int[len];
172 } else if (pixelColors.length != len) {
173 this.pixelColors = new int[len];
174 this.pixelColorsOriginal = new int[len];
175 }
176 }
177
178 //start methods for manipulating dataSet of Object[]
179 private String findValueOf(Object obj, int place) {
180 if (obj instanceof double[]) {
181 double[] dataArray = (double[]) obj;
182
183 return String.valueOf(dataArray[place]);
184 } else if (obj instanceof int[]) {
185 int[] dataArray = (int[]) obj;
186
187 return String.valueOf(dataArray[place]);
188 } else if (obj instanceof String[]) {
189 String[] dataArray = (String[]) obj;
190
191 return String.valueOf(dataArray[place]);
192 } else {
193 throw new IllegalArgumentException(
194 "obj passed in must be a String[], double[] or int[]");
195 }
196 }
197
198 //end methods for manipulating dataSet of Object[]
199 private void findBuffFillOrder() {
200 //this.pixelIndex = FillOrderScan.getFillOrder(data[0].length, this.pixelIndex);
201 if (this.currOrderColumn == -1) { //no numeric data
202
203 return;
204 }
205
206 int len = this.dataSet.getNumObservations();
207
208 this.pixelIndex = FillOrder.findFillOrder(len, this.pixelIndex,
209 this.fillOrder);
210
211 //init bufferedImage if need be
212 int height = this.pixelIndex.length; //nRows
213 int width = this.pixelIndex[0].length; //nColumns
214
215 if ((this.pixelBuff.getWidth() != width) ||
216 (this.pixelBuff.getHeight() != height)) {
217 this.makeBuff(width, height);
218 }
219 }
220
221 private static void findPixelOrder(Object[] data, double[][] pixOrder,
222 int orderColumn) {
223 if (orderColumn < 0) {
224 return;
225 }
226
227 //we need to get our data in numeric form.
228 double[] doubleData = null;
229
230 if (data[orderColumn] instanceof double[]) {
231 doubleData = (double[]) data[orderColumn];
232 } else if (data[orderColumn] instanceof int[]) {
233 int[] intData = (int[]) data[orderColumn];
234 doubleData = new double[intData.length];
235
236 for (int i = 0; i < intData.length; i++) {
237 doubleData[i] = intData[i];
238 } //next i
239 } else {
240 throw new IllegalArgumentException(
241 "obj passed in must be a double[] or int[]");
242 }
243
244 //pixelOrder[][] is in row, column order (Frank)
245 //first let's get the data and set the index
246 for (int i = 0; i < pixOrder.length; i++) {
247 pixOrder[i][SpaceFillCanvas.COLUMN_ORIGINAL_ORDER] = i;
248 pixOrder[i][SpaceFillCanvas.COLUMN_ORIGINAL_DATA] = doubleData[i];
249 } //next i
250
251
252 //now sort on the data
253 ArraySort2D.sortDouble(pixOrder, SpaceFillCanvas.COLUMN_ORIGINAL_DATA);
254
255 //now add the index for pixeling by
256 for (int i = 0; i < pixOrder.length; i++) {
257 pixOrder[i][SpaceFillCanvas.COLUMN_DATA_ORDER] = i;
258 } //next i
259 }
260
261 //public static void colorPixels(BufferedImage buffIm, double[][] pixOrder, int[] pixColors, int[][] pixIndex){
262 private void colorPixels() {
263 for (int i = 0; i < this.pixelIndex.length; i++) { //row
264
265 for (int j = 0; j < pixelIndex[0].length; j++) { //column
266
267 //step 1: find the index from the order array
268 int rgb = 0;
269 int buffIndex = pixelIndex[i][j];
270
271 //if it is outside the space fill viz (can't make it a rectangle...)
272 if (buffIndex == Integer.MIN_VALUE) {
273 //rgb = this.colorNotInStudyArea.getRGB();
274 rgb = this.colorNotInStudyArea.getRGB();
275 } else {
276 //find out what element is the 'buffIndex'th one when sorted
277 int arrayIndex = (int) Math.round(
278 pixelOrder[buffIndex][SpaceFillCanvas.COLUMN_ORIGINAL_ORDER]);
279
280 //is it conditioned out?
281 if (this.conditioning[arrayIndex] < 0){
282 rgb = this.getBackground().getRGB();
283 }
284 else {
285 //what color is that bad boy?
286 rgb = pixelColors[arrayIndex];
287 }
288
289 //let's find the red val
290 //Color aColor = new Color(rgb);
291 //int red = aColor.getRed();
292 }
293
294 pixelBuff.setRGB(j, i, rgb);
295 }
296 }
297
298 paintBuffer();
299 }
300
301 private void colorCurrSelection() {
302 for (int i = 0; i < this.selectedObservations.length; i++) {
303 int j = this.selectedObservations[i];
304 this.pixelColors[j] = this.colorSelection.getRGB();
305 }
306 }
307
308 private void colorNewSelection(int[] selectedObservationsOld) {
309 for (int i = 0; i < selectedObservationsOld.length; i++) {
310 this.pixelColors[selectedObservationsOld[i]] = this.pixelColorsOriginal[selectedObservationsOld[i]];
311 }
312
313 this.colorCurrSelection();
314 this.colorCurrIndication();
315 }
316
317 private void colorCurrIndication() {
318 if (this.indication >= 0) {
319 this.pixelColors[indication] = this.colorIndication.getRGB();
320 }
321 }
322
323 //note: there are two preconditions to this method working correctly:
324 //the oldIndication must be set correcty, and this.indication must
325 //reflect the new one.
326 private void colorNewIndication(int oldIndication) {
327 //first let's color the old indication correctly
328 if (oldIndication >= 0) {
329 this.pixelColors[oldIndication] = this.pixelColorsOriginal[oldIndication];
330 }
331
332 this.colorCurrSelection();
333 this.colorCurrIndication();
334 }
335
336 private void findPixelColors(Object dataColors) {
337 int len = -1;
338
339 //doubleData = null;
340 if (dataColors instanceof double[]) {
341 double[] doubleData = (double[]) dataColors;
342 len = doubleData.length;
343 } else if (dataColors instanceof int[]) {
344 int[] intData = (int[]) dataColors;
345 len = intData.length;
346 } else {
347 throw new IllegalArgumentException(
348 "dataColors must be a double[] or int[]");
349 }
350
351 if ((this.colors == null) || (this.colors.length != len)) {
352 //we do a coloring here... note that this is a re-class and re-color each time
353 //also, do we need to do the numeric type discovery thing twice???
354 this.colors = this.findColoringByClass(dataColors);
355 }
356
357 for (int i = 0; i < this.pixelColors.length; i++) {
358 int rgb = this.colors[i].getRGB();
359 this.pixelColorsOriginal[i] = rgb;
360 this.pixelColors[i] = rgb;
361 }
362
363 this.colorCurrSelection();
364 this.colorCurrIndication();
365 }
366
367 private Color[] findColoringByClass(Object dataColors) {
368 //we need to get our data in numeric form.
369 double[] doubleData = null;
370
371 if (dataColors instanceof double[]) {
372 doubleData = (double[]) dataColors;
373 } else if (dataColors instanceof int[]) {
374 int[] intData = (int[]) dataColors;
375 doubleData = new double[intData.length];
376
377 for (int i = 0; i < intData.length; i++) {
378 doubleData[i] = intData[i];
379 } //next i
380 } else {
381 throw new IllegalArgumentException(
382 "obj passed in must be a double[] or int[]");
383 }
384
385 Color[] returnColors = this.colorClasser.symbolize(doubleData);
386
387 return returnColors;
388 }
389
390 //start shape handling
391 public void makeGeographicShapes(Shape[] originalShapes) {
392 if ((this.data == null) || (this.getWidth() < 1) ||
393 (originalShapes == null)) {
394 return;
395 }
396
397 int numShapes = originalShapes.length;
398
399 if (numShapes > 100) {
400 return;
401 }
402
403 if ((this.drawingShapes == null) ||
404 (this.drawingShapes.length != numShapes)) {
405 this.drawingShapes = new Shape[numShapes];
406 }
407
408 //xxx
409 //first we figure out how big each shape is
410 int width = this.getWidth();
411 int height = this.getHeight();
412 int heightIndex = this.pixelIndex.length; //nRows
413 int widthIndex = this.pixelIndex[0].length; //nColumns
414 float perCellWidth = (float) width / (float) widthIndex;
415 float perCellHeight = (float) height / (float) heightIndex;
416
417 AffineTransform xForm = null;
418
419 for (int i = 0; i < this.pixelIndex.length; i++) { //row
420
421 for (int j = 0; j < pixelIndex[0].length; j++) { //column
422
423 //step 1: find the index from the order array
424 int buffIndex = pixelIndex[i][j];
425
426 //if it is not outside the space fill viz
427 if (buffIndex != Integer.MIN_VALUE) {
428 //get that original shape
429 int arrayIndex = (int) Math.round(
430 pixelOrder[buffIndex][SpaceFillCanvas.COLUMN_ORIGINAL_ORDER]);
431 Shape geogShape = originalShapes[arrayIndex];
432 Rectangle2D source = geogShape.getBounds2D();
433 Rectangle2D target = new Rectangle2D.Double(perCellWidth * j,
434 perCellHeight * i,
435 perCellWidth,
436 perCellHeight);
437 AffineTransformModifier xMod = new AffineTransformModifier();
438 xForm = AffineTransformModifier.makeGeogAffineTransform(source,
439 target, true,
440 true);
441 this.drawingShapes[arrayIndex] = xForm.createTransformedShape(
442 geogShape);
443 } //end if
444 } // next column
445 } // next row
446
447 return;
448 }
449
450 //end shape handling
451 //start mouse event handling
452
453 /***
454 * Draws a bounding box for selection.
455 * @param e
456 */
457 public void mouseDragged(MouseEvent e) {
458 e.consume();
459 mouseX2 = e.getX();
460 mouseY2 = e.getY();
461 repaint();
462 }
463
464 /***
465 * Activates a tool tip.
466 * @param e
467 */
468 public void mouseMoved(MouseEvent e) {
469 //Tool tip, why not?
470 //this is indication as well...
471 if (data != null) {
472 Point2D.Double mouseLocation = new Point2D.Double();
473 mouseLocation.setLocation(e.getX(), e.getY());
474
475 try {
476 xform.inverseTransform(mouseLocation, mouseLocation);
477 } catch (Exception ex) {
478 ex.printStackTrace();
479 }
480
481 int x = (int) mouseLocation.getX();
482 int y = (int) mouseLocation.getY();
483 this.makeToolTip(x, y);
484
485 int currObs = this.findArrayIndexAt(x, y);
486
487 if (currObs != indication) {
488 int oldInd = this.indication;
489 indication = currObs;
490 this.makeToolTip(indication);
491
492
493 //System.out.println("indication = " + indication);
494 this.colorNewIndication(oldInd);
495 this.colorPixels();
496 fireIndicationChanged(indication);
497 }
498 }
499 }
500
501 /***
502 * Inits selection bounding box.
503 * @param e
504 */
505 public void mousePressed(MouseEvent e) {
506 e.consume();
507 mouseX1 = e.getX();
508 mouseY1 = e.getY();
509 mouseX2 = e.getX();
510 mouseY2 = e.getY();
511 }
512
513 /***
514 * Makes selection.
515 * @param e
516 */
517 public void mouseReleased(MouseEvent e) {
518 if (data != null) {
519 mouseX2 = e.getX();
520 mouseY2 = e.getY();
521 e.consume();
522
523 Point2D.Double selectionStart = new Point2D.Double();
524 Point2D.Double selectionEnd = new Point2D.Double();
525
526 selectionStart.setLocation(mouseX1, mouseY1);
527 selectionEnd.setLocation(mouseX2, mouseY2);
528
529 try {
530 xform.inverseTransform(selectionStart, selectionStart);
531 xform.inverseTransform(selectionEnd, selectionEnd);
532 } catch (Exception ex) {
533 ex.printStackTrace();
534 }
535
536 int x1;
537 int x2;
538 int y1;
539 int y2;
540 x1 = (int) selectionStart.getX();
541 x2 = 1 + (int) selectionEnd.getX();
542 y1 = (int) selectionStart.getY();
543 y2 = 1 + (int) selectionEnd.getY();
544
545 if (e.isShiftDown()) {
546 this.makeSelectionShift(x1, x2, y1, y2);
547 } else {
548 this.makeSelection(x1, x2, y1, y2);
549 }
550
551 mouseX1 = -2;
552 repaint();
553 } //if not null
554 }
555
556 /***
557 * makes crosshair cursor
558 * @param e
559 */
560 public void mouseEntered(MouseEvent e) {
561 this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
562 }
563
564 /***
565 * resets cursor
566 * @param e
567 */
568 public void mouseExited(MouseEvent e) {
569 if (data == null){
570 return;
571 }
572 //ok, let's clobber the indiction
573 this.indication = Integer.MIN_VALUE;
574 this.findPixelColors(data[currColorColumn]);
575 this.colorPixels();
576
577 for (int i = 0; i < pixelColors.length; i++) {
578 this.pixelColors[i] = this.pixelColorsOriginal[i];
579 }
580 this.fireIndicationChanged(-1);
581 }
582
583 /***
584 * noop
585 * @param e
586 */
587 public void mouseClicked(MouseEvent e) {
588 if (e.getClickCount() > 1) { // This is a double-click or triple...
589
590 //if (dataIndices[0] != dataIndices[1]) { //why this??? I guess we don't want to pop up one from the
591 //diagonal if we are a scatterplot
592 SpaceFill detailSpaceFill = new SpaceFill();
593 detailSpaceFill.setData(this.data);
594
595
596 //detailSpaceFill.setBivarColorClasser(this.bivarColorClasser);
597 detailSpaceFill.setSelectedObservationsInt(this.selectedObservations);
598 detailSpaceFill.setCurrColorColumn(this.currColorColumn);
599 detailSpaceFill.setCurrOrderColumn(this.currOrderColumn);
600
601 //(dataObject,
602 // dataIndices, true, background);
603 JFrame dummyFrame = new JFrame();
604 JDialog detailSpaceFillFrame = new JDialog(dummyFrame,
605 "Detail Space Filling Visualization",
606 true);
607 detailSpaceFillFrame.setLocation(300, 300);
608 detailSpaceFillFrame.setSize(300, 300);
609 detailSpaceFillFrame.getContentPane().setLayout(new BorderLayout());
610 detailSpaceFillFrame.getContentPane()
611 .add(detailSpaceFill, BorderLayout.CENTER);
612 detailSpaceFill.addActionListener(new ActionListener() {
613 /***
614 * put your documentation comment here
615 * @param e
616 */
617 public void actionPerformed(ActionEvent e) {
618 //System.out.println("something came from detailed one.");
619 SpaceFill detailSpaceFill = (SpaceFill) e.getSource();
620 String command = e.getActionCommand();
621
622 if (command.compareTo(SpaceFillCanvas.COMMAND_SELECTION) == 0) {
623 Vector selRecords = detailSpaceFill.getSelectedObservations();
624
625
626 // Don't recall the map which generated the original event
627 SpaceFillCanvas.this.setSelectedObservations(selRecords);
628 SpaceFillCanvas.this.fireActionPerformed(
629 SpaceFillCanvas.COMMAND_SELECTION);
630
631 //repaint();
632 } else if (command.compareTo(
633 SpaceFillCanvas.COMMAND_COLOR_CLASSFICIATION) == 0) {
634 SpaceFillCanvas.this.setBivarColorClasser(
635 detailSpaceFill.getBivarColorClasser(), false);
636 SpaceFillCanvas.this.fireActionPerformed(
637 SpaceFillCanvas.COMMAND_COLOR_CLASSFICIATION);
638 } else {
639 System.err.println("Unknown command! = " + command);
640 }
641 }
642 }); //end action performed
643 detailSpaceFillFrame.show();
644
645 //}//end dataIndeces
646 } //end if doubleclick
647 }
648
649 private int findArrayIndexAt(int x, int y) {
650 int arrayIndex = Integer.MIN_VALUE;
651
652 if (x > this.pixelIndex[0].length) {
653 return arrayIndex;
654 }
655
656 if (y > this.pixelIndex.length) {
657 return arrayIndex;
658 }
659
660 if (x < 0) {
661 return arrayIndex;
662 }
663
664 if (y < 0) {
665 return arrayIndex;
666 }
667
668 //first we find which pixel is selected
669 //lets use the pixel index (he he)
670 int buffIndex = pixelIndex[y][x];
671
672 //if it is outside the space fill viz (can't make it a rectangle...)
673 if (buffIndex != Integer.MIN_VALUE) {
674 //find out what element is the 'buffIndex'th one when sorted
675 arrayIndex = (int) Math.round(
676 pixelOrder[buffIndex][SpaceFillCanvas.COLUMN_ORIGINAL_ORDER]);
677 }
678
679 return arrayIndex;
680 }
681
682 private void makeToolTip(int arrayIndex) {
683 if (arrayIndex != Integer.MIN_VALUE) {
684 //setting multi-line tool tip
685 //b.setToolTipText("<html>ToolTip : 1st Line<br>2nd Line<br> 3rd Line </html>");
686 String colorVal = this.findValueOf(this.data[this.currColorColumn],
687 arrayIndex);
688 String orderVal = this.findValueOf(this.data[this.currOrderColumn],
689 arrayIndex);
690 String s = "<html> ";
691
692 if (this.observationNames != null) {
693 s = s + "Name = " + observationNames[arrayIndex] + "<br>";
694 }
695
696 s = s + variableNames[currColorColumn - 1] + " = " + colorVal + "<br>" +
697 variableNames[currOrderColumn - 1] + " = " + orderVal + "</html>";
698
699 this.setToolTipText(s);
700 } //if
701 }
702
703 private void makeToolTip(int x, int y) {
704 if (x > this.pixelIndex[0].length) {
705 return;
706 }
707
708 if (y > this.pixelIndex.length) {
709 return;
710 }
711
712 if (x < 0) {
713 return;
714 }
715
716 if (y < 0) {
717 return;
718 }
719
720 int arrayIndex = this.findArrayIndexAt(x, y);
721 this.makeToolTip(arrayIndex);
722 }
723
724 private void makeSelection(int x1, int x2, int y1, int y2) {
725 if (x1 > this.pixelIndex[0].length) {
726 x1 = pixelIndex[0].length;
727 }
728
729 if (x2 > this.pixelIndex[0].length) {
730 x2 = pixelIndex[0].length;
731 }
732
733 if (y1 > this.pixelIndex.length) {
734 y1 = pixelIndex.length;
735 }
736
737 if (y2 > this.pixelIndex.length) {
738 y2 = pixelIndex.length;
739 }
740
741 if (x1 < 0) {
742 x1 = 0;
743 }
744
745 if (x2 < 0) {
746 x2 = 0;
747 }
748
749 if (y1 < 0) {
750 y1 = 0;
751 }
752
753 if (y2 < 0) {
754 y2 = 0;
755 }
756
757 //X1 needs to be less than X2, same with Y1 and y2
758 int tempx = 0;
759 int tempy = 0;
760
761 if (x1 > x2) {
762 tempx = x1;
763 x1 = x2;
764 x2 = tempx;
765 }
766
767 if (y1 > y2) {
768 tempy = y1;
769 y1 = y2;
770 y2 = tempy;
771 }
772
773 //first we assemble a list of what tuples have been selected.
774 //lets use the pixel index (he he)
775 Vector selObs = new Vector();
776
777 for (int i = y1; i < y2; i++) { //row
778
779 for (int j = x1; j < x2; j++) { //column
780
781 int buffIndex = pixelIndex[i][j];
782
783 //if it is outside the space fill viz (can't make it a rectangle...)
784 if (buffIndex != Integer.MIN_VALUE) {
785 //find out what element is the 'buffIndex'th one when sorted
786 int arrayIndex = (int) Math.round(
787 pixelOrder[buffIndex][SpaceFillCanvas.COLUMN_ORIGINAL_ORDER]);
788 selObs.add(new Integer(arrayIndex));
789 } //if
790 } //j
791 } //i
792
793 int counter = 0;
794 int[] newSel = new int[selObs.size()];
795
796 for (Enumeration e = selObs.elements(); e.hasMoreElements();) {
797 Integer I = (Integer) e.nextElement();
798 int i = I.intValue();
799 newSel[counter] = i;
800
801
802 //this.selectedObservationsOld[counter] = i;
803 counter++;
804 }
805
806 this.setSelectedObservationsInt(newSel);
807 fireActionPerformed(COMMAND_SELECTION);
808 } //method
809
810 private void makeSelectionShift(int x1, int x2, int y1, int y2) {
811 }
812
813 //end mouse event handling
814 //start component event handling
815 //note: this class only listens to itself
816 public void componentHidden(ComponentEvent e) {
817 }
818
819 public void componentMoved(ComponentEvent e) {
820 }
821
822 public void componentResized(ComponentEvent e) {
823 if (this.useDrawingShapes) {
824 this.makeGeographicShapes(this.originalSpatialData);
825 }
826
827 remakeDrawingBuff();
828 }
829
830 public void componentShown(ComponentEvent e) {
831 //System.out.println("componentShown event from "
832 // + e.getComponent().getClass().getName());
833 }
834
835 //end component handling
836 //start coordinated events handling
837 public void selectionChanged(SelectionEvent e) {
838 int[] sel = e.getSelection();
839 this.setSelectedObservationsInt(sel);
840 }
841
842 public void remakeDrawingBuff() {
843 int width = this.getWidth();
844 int height = this.getHeight();
845
846 //this.drawingBuff = new Image(width,height,BufferedImage.TYPE_INT_ARGB);
847 if ((width > 0) && (height > 0)) {
848 drawingBuff = this.createImage(width, height);
849 this.paintBuffer();
850 }
851 }
852
853 //end component event handling
854
855 public void setBackground(Color c){
856 super.setBackground(c);
857 this.colorOutOfFocus = c;
858 if (this.dataSet != null){
859 this.colorPixels();
860 this.repaint();
861 }
862 }
863 //start accessors
864 public void setBivarColorClasser(BivariateColorSymbolClassification bivarColorClasser, boolean reverseColor) {
865 //System.out.println("got a color classer");
866
867 ColorSymbolizer symbolizer = bivarColorClasser.getYColorSymbolizer();
868 ColorSymbolClassificationSimple colorClasser = new ColorSymbolClassificationSimple();
869 colorClasser.setClasser(bivarColorClasser.getClasserY());
870 colorClasser.setColorer(bivarColorClasser.getYColorSymbolizer());
871 this.setColorSymbolizer(colorClasser);
872
873 //this.colorClasser = bivarColorClasser.getYColorSymbolizer();
874 }
875
876 public BivariateColorSymbolClassification getBivarColorClasser() {
877 return null;
878 }
879
880 public void setColorSymbolizer(ColorSymbolClassification colorSymbolizer) {
881 this.colorClasser = colorSymbolizer;
882
883 if (currColorColumn >= 0) {
884 this.colors = this.findColoringByClass(data[currColorColumn]);
885 this.findPixelColors(data[currColorColumn]);
886 this.colorPixels();
887 }
888 }
889
890 //public ColorSymbolClassification getColorSymbolizer() {
891 // return this.bivarColorClasser;
892 //}
893 public void setData(Object[] dataIn) {
894 dataSet = new DataSetForApps();
895 dataSet.setDataObject(dataIn);
896 this.variableNames = dataSet.getAttributeNamesNumeric();
897 this.data = dataSet.getDataSetNumericAndSpatial();
898
899 if (dataSet.getNumberNumericAttributes() > 2) {
900 this.currOrderColumn = 1;
901 this.currColorColumn = 2;
902 }
903
904 this.observationNames = dataSet.getObservationNames();
905 this.findBuffFillOrder();
906 this.refreshMembers();
907 this.findPixelOrder(this.data, this.pixelOrder, this.currOrderColumn);
908
909 if (currColorColumn >= 0) {
910 this.findPixelColors(data[currColorColumn]);
911 }
912 this.conditioning = new int[dataSet.getNumObservations()];
913 this.colorPixels();
914 this.originalSpatialData = dataSet.getShapeData();
915
916 if (this.useDrawingShapes) {
917 this.makeGeographicShapes(this.originalSpatialData);
918 }
919 }
920
921 public Object[] getData() {
922 return this.data;
923 }
924
925 public void setPixelBuff(BufferedImage pixelBuff) {
926 this.pixelBuff = pixelBuff;
927 }
928
929 public BufferedImage getPixelBuff() {
930 return this.pixelBuff;
931 }
932
933 public void setCurrOrderColumn(int currOrderColumn) {
934 if ((data != null) && (currOrderColumn < data.length)) {
935 this.currOrderColumn = currOrderColumn;
936 this.findPixelOrder(this.data, this.pixelOrder, this.currOrderColumn);
937
938 if (this.useDrawingShapes) {
939 this.makeGeographicShapes(this.originalSpatialData);
940 }
941
942 this.colorPixels();
943 }
944 }
945
946 public int getCurrOrderColumn() {
947 return this.currOrderColumn;
948 }
949
950 public void setCurrColorColumn(int currColorColumn) {
951 if ((data != null) && (currColorColumn < data.length)) {
952 this.currColorColumn = currColorColumn;
953 this.colors = this.findColoringByClass(data[currColorColumn]);
954 this.findPixelColors(data[currColorColumn]);
955 this.colorPixels();
956 }
957 }
958
959 public int getCurrColorColumn() {
960 return this.currColorColumn;
961 }
962
963 public void setColorSelection(Color colorSelection) {
964 this.colorSelection = colorSelection;
965 }
966
967 public Color getColorSelection() {
968 return this.colorSelection;
969 }
970
971 public boolean getSelOriginalColorMode() {
972 return selOriginalColorMode;
973 }
974
975 public void setSelOriginalColorMode(boolean selOriginalColorMode) {
976 this.selOriginalColorMode = selOriginalColorMode;
977 }
978
979 public void setColorIndication(Color colorIndication) {
980 this.colorIndication = colorIndication;
981 }
982
983 public Color getColorIndication() {
984 return this.colorIndication;
985 }
986
987 public void setIndication(int indication) {
988
989 if (this.indication != indication) {
990 int oldInd = this.indication;
991 this.indication = indication;
992 //this.makeToolTip(indication);
993
994
995 //System.out.println("indication = " + indication);
996 this.colorNewIndication(oldInd);
997 this.colorPixels();
998
999 }
1000
1001
1002 }
1003
1004 public int getIndication() {
1005 return this.indication;
1006 }
1007
1008 public void setColorNull(Color colorNull) {
1009 this.colorNull = colorNull;
1010 this.findPixelColors(data[currColorColumn]);
1011 this.colorPixels();
1012 }
1013
1014 public Color getColorNull() {
1015 return this.colorNull;
1016 }
1017
1018 public void setColorOutOfFocus(Color colorOutOfFocus) {
1019 this.colorOutOfFocus = colorOutOfFocus;
1020 this.findPixelColors(data[currColorColumn]);
1021 this.colorPixels();
1022 }
1023
1024 public Color getColorOutOfFocus() {
1025 return this.colorOutOfFocus;
1026 }
1027
1028 public void setColorNotInStudyArea(Color colorNotInStudyArea) {
1029 this.colorNotInStudyArea = colorNotInStudyArea;
1030 this.findPixelColors(data[currColorColumn]);
1031 this.colorPixels();
1032 }
1033
1034 public Color getColorNotInStudyArea() {
1035 return this.colorNotInStudyArea;
1036 }
1037
1038 public void setVariableNames(String[] variableNames) {
1039 this.variableNames = variableNames;
1040 }
1041
1042 public String[] getVariableNames() {
1043 return this.variableNames;
1044 }
1045
1046 public void setConditionArray (int[] conditionArray){
1047 if (this.dataSet == null){
1048 return;
1049 }
1050 if (conditionArray.length != this.dataSet.getNumObservations()){
1051 throw new IllegalArgumentException("passed incompatible length conditioning array");
1052 }
1053 this.conditioning = conditionArray;
1054
1055
1056 this.colorPixels();
1057 }
1058
1059 public void setSelectedObservations(Vector selectedObservations) {
1060 int counter = 0;
1061 this.selectedObservations = new int[selectedObservations.size()];
1062
1063 for (Enumeration e = selectedObservations.elements(); e.hasMoreElements();) {
1064 Integer I = (Integer) e.nextElement();
1065 int i = I.intValue();
1066 this.selectedObservations[counter] = i;
1067 counter++;
1068 }
1069
1070 this.setSelectedObservationsInt(this.selectedObservations);
1071 }
1072
1073 public void setSelections(int[] selections) {
1074 Vector v = new Vector();
1075
1076 for (int i = 0; i < selections.length; i++) {
1077 if (selections[i] == 1) {
1078 v.add(new Integer(i));
1079 }
1080 }
1081
1082 this.selectedObservations = new int[v.size()];
1083
1084 int i = 0;
1085
1086 for (Enumeration e = v.elements(); e.hasMoreElements();) {
1087 Integer bigIint = (Integer) e.nextElement();
1088 this.selectedObservations[i] = bigIint.intValue();
1089 i++;
1090 }
1091
1092 this.setSelectedObservationsInt(this.selectedObservations);
1093 }
1094
1095 public int[] getSelections() {
1096 int[] selections = new int[this.dataSet.getNumObservations()];
1097
1098 for (int i = 0; i < this.selectedObservations.length; i++) {
1099 selections[this.selectedObservations[i]] = 1;
1100 }
1101
1102 return selections;
1103 }
1104
1105 public Vector getSelectedObservations() {
1106 Vector v = new Vector();
1107
1108 for (int i = 0; i < this.selectedObservations.length; i++) {
1109 Integer anInt = new Integer(this.selectedObservations[i]);
1110 v.add(anInt);
1111 }
1112
1113 return v;
1114 }
1115
1116 public void setSelectedObservationsInt(int[] selectedObservations) {
1117 //copy selected obs
1118 this.selectedObservationsOld = new int[this.selectedObservations.length];
1119
1120 for (int i = 0; i < this.selectedObservations.length; i++) {
1121 this.selectedObservationsOld[i] = this.selectedObservations[i];
1122 }
1123
1124 this.selectedObservations = selectedObservations;
1125 this.colorNewSelection(this.selectedObservationsOld); //this also colors
1126
1127
1128 //current selection
1129 this.findPixelColors(data[currColorColumn]);
1130 this.colorPixels();
1131 this.repaint();
1132 }
1133
1134 public int[] getSelectedObservationsInt() {
1135 return this.selectedObservations;
1136 }
1137
1138 public void setFillOrder(int fillOrder) {
1139 if (this.fillOrder != fillOrder) {
1140 if ((fillOrder > FillOrder.FILL_ORDER_MAX) || (fillOrder < 0)) {
1141 throw new IllegalArgumentException(
1142 "Fill order outside legal range defined in FillOrder");
1143 } else {
1144 this.fillOrder = fillOrder;
1145 this.findBuffFillOrder();
1146 this.colorPixels();
1147 }
1148 } //
1149 } //end method
1150
1151 public int getFillOrder() {
1152 return this.fillOrder;
1153 }
1154
1155 public void setColors(Color[] colors) {
1156 this.colors = colors;
1157
1158 if (data != null) {
1159 this.findPixelColors(data[currColorColumn]);
1160 this.colorPixels();
1161 }
1162 }
1163
1164 public Color[] getColors() {
1165 return this.colors;
1166 }
1167
1168 public void setObservationNames(String[] observationNames) {
1169 this.observationNames = observationNames;
1170 }
1171
1172 public String[] getObservationNames() {
1173 return this.observationNames;
1174 }
1175
1176 public void setUseDrawingShapes(boolean useDrawingShapes) {
1177 this.useDrawingShapes = useDrawingShapes;
1178
1179 if (this.useDrawingShapes) {
1180 this.makeGeographicShapes(this.originalSpatialData);
1181 } else {
1182 this.drawingShapes = null;
1183 }
1184
1185 this.remakeDrawingBuff();
1186 }
1187
1188 public boolean getUseDrawingShapes() {
1189 return this.useDrawingShapes;
1190 }
1191
1192 //end accessors
1193
1194 /***
1195 * This method reconstructs the contents of the drawingBuff.
1196 * @param g
1197 */
1198 public void paintBuffer() {
1199 if ((this.getWidth() <= 0) || (this.getHeight() <= 0)) {
1200 return;
1201 }
1202
1203 if (drawingBuff == null) {
1204 this.remakeDrawingBuff();
1205 }
1206
1207 Graphics g = this.drawingBuff.getGraphics();
1208 this.makeXform();
1209
1210 boolean transformChanged = false;
1211 Graphics2D g2 = (Graphics2D) g;
1212
1213
1214 //draw image
1215 g2.drawImage(pixelBuff, xform, this);
1216
1217 if ((this.drawingShapes != null) && this.useDrawingShapes) {
1218 g2.setColor(Color.cyan);
1219
1220 BasicStroke outline = new BasicStroke(2.0f);
1221 g2.setStroke(outline);
1222
1223 for (int i = 0; i < this.drawingShapes.length; i++) {
1224 if (drawingShapes[i] != null) {
1225 g2.draw(this.drawingShapes[i]);
1226 } //end if null
1227 } // next i
1228 } // end if
1229
1230
1231 //draw shapes
1232 //xxx
1233 repaint();
1234 }
1235
1236 /***
1237 * This method only paints the current contents of the drawingBuff.
1238 * @param g
1239 */
1240 public void paintComponent(Graphics g) {
1241 if ((this.getWidth() <= 0) || (this.getHeight() <= 0)) {
1242 return;
1243 }
1244
1245 if (drawingBuff == null) {
1246 this.remakeDrawingBuff();
1247 }
1248
1249 g.drawImage(this.drawingBuff, 0, 0, this);
1250
1251 Graphics2D g2 = (Graphics2D) g;
1252 Stroke currStroke = g2.getStroke();
1253 Color currColor = g2.getColor();
1254
1255 //draw selection box
1256 if (mouseX1 > -1) {
1257 Stroke tempStroke = g2.getStroke();
1258 float[] dash = new float[3];
1259 dash[0] = (float) 5.0;
1260 dash[1] = (float) 7.0;
1261 dash[2] = (float) 5.0;
1262
1263 BasicStroke dashStroke = new BasicStroke((float) 2.0,
1264 BasicStroke.CAP_SQUARE,
1265 BasicStroke.JOIN_MITER,
1266 (float) 10.0, dash, 0);
1267 g2.setStroke(dashStroke);
1268 g2.setPaintMode();
1269 g2.setColor(Color.black);
1270 g2.setXORMode(Color.white);
1271
1272 //let's take drawing the selection rectangle by cases
1273 //not elegant, but the alternative is introducing more class variables
1274 int selectX = 0;
1275 int selectY = 0;
1276 int selectWidth = 0;
1277 int selectHeight = 0;
1278
1279 if ((mouseX1 <= mouseX2) && (mouseY1 <= mouseY2)) {
1280 selectX = mouseX1;
1281 selectY = mouseY1;
1282 selectWidth = mouseX2 - mouseX1;
1283 selectHeight = mouseY2 - mouseY1;
1284 }
1285
1286 if ((mouseX2 < mouseX1) && (mouseY1 <= mouseY2)) {
1287 selectX = mouseX2;
1288 selectY = mouseY1;
1289 selectWidth = mouseX1 - mouseX2;
1290 selectHeight = mouseY2 - mouseY1;
1291 }
1292
1293 if ((mouseX1 <= mouseX2) && (mouseY2 < mouseY1)) {
1294 selectX = mouseX1;
1295 selectY = mouseY2;
1296 selectWidth = mouseX2 - mouseX1;
1297 selectHeight = mouseY1 - mouseY2;
1298 }
1299
1300 if ((mouseX2 < mouseX1) && (mouseY2 < mouseY1)) {
1301 selectX = mouseX2;
1302 selectY = mouseY2;
1303 selectWidth = mouseX1 - mouseX2;
1304 selectHeight = mouseY1 - mouseY2;
1305 }
1306
1307 g2.drawRect(selectX, selectY, selectWidth, selectHeight);
1308 } //end if mouse
1309 g2.setStroke(currStroke);
1310 g2.setColor(currColor);
1311 g2.setPaintMode();
1312 }
1313
1314 /***
1315 * adds an ActionListener to the component
1316 */
1317 public void addActionListener(ActionListener l) {
1318 listenerList.add(ActionListener.class, l);
1319 }
1320
1321 /***
1322 * removes an ActionListener from the component
1323 */
1324 public void removeActionListener(ActionListener l) {
1325 listenerList.remove(ActionListener.class, l);
1326 }
1327
1328 /***
1329 * Notify all listeners that have registered interest for
1330 * notification on this event type. The event instance
1331 * is lazily created using the parameters passed into
1332 * the fire method.
1333 * @see EventListenerList
1334 */
1335 public void fireActionPerformed(String command) {
1336 // Guaranteed to return a non-null array
1337 Object[] listeners = listenerList.getListenerList();
1338 ActionEvent e = null;
1339
1340 // Process the listeners last to first, notifying
1341 // those that are interested in this event
1342 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1343 if (listeners[i] == ActionListener.class) {
1344 // Lazily create the event:
1345 if (e == null) {
1346 e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command);
1347 }
1348
1349 ((ActionListener) listeners[i + 1]).actionPerformed(e);
1350 }
1351 }
1352 }
1353
1354 /***
1355 * adds an IndicationListener to the component
1356 */
1357 public void addIndicationListener(IndicationListener l) {
1358 listenerList.add(IndicationListener.class, l);
1359 }
1360
1361 /***
1362 * removes an IndicationListener from the component
1363 */
1364 public void removeIndicationListener(IndicationListener l) {
1365 listenerList.remove(IndicationListener.class, l);
1366 }
1367
1368 /***
1369 * Notify all listeners that have registered interest for
1370 * notification on this event type. The event instance
1371 * is lazily created using the parameters passed into
1372 * the fire method.
1373 * @see EventListenerList
1374 */
1375 public void fireIndicationChanged(int indication) {
1376 // Guaranteed to return a non-null array
1377 Object[] listeners = listenerList.getListenerList();
1378 IndicationEvent e = null;
1379
1380 // Process the listeners last to first, notifying
1381 // those that are interested in this event
1382 for (int i = listeners.length - 2; i >= 0; i -= 2) {
1383 if (listeners[i] == IndicationListener.class) {
1384 // Lazily create the event:
1385 if (e == null) {
1386 e = new IndicationEvent(this, indication);
1387 }
1388
1389 ((IndicationListener) listeners[i + 1]).indicationChanged(e);
1390 }
1391 }
1392 }
1393 }
This page was automatically generated by Maven