View Javadoc
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