001 package ui.recognizer; 002 003 import javax.swing.*; 004 import java.awt.*; 005 import java.awt.event.*; 006 import java.awt.geom.*; 007 import java.awt.image.*; 008 import java.net.*; 009 import java.io.*; 010 import java.text.*; 011 import java.util.*; 012 import java.util.Collection.*; 013 014 import java.awt.dnd.*; 015 import java.awt.datatransfer.*; 016 017 public class PlotRecognizer extends JFrame implements ItemListener, ActionListener, DropTargetListener { 018 019 public static final String FILE = "File"; 020 public static final String FILE_LOAD = "Load Image"; 021 public static final String FILE_SAVE = "Save Data"; // disabled until data available 022 public static final String FILE_QUIT = "Quit"; 023 JMenuItem saveMenuItem; // disabled until data available 024 025 JMenu editMenu; // disabled until image is loaded 026 public static final String EDIT = "Edit"; 027 public static final String EDIT_CLEAN = "Remove blemishes"; 028 public static final String EDIT_REMOVE_GRID= "Remove grid"; 029 public static final String EDIT_CALIBRATE = "Calibrate axes"; 030 public static final String EDIT_WINDOW = "Restrict data to window"; 031 public static final String EDIT_RECOGNIZE = "Recognize plot"; 032 033 JMenu viewMenu; // disabled until image is loaded 034 public static final String VIEW = "View"; 035 public static final String VIEW_ZOOM_IN = "Zoom out"; 036 public static final String VIEW_ZOOM_OUT = "Zoom in"; 037 public static final String VIEW_ZOOM_NORMAL= "Zoom normal"; 038 039 JMenu dataMenu; // disabled until data available 040 public static final String DATA = "Data"; 041 public static final String DATA_MODIFY = "View or modify data"; 042 public static final String DATA_SMOOTH = "Smooth data"; 043 public static final String DATA_FLATEN = "Flaten data"; 044 public static final String DATA_OVERLAY = "Show overlay"; 045 046 public static int WIDTH = 1024; 047 public static int HEIGHT = 768; 048 049 JFileChooser loadFileChooser = new PlotFileChooser("Load a GIF or PNG plot image to be recognized", 050 "Image Files", new String[] {"gif", "png"}); 051 JFileChooser saveFileChooser = new PlotFileChooser("Save recognized plot data as x, y file", 052 "Data Files", new String[] {"txt", "dat"}); 053 054 // fields which determine the state of the plot processor 055 056 DataCoordinate[] data; 057 ImageCoordinate[] imagePoints; 058 ImageIcon imageIcon = null; 059 060 //Rectangle plotBorder = null; // the image coordinates of the plot border 061 Calibration calibration; 062 063 public static String DATA_OUTPUT_FORMAT_TEXT = "text"; 064 public static String DATA_OUTPUT_FORMAT_XML = "xml"; 065 public static String DATA_OUTPUT_FORMAT_FITS = "fits"; 066 067 private String dataOutputFormat = DATA_OUTPUT_FORMAT_TEXT; 068 private String xTextOutputFormat = "0.00"; 069 private String yTextOutputFormat = "0.0000"; 070 071 private int blackThreshold = 128; 072 073 // the data ranges (will be different for most plots) 074 private double xlow = 0.0d; 075 private double xhigh = 1.0d; 076 private double ylow = 0.0d; 077 private double yhigh = 1.0d; 078 079 private int samples = 0; 080 private String dataFileType = ".dat"; 081 private String dataFileName; 082 private String imageFileName; 083 private boolean imageLoaded = false; 084 private boolean dataAvailable = false; 085 private boolean overlay = true; 086 private boolean axesCalibrated = false; 087 088 JScrollPane scrollPane = new JScrollPane(new JLabel("Load Image")); 089 090 public PlotRecognizer(String aTitle) { 091 super(aTitle); 092 } 093 094 public void init() { 095 JMenuBar menuBar = createMenu(); 096 setJMenuBar(menuBar); 097 scrollPane.setPreferredSize(new Dimension(400, 100)); 098 getContentPane().add(scrollPane); 099 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 100 101 // TODO: create a mousemotion listener and show coordinates in status bar or title bar ... 102 setSize(new Dimension(WIDTH, HEIGHT)); 103 setDropTarget(new DropTarget(this, this)); // set this JFrame as a drag and drop drop target 104 pack(); 105 setVisible(true); 106 } 107 108 public JMenuBar createMenu() { 109 //Create the menu bar. 110 JMenuBar menuBar = new JMenuBar(); 111 112 JMenu fileMenu = new JMenu(FILE); 113 //fileMenu.setMnemonic('f'); 114 fileMenu.getAccessibleContext().setAccessibleDescription("The File menu"); 115 fileMenu.add(createSimpleMenuItem(FILE, FILE_LOAD, "Load an image containing a plot")); 116 saveMenuItem = createSimpleMenuItem(FILE, FILE_SAVE, "Save the recognized plot data"); 117 saveMenuItem.setEnabled(isDataAvailable()); 118 fileMenu.add(saveMenuItem); 119 fileMenu.add(createSimpleMenuItem(FILE, FILE_QUIT, "Quit the application without saving data")); 120 menuBar.add(fileMenu); 121 122 editMenu = new JMenu(EDIT); 123 editMenu.getAccessibleContext().setAccessibleDescription("The Edit menu"); 124 editMenu.add(createSimpleMenuItem(EDIT, EDIT_CLEAN, "Remove blemishes such as isolated pixels and dust shadows")); 125 editMenu.add(createSimpleMenuItem(EDIT, EDIT_REMOVE_GRID, "Remove grids")); 126 editMenu.add(createSimpleMenuItem(EDIT, EDIT_CALIBRATE, "Remove blemishes such as isolated pixels and dust shadows")); 127 editMenu.add(createSimpleMenuItem(EDIT, EDIT_WINDOW, "Restrict the data to a window")); 128 editMenu.add(createSimpleMenuItem(EDIT, EDIT_RECOGNIZE, "Recognize the plot and produce plot data")); 129 editMenu.setEnabled(isImageLoaded()); 130 menuBar.add(editMenu); 131 132 viewMenu = new JMenu(VIEW); 133 viewMenu.getAccessibleContext().setAccessibleDescription("The View menu"); 134 viewMenu.add(createSimpleMenuItem(VIEW, VIEW_ZOOM_IN, "Zoom in image")); 135 viewMenu.add(createSimpleMenuItem(VIEW, VIEW_ZOOM_OUT, "Zoom out image")); 136 viewMenu.add(createSimpleMenuItem(VIEW, VIEW_ZOOM_NORMAL, "Zoom normal")); 137 viewMenu.setEnabled(isImageLoaded()); 138 menuBar.add(viewMenu); 139 140 dataMenu = new JMenu(DATA); 141 dataMenu.getAccessibleContext().setAccessibleDescription("The Data menu"); 142 dataMenu.add(createSimpleMenuItem(DATA, DATA_MODIFY, "View and/or modify the data in a table")); 143 dataMenu.add(createSimpleMenuItem(DATA, DATA_SMOOTH, "Smooth the data to eliminate high frequencies")); 144 dataMenu.add(createSimpleMenuItem(DATA, DATA_FLATEN, "Flatent the data to eliminate low frequencies")); 145 dataMenu.add(createCheckBoxMenuItem(DATA_OVERLAY, DATA_OVERLAY, "Show overlay", isOverlay())); 146 dataMenu.setEnabled(isDataAvailable()); 147 menuBar.add(dataMenu); 148 149 return menuBar; 150 } 151 152 private JMenuItem createSimpleMenuItem(String aMenu, String aLabel, String anAccessibleDescription) { 153 JMenuItem simpleMenuItem = new JMenuItem(aLabel); 154 simpleMenuItem.getAccessibleContext().setAccessibleDescription(anAccessibleDescription); 155 simpleMenuItem.setName(aMenu); 156 simpleMenuItem.setActionCommand(aLabel); 157 simpleMenuItem.addActionListener(this); 158 return simpleMenuItem; 159 } 160 161 private JMenuItem createSimpleMenuItem(String aMenu, String aLabel, String anAccessibleDescription, int aShortcut) { 162 JMenuItem simpleMenuItem = createSimpleMenuItem(aMenu, aLabel, anAccessibleDescription); 163 simpleMenuItem.setAccelerator(KeyStroke.getKeyStroke(aShortcut, ActionEvent.CTRL_MASK)); 164 return simpleMenuItem; 165 } 166 167 private JMenuItem createCheckBoxMenuItem(String aMenu, String aLabel, String anAccessibleDescription, boolean aSelected) { 168 JCheckBoxMenuItem checkBoxMenuItem = new JCheckBoxMenuItem(aLabel); 169 checkBoxMenuItem.getAccessibleContext().setAccessibleDescription(anAccessibleDescription); 170 checkBoxMenuItem.setName(aMenu); 171 checkBoxMenuItem.setActionCommand(aLabel); 172 checkBoxMenuItem.setSelected(aSelected); // must be set before adding item listener 173 checkBoxMenuItem.addItemListener(this); 174 return checkBoxMenuItem; 175 } 176 177 // BUG: this never gets called, why ? 178 public void itemStateChanged(ItemEvent e) { 179 JMenuItem source = (JMenuItem) (e.getSource()); // this property is the action 'grouper' 180 String name = source.getName(); // this property is the specific selection 181 boolean repaint = false; 182 if (e.getStateChange() == ItemEvent.SELECTED) { 183 if (name.equals(DATA_OVERLAY)) { 184 setOverlay(true); 185 repaint = true; 186 } 187 } else if (e.getStateChange() == ItemEvent.DESELECTED) { 188 if (name.equals(DATA_OVERLAY)) { 189 setOverlay(false); 190 repaint = true; 191 } 192 } 193 if (repaint) reDraw(); 194 } 195 196 public void reDraw() { 197 // TODO: 198 }; 199 200 // implementation for ActionListener (menus and popup menus) 201 public void actionPerformed(ActionEvent e) { 202 JMenuItem source = (JMenuItem) (e.getSource()); 203 String name = source.getName(); 204 String action = source.getActionCommand(); 205 boolean repaint = false; 206 if (name.equals(FILE)) { 207 if (action.equals(FILE_LOAD)) { 208 loadImage(); 209 } else if (action.equals(FILE_SAVE)) { 210 saveData(); 211 } else if (action.equals(FILE_QUIT)) { 212 System.exit(0); 213 } 214 } else if (name.equals(EDIT)) { 215 if (action.equals(EDIT_CALIBRATE)) { 216 calibrate(); 217 } else if (action.equals(EDIT_RECOGNIZE)) { 218 recognize(); 219 } 220 } 221 // outline the graph frame (if no outline is specified pixel coordinates are used as a metric and bounds are edges of image) 222 // manual : click on at least three corners (parallelogram like-behavior) 223 // automatic (a statitical estimate is made of the location and orientation of the axis lines) 224 if (repaint) reDraw(); 225 } 226 227 public void loadImage() { 228 setDataAvailable(false); // new image must be recognized before data becomes available 229 if (loadFileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { // BUG: 'up' icon in file chooser is disabled 230 // if File is a directory then process all files in that directory 231 //UIUtilities.setWaitCursor(this, true); 232 loadFileChooser.getSelectedFile(); 233 loadImage(loadFileChooser.getSelectedFile()); 234 } 235 } 236 237 private XRule xRule; 238 private YRule yRule; 239 240 private JToggleButton isDataUnits; 241 242 public void loadImage(File aFile) { 243 setDataAvailable(false); 244 if (scrollPane == null) return; 245 try { 246 setImageFileName(aFile.getName()); 247 imageIcon = new ImageIcon(aFile.toURL()); 248 249 setUpScrollPane(imageIcon); 250 251 //Image image = Toolkit.getDefaultToolkit().getImage(getFileName()); 252 //Image img = UIUtilities.getImage(getFileName()); 253 254 setImageLoaded(true); 255 } catch(Exception ex) { 256 System.out.println("Could not open file : " + ex); 257 } 258 } 259 260 void setUpScrollPane(ImageIcon anImageIcon) { 261 262 // default calibration 263 Rectangle plotBorder = new Rectangle(0, 0, anImageIcon.getIconWidth(), anImageIcon.getIconHeight()); 264 //Rectangle ticZone = plotBorder; 265 calibration = new Calibration(plotBorder); 266 267 // create the rulers 268 xRule = new XRule(true, calibration, null); 269 xRule.setPreferredWidth(anImageIcon.getIconWidth()); 270 yRule = new YRule(true, calibration); 271 yRule.setPreferredHeight(anImageIcon.getIconHeight()); 272 273 // Create the corners 274 JPanel buttonCorner = new JPanel(); 275 isDataUnits = new JToggleButton("Data", true); 276 isDataUnits.setFont(new Font("SansSerif", Font.PLAIN, 11)); 277 isDataUnits.setMargin(new Insets(2,2,2,2)); 278 isDataUnits.addItemListener(new UnitsListener()); 279 buttonCorner.add(isDataUnits); //Use the default FlowLayout 280 281 // Create the main view 282 JLabel label = new JLabel(anImageIcon); 283 label.setVerticalAlignment(JLabel.TOP); 284 label.setHorizontalAlignment(JLabel.LEFT); 285 286 scrollPane.setViewportView(label); 287 scrollPane.setPreferredSize(new Dimension(300, 250)); 288 scrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black)); 289 scrollPane.setColumnHeaderView(xRule); 290 scrollPane.setRowHeaderView(yRule); 291 scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, buttonCorner); 292 scrollPane.setCorner(JScrollPane.LOWER_LEFT_CORNER, new Corner()); 293 scrollPane.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new Corner()); 294 } 295 296 class UnitsListener implements ItemListener { 297 public void itemStateChanged(ItemEvent e) { 298 if (e.getStateChange() == ItemEvent.SELECTED) { 299 // Turn it to metric. 300 yRule.setDataUnits(true); 301 xRule.setDataUnits(true); 302 } else { 303 // Turn it to inches. 304 yRule.setDataUnits(false); 305 xRule.setDataUnits(false); 306 } 307 //picture.setMaxUnitIncrement(yRule.getIncrement()); 308 } 309 } 310 311 /** Bring up a file requestor and save the current data into that file. 312 */ 313 public void saveData() { 314 // TODO: use the file name for the current image, strip its terminator and append .txt 315 // BUG: 'up' icon in file chooser is disabled 316 if (saveFileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) 317 saveData(saveFileChooser.getSelectedFile()); 318 } 319 320 /** Save the current data as file, the file will be saved in the current export format 321 * @param aFile a file in which to save the data 322 */ 323 public void saveData(File aFile) { 324 String format = getDataOutputFormat(); 325 DecimalFormat xFormatter = new DecimalFormat(getXTextOutputFormat()); 326 DecimalFormat yFormatter = new DecimalFormat(getYTextOutputFormat()); 327 //String output = xFormatter.format(value); 328 329 if (format != null && format.equals(DATA_OUTPUT_FORMAT_TEXT)) { 330 for (int i = 0; i < getSamples(); i++) { 331 DataCoordinate sample = data[i]; 332 System.out.println(xFormatter.format(sample.getX()) + " " + 333 yFormatter.format(sample.getY()) ); 334 } 335 } 336 } 337 338 /** Process a list of image files. The list could be a product of a 339 * drag and drop operation involving multiple files or it could be constructed from a special file 340 * containing a list of filenames. The calibration and recognition steps are performed automatically. 341 * The calibration must be the same for all plots, they must have the same x-range. 342 * @param aListOfFiles a collection of File objects to be processed. 343 */ 344 public void processFiles(java.util.List aListOfFiles) { 345 int files = aListOfFiles.size(); 346 ProgressMonitor progressMonitor = new ProgressMonitor(this, "Recognizing a list of images", "", 0, files); 347 progressMonitor.setMillisToDecideToPopup(500); 348 for(int i = 0; i < files; i++ ) { 349 File file = (File) aListOfFiles.get(i); 350 if (file.isFile()) { 351 System.out.println("Processing file : " + file.getAbsolutePath()); 352 loadImage(file); 353 recognize(); 354 //saveData(new File(file.getName() + ".dat")); 355 progressMonitor.setProgress(i); 356 progressMonitor.setNote("Plot : " + getImageFileName()); 357 } else if (file.isDirectory()){ 358 System.out.println("Processing directory : " + file.getAbsolutePath()); 359 //TODO: process all files in the dictory called 'file' 360 File[] fileList = file.listFiles(); 361 processFiles(Arrays.asList(fileList)); // recursive call 362 } 363 } 364 progressMonitor.close(); 365 } 366 367 /** Calibrate the image by asking for the user to click on the axes and to define a numerical value for the coordinates of those points. 368 */ 369 public void calibrate() { 370 // setSamples(imageIcon.getWidth()); 371 } 372 373 /** Recognize the image by iterating over the pixexl columns of the calibrated image window and by searching for 374 * the plot 'trace' or 'pen' which represents the function y=f(x). 375 */ 376 public void recognize() { 377 Image image = imageIcon.getImage(); 378 int width = image.getWidth(this); 379 int height = image.getHeight(this); 380 setSamples(width); 381 data = new DataCoordinate[getSamples()]; 382 imagePoints = new ImageCoordinate[getSamples()]; 383 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); // TYPE_INT_RGB 384 //bufferedImage = createImage(width, height); 385 Graphics2D g2 = bufferedImage.createGraphics(); 386 g2.drawImage(image, 0, 0, this); 387 388 WritableRaster raster = bufferedImage.getRaster(); 389 SampleModel sampleModel = raster.getSampleModel(); 390 DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); 391 byte[] byteData = dataBuffer.getData(); 392 393 394 int edge = 40; // borders are about 40 pixels from the edge for LBQS quasars 395 // this area defines a rectangle which should be obtained during the calibration 396 int xEdgeLow = edge; 397 int xEdgeHigh = width - edge; 398 int yEdgeLow = edge; 399 int yEdgeHigh = height - edge; 400 401 // data for HD124448; 402 //edge = 100; 403 //int xEdgeLow = 0; 404 //int xEdgeHigh = width; 405 //int yEdgeLow = edge; 406 //int yEdgeHigh = height; 407 408 double x, y; 409 int penHeight; 410 double dataX, dataY; 411 for (int i = 0; i < getSamples(); i++) { 412 byte aByte; 413 penHeight = 0; 414 if (i > xEdgeLow && i < xEdgeHigh) { 415 int sumj = 0; // the sum of the height of the 'black' pixels 416 int blackPixels = 0; // the number of 'black' pixels 417 int offset = yEdgeLow * width + i; 418 for (int j = yEdgeLow; j < yEdgeHigh; j++) { 419 aByte = byteData[offset]; // -1 is white, 0 is black, 420 offset += width; 421 if (aByte >= 0 && aByte < getBlackThreshold()) { 422 sumj += j; 423 blackPixels++; 424 } 425 } 426 if (blackPixels > 0) 427 penHeight = sumj / blackPixels; // average of the height of the 'black' pixels 428 } 429 //dataX = 3200.0d + (7000.0d - 3200.0d) * (double) i / (double) width; 430 dataX = 3200.0d + (5160.0d - 3200.0d) * (double) i / (double) width; 431 if (penHeight == 0) 432 dataY = 0.0d; 433 else 434 dataY = (double) (height - penHeight)/ (double) height; 435 436 data[i] = new DataCoordinate(dataX, dataY); 437 imagePoints[i] = new ImageCoordinate(i, penHeight); 438 } 439 setDataAvailable(true); 440 xRule.setImagePoints(imagePoints); // let the x rule display a gray representation of plot data 441 } 442 443 public void overlay() { 444 445 // TODO: how do we draw into the viewport, use createImage(w,h) ? 446 //Graphics g = imageIcon.getImage().getGraphics(); 447 448 if (imageIcon != null) { 449 ImageIcon newImageIcon; 450 if (isDataAvailable() && isOverlay()) { 451 Image image = imageIcon.getImage(); 452 int width = imageIcon.getIconWidth(); 453 int height = imageIcon.getIconHeight(); 454 455 Image bufferedImage = createImage(width, height); 456 Graphics2D g2 = (Graphics2D) bufferedImage.getGraphics(); 457 g2.drawImage(image, 0, 0, this); 458 g2.setColor(Color.red); // overlay color 459 460 ImageCoordinate point; 461 int x, y, lastx = 0, lasty = height-1; 462 for (int i = 0; i < getSamples(); i++) { 463 point = imagePoints[i]; 464 if (point != null) { 465 x = (int) point.getX(); 466 y = (int) point.getY(); 467 if (y == 0) y = height-1; 468 g2.drawLine(lastx, lasty, x, y); 469 lastx = x; 470 lasty = y; 471 } 472 } 473 newImageIcon = new ImageIcon(bufferedImage); 474 } else { 475 newImageIcon = imageIcon; // clear overlay 476 } 477 JLabel label = new JLabel(newImageIcon); 478 label.setVerticalAlignment(JLabel.TOP); 479 label.setHorizontalAlignment(JLabel.LEFT); 480 scrollPane.setViewportView(label); 481 } 482 } 483 484 public static void main(String argv[]) { 485 final PlotRecognizer recognizer = new PlotRecognizer("Plot Recognizer v1.0"); 486 recognizer.init(); 487 } 488 489 //-----Accessor methods--------------------------------------------------------------------------------- 490 491 /** Set the data output format such as text or xml. 492 * @param aDataOutputFormat the data output format 493 */ 494 public void setDataOutputFormat(String aDataOutputFormat) { 495 dataOutputFormat = aDataOutputFormat; 496 } 497 498 /** Get the data output format such as text or xml. 499 * @return the data output format 500 */ 501 public String getDataOutputFormat() { 502 return dataOutputFormat; 503 } 504 505 /** Get the text output format string for the x data values, which determines the precision or number of significant digits when exporting the x value as text 506 * @return a decimal format string for the x values 507 */ 508 public String getXTextOutputFormat() { 509 return xTextOutputFormat; 510 } 511 512 /** Set the text output format string for the x data values. 513 * @param aXTextOutputFormat a string representing the decimal text output format for the x values 514 */ 515 public void setXTextOutputFormat(String aXTextOutputFormat) { 516 xTextOutputFormat = aXTextOutputFormat; 517 } 518 519 /** Get the text output format string for the y data values, which determines the precision or number of significant digits when exporting the y value as text 520 * @return a decimal format string for the y values 521 */ 522 public String getYTextOutputFormat() { 523 return yTextOutputFormat; 524 } 525 526 /** Set the text output format string for the y data values. 527 * @param aYTextOutputFormat a string representing the decimal text output format for the y values 528 */ 529 public void setYTextOutputFormat(String aYTextOutputFormat) { 530 yTextOutputFormat = aYTextOutputFormat; 531 } 532 533 /** Get the gray color intensity below which a pixel is considered 'black' 534 * @return the threshold intensity for black, an integer between 0 and 255 535 */ 536 public int getBlackThreshold() { 537 return blackThreshold; 538 } 539 540 /** Set the gray color intensity below which a pixel is considered 'black' 541 * @param aBlackThreshold the threshold intensity for black, an integer between 0 and 255 542 */ 543 public void setBlackThreshold(int aBlackThreshold) { 544 blackThreshold = aBlackThreshold; 545 } 546 547 /** Get the number of data samples in the plot 548 * @return the number of data samples in the plot 549 */ 550 public int getSamples() { 551 return samples; 552 } 553 554 /** Set the number of data samples in the plot 555 * @param aSamples the number of data samples in the plot 556 */ 557 public void setSamples(int aSamples) { 558 samples = aSamples; 559 } 560 561 /** Get the data file type. 562 * @return a string representing the data file type. 563 */ 564 public String getDataFileType() { 565 return dataFileType; 566 } 567 568 /** Set the file name for the plot data. 569 * @param aDataFileType a string representing the data file name 570 */ 571 public void setDataFileType(String aDataFileType) { 572 dataFileType = aDataFileType; 573 } 574 575 /** Get the file name for the plot data. 576 * @return a string representing the data file name. 577 */ 578 public String getDataFileName() { 579 return dataFileName; 580 } 581 582 /** Set the file name for the plot data. 583 * @param aDataFileName a string representing the data file name 584 */ 585 public void setDataFileName(String aDataFileName) { 586 dataFileName = aDataFileName; 587 } 588 589 /** Get the file name for the image. 590 * @return a string representing the image file name. 591 */ 592 public String getImageFileName() { 593 return imageFileName; 594 } 595 596 public void setImageFileName(String anImageFileName) { 597 imageFileName = anImageFileName; 598 } 599 600 /** Get the status of the axes calibration procedure. 601 * @return true if the axes have been calibrated according to the axis labels 602 */ 603 public boolean isAxesCalibrated() { 604 return axesCalibrated; 605 } 606 607 /** Set the status of the axis calibration procedure. 608 * @param aAxesCalibrated boolean flag indicating if axes have been calibrated 609 */ 610 public void setAxesCalibrated(boolean aAxesCalibrated) { 611 axesCalibrated = aAxesCalibrated; 612 } 613 614 /** Get the status of the available processed data. 615 * @return true if image has been processed and data is available for saving etc... 616 */ 617 public boolean isDataAvailable() { 618 return dataAvailable; 619 } 620 621 /** Set the status of the available processed data. 622 * @param aDataAvailable a boolean flag indicating if the data is available 623 */ 624 public void setDataAvailable(boolean aDataAvailable) { 625 dataAvailable = aDataAvailable; 626 // these menus are disabled until some data is available 627 dataMenu.setEnabled(isDataAvailable()); 628 saveMenuItem.setEnabled(isDataAvailable()); 629 if (!isDataAvailable()) { 630 imagePoints = null; // clear data arrays 631 data = null; 632 } 633 overlay(); 634 } 635 636 /** Get the status of the image loading process. 637 * @return true if image is loaded and ready for processing 638 */ 639 public boolean isImageLoaded() { 640 return imageLoaded; 641 } 642 643 /** Set the status of the image loading process. 644 */ 645 public void setImageLoaded(boolean anImageLoaded) { 646 imageLoaded = anImageLoaded; 647 // these menus are disabled until an image is loaded 648 editMenu.setEnabled(isImageLoaded()); 649 viewMenu.setEnabled(isImageLoaded()); 650 } 651 652 /** Get the overlay option. 653 * @return true if overlay is to be plotted when available 654 */ 655 public boolean isOverlay() { 656 return overlay; 657 } 658 659 /** Set the overlay option. 660 * @param anOverlay a boolean flag representing the choice to plot data over the image 661 */ 662 public void setOverlay(boolean anOverlay) { 663 overlay = anOverlay; 664 overlay(); 665 } 666 667 //-------------------- drag and drop -------------------------------------------------- 668 669 // TODO: if a series of files are dropped then they are processed automatically 670 // each is recognized and its data is saved with the same filename but with .dat extension 671 672 public void dragEnter(DropTargetDragEvent e) { 673 e.acceptDrag(DnDConstants.ACTION_COPY); 674 } 675 676 public void dragOver(DropTargetDragEvent e) { 677 e.acceptDrag(DnDConstants.ACTION_COPY); 678 } 679 680 public void dragExit(DropTargetEvent e) { 681 } 682 683 public void drop(DropTargetDropEvent e) { 684 DropTargetContext targetContext = e.getDropTargetContext(); 685 686 boolean outcome = false; 687 688 if ((e.getSourceActions() & DnDConstants.ACTION_COPY) != 0) 689 e.acceptDrop(DnDConstants.ACTION_COPY); 690 else { 691 e.rejectDrop(); 692 return; 693 } 694 695 DataFlavor[] dataFlavors = e.getCurrentDataFlavors(); 696 DataFlavor transferDataFlavor = null; 697 698 for (int i = 0; i < dataFlavors.length; i++) { 699 if (dataFlavors[i].isFlavorJavaFileListType()) { 700 transferDataFlavor = dataFlavors[i]; 701 break; 702 } 703 } 704 705 // If a DataFlavor is specified with a MIME "Content-Type" of application/x-java-file-list;class=java.util.List 706 // the Drag and Drop system will expect the list elements to be a homogeneous list of objects of type java.io.File. 707 708 if (transferDataFlavor != null) { 709 Transferable t = e.getTransferable(); 710 try { 711 java.util.List fileList = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor); 712 processFiles(fileList); // progress monitor will not appear within this event handler method 713 outcome = true; 714 } catch(java.io.IOException ioe) { 715 System.out.println(ioe); 716 } catch(java.awt.datatransfer.UnsupportedFlavorException ex) { 717 System.out.println(ex); 718 } 719 } 720 targetContext.dropComplete(outcome); 721 } 722 723 public void dragScroll(DropTargetDragEvent e) { 724 } 725 726 public void dropActionChanged(DropTargetDragEvent e) { 727 // System.err.println("[Target] dropActionChanged"); 728 } 729 } 730