Author: mccaky
Date: Tue Nov 4 10:19:31 2014
New Revision: 1427
Log:
More event display updates.
Added:
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/LCIOManager.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsEvent.java (with props)
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsListener.java (with props)
Modified:
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/exec/Main.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/AdvancedReader.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/TextManager.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CalorimeterPanel.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java
java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/exec/Main.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/exec/Main.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/exec/Main.java Tue Nov 4 10:19:31 2014
@@ -1,72 +1,59 @@
package org.hps.monitoring.ecal.eventdisplay.exec;
-
-import org.hps.monitoring.ecal.eventdisplay.io.TextManager;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
+import java.io.File;
import java.io.IOException;
-import org.hps.monitoring.ecal.eventdisplay.ui.ActiveViewer;
-import org.hps.monitoring.ecal.eventdisplay.ui.ClusterViewer;
import org.hps.monitoring.ecal.eventdisplay.ui.FileViewer;
-import org.hps.monitoring.ecal.eventdisplay.ui.OccupancyViewer;
+import org.hps.monitoring.ecal.eventdisplay.ui.DataFileViewer;
/**
- * The class <code>Main</code> can be used to create an event display that
- * reads from file. By default it reads from "cluster-hit.txt" at the class
- * path root. This can be changed by altering the line<br/>
- * <code>window.setDataSource("cluster-hit.txt")</code><br/>
- **/
+ * The class <code>Main</code> can be used to create an event display
+ * that reads from file. The input file can be set with the "-i" command,
+ * though any file can be loaded from the file menu after initialization.
+ * Calorimeter wiring information can be loaded with the"-w" command.
+ */
public class Main {
-
public static void main(String[] args) throws IOException {
- // If "-h" was given as a command line argument, print the
- // help text.
- for(String s : args) {
- if(s.compareTo("-h") == 0 || s.compareTo("--help") == 0) {
- System.out.println("HPS Event Display");
- System.out.println("Options:");
- System.out.printf("%-4s%-12s%s%n", "-h", "--help", "Display help text.");
- System.out.printf("%-4s%-12s%s%n", "-i", "--input", "Defines the input file.");
- System.out.printf("%-4s%-12s%s%n", "-t", "--type", "Select the type of display.");
- System.out.printf("%-4s%-12s%s%n", "", "", "Allowed types: Event, Cluster, Occupancy");
- System.exit(0);
- }
- }
-
- // If -i or --input was given, set the input file.
- String filepath = "raw-hits.txt";
- for(int i = 0; i < args.length; i++) {
- if(args[i].compareTo("-i") == 0 || args[i].compareTo("--input") == 0) {
- if(args.length <= i + 1) { System.out.println("Error: Expected additional argument."); }
- else { filepath = args[i + 1]; }
- }
- }
-
- // Define the viewer. By default, we employ a file viewer.
- TextManager dataManager = new TextManager(filepath);
- ActiveViewer window = new FileViewer(dataManager);
+ // If "-h" was given as a command line argument, print the
+ // help text.
+ for(String s : args) {
+ if(s.compareTo("-h") == 0 || s.compareTo("--help") == 0) {
+ System.out.println("HPS Event Display");
+ System.out.println("Options:");
+ System.out.printf("%-4s%-12s%s%n", "-h", "--help", "Display help text.");
+ System.out.printf("%-4s%-12s%s%n", "-i", "--input", "Defines the input file.");
+ System.out.printf("%-4s%-12s%s%n", "-w", "--wiring", "Defines the wiring data file.");
+ System.exit(0);
+ }
+ }
- // Command line argument "-t" allows a different type to be declared.
- if(args.length >= 2 && (args[0].compareTo("-t") == 0 || args[0].compareTo("--type") == 0)) {
- // If an occupancy viewer has been specified...
- if(args[1].compareToIgnoreCase("Occupancy") == 0) {
- window = new OccupancyViewer(dataManager);
- }
- // If an event viewer has been specified...
- else if(args[1].compareToIgnoreCase("Event") == 0) {
- window = new FileViewer(dataManager);
- }
- // If a cluster viewer has been specified...
- else if(args[1].compareToIgnoreCase("Cluster") == 0) {
- window = new ClusterViewer(dataManager, 2);
- }
- // Otherwise, it is an invalid type.
- else {
- System.out.println("Display type \"" + args[1] + "\" not recognized.");
- System.exit(0);
- }
+ // If -i or --input was given, set the input file.
+ File dataSource = null;
+ String filepath = null;
+ for(int i = 0; i < args.length; i++) {
+ if(args[i].compareTo("-i") == 0 || args[i].compareTo("--input") == 0) {
+ if(args.length <= i + 1) { System.out.println("Error: Expected additional argument."); }
+ else { filepath = args[i + 1]; }
+ }
}
+ if(filepath != null) { dataSource = new File(filepath); }
+
+ // If -w or --wiring was given, set the input file.
+ String wiringPath = null;
+ for(int i = 0; i < args.length; i++) {
+ if(args[i].compareTo("-w") == 0 || args[i].compareTo("--witing") == 0) {
+ if(args.length <= i + 1) { System.out.println("Error: Expected additional argument."); }
+ else { wiringPath = args[i + 1]; }
+ }
+ }
+ if(filepath != null) { dataSource = new File(filepath); }
+
+ // Define the viewer.
+ FileViewer window;
+ if(wiringPath != null) { window = new DataFileViewer(dataSource, wiringPath); }
+ else { window = new FileViewer(dataSource); }
// Get screen size of primary monitor
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
@@ -77,8 +64,5 @@
window.setLocation((screenWidth - window.getPreferredSize().width) / 2,
(screenHeight - window.getPreferredSize().height) / 2);
window.setVisible(true);
-
- // Start the viewer with the first event.
- window.displayNextEvent();
}
-}
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/AdvancedReader.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/AdvancedReader.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/AdvancedReader.java Tue Nov 4 10:19:31 2014
@@ -13,237 +13,237 @@
* @author Kyle McCarty
*/
public class AdvancedReader extends Reader {
- private RandomAccessFile file;
- private long mark = -1;
-
- /**
- * <b>AdvancedReader</b><br/><br/>
- * <code>public <b>AdvancedReader</b>(String filepath)</code><br/><br/>
- * Constructs an <code>AdvancedReader</code> from the file located
- * at the given file path.
- * @param filepath - The path to the file that is to be loaded.
- * @throws FileNotFoundException - Occurs when there is no file at
- * the indicated file path.
- */
- public AdvancedReader(String filepath) throws FileNotFoundException {
- file = new RandomAccessFile(filepath, "r");
- }
-
- /**
- * <b>AdvancedReader</b><br/><br/>
- * <code>public <b>AdvancedReader</b>(File inputFile)</code><br/><br/>
- * Constructs an <code>AdvancedReader</code> from the indicated file.
- * @param inputFile - The file that is to be loaded.
- * @throws FileNotFoundException - Occurs when the referenced file
- * does not exist.
- */
- public AdvancedReader(File inputFile) throws FileNotFoundException {
- file = new RandomAccessFile(inputFile.getAbsolutePath(), "r");
- }
-
- public void close() throws IOException { file.close(); }
-
- public void mark(int readAheadLimit) throws IOException { mark = file.getFilePointer(); }
-
- public boolean markSupported() { return true; }
-
- public int read() throws IOException { return file.read(); }
-
- public int read(char[] cbuf) throws IOException {
- // Read a character from the file into each spot in the array.
- for(int i = 0; i < cbuf.length; i++) {
- // Get the next character.
- int curChar = file.read();
-
- // If the character exists, write it to the array.
- if(curChar != 0) { cbuf[i] = (char)curChar; }
-
- // Otherwise, return noting the number of filled slots.
- else { return i; }
- }
-
- // If we reach the end of the loop, all array slots are filled.
- return cbuf.length;
- }
-
- public int read(char[] cbuf, int off, int len) throws IOException {
- // We will fill the char array until either the indicated number
- // of slots are filled or until we run out of slots.
- int[] max = { cbuf.length, off + len };
-
- // Track the number of slots written to.
- int slotsFilled = 0;
-
- // Fill the array slots.
- for(int i = off; (i < max[0] && i < max[1]); i++) {
- // Get the next character.
- int curChar = file.read();
-
- // If the character is defined, write it.
- if(curChar != -1) {
- cbuf[i] = (char)curChar;
- slotsFilled++;
- }
-
- // Otherwise, return noting the number of filled slots.
- else { return slotsFilled; }
- }
-
- // If we reach the end of the loop, all array slots are filled.
- return slotsFilled;
- }
-
- /**
- * <b>readNextLine</b><br/><br/>
- * <code>public String <b>readNextLine</b>()</code><br/><br/>
- * Reads the next line of text. A line is considered to be
- * terminated by any one of a line feed ('\n'), a carriage return
- * ('\r'), or a carriage return followed immediately by a linefeed.
- * @return A String containing the contents of the line, not
- * including any line-termination characters, or null if the end
- * of the stream has been reached.
- * @throws IOException - Occurs if there is an issue reading
- * the file.
- */
- public String readNextLine() throws IOException {
- // Store whether the new line we found was a carriage return
- // or a proper newline.
- boolean readCarriageReturn = false;
-
- // Add characters to a buffer until we reach either a new line
- // or a carriage return.
- int curChar = -1;
- StringBuffer curLine = new StringBuffer();
- while((curChar = file.read()) != -1) {
- if(curChar != '\n' && curChar != '\r') { curLine.append((char)curChar); }
- else if(curChar == '\r') {
- readCarriageReturn = true;
- break;
- }
- else { break; }
- }
-
- // If we reached this point because we hit the end of the file,
- // check to make sure that the string buffer contains something.
- // If it doesn't, then we started at the end of the file and
- // should return null. Otherwise, just return what is in the
- // string buffer.
- if(curChar == -1) {
- if(curLine.length() == 0) { return null; }
- else { return curLine.toString(); }
- }
-
- // If we found a carriage return as the new line character, then
- // we need to check if the next line is a newline '\n' character,
- // since some systems us '/r/n' for a new line signifier.
- if(readCarriageReturn) {
- curChar = file.read();
- if(curChar != '\n') { file.seek(file.getFilePointer() - 1); }
- }
-
- // Return the buffer.
- return curLine.toString();
- }
-
- /**
- * <b>readPreviousLine</b><br/><br/>
- * <code>public String <b>readPreviousLine</b>()</code><br/><br/>
- * Reads the previous line of text. A line is considered to be
- * terminated by any one of a line feed ('\n'), a carriage return
- * ('\r'), or a carriage return followed immediately by a linefeed.
- * @return A <code>String</code> containing the contents of the
- * line, not including any line-termination characters, or null
- * if the beginning of the stream has been reached.
- * @throws IOException - Occurs if there is an issue reading
- * the file.
- */
- public String readPreviousLine() throws IOException {
- // Define variables.
- short newlinesRead = 0;
- boolean allowDuplicate = false;
- int lastChar = -1;
- long offset = file.getFilePointer();
- int curChar;
-
- // If we are at the start of the file, return null.
- if(offset == 0) { return null; }
-
- while(newlinesRead < 3) {
- // Decrement the offset.
- offset -= 1;
-
- // If the offset is still within the bounds of the file,
- // then go to it.
- if(offset >= 0) {
- // Get the new file position.
- file.seek(offset);
-
- // Read the character there.
- curChar = file.read();
-
- // If this a new line character, account for it.
- if(curChar == '\n' || curChar == '\r') {
- // If we have read a newline, and we then read another
- // immediately after it, then we will accept that newline
- // as well, since some systems use
- if(((lastChar == '\n' && curChar == '\r') || (lastChar == '\r' && curChar == '\n')) && allowDuplicate) {
- allowDuplicate = false;
- }
-
- // If this is the first newline character we have
- // seen, then we have reached the end of the desired
- // line. We need to keep going until we find the start.
- else if(newlinesRead < 3) {
- newlinesRead++;
- allowDuplicate = true;
- }
- }
-
- // If a character other than a newline was read after
- // a newline, then a second newline is always unrelated.
- else { allowDuplicate = false; }
-
- // Set the current character to the last read character.
- lastChar = curChar;
- }
- // If the offset has reached zero, but didn't start there,
- // then we have reached the start of the file. We handle
- // this case.
- else {
- // Set the pointer to the beginning of the file.
- file.seek(0);
-
- // If we are looking for the final new line, then the
- // start of the file counts and we should return.
- if(newlinesRead == 2) { return readNextLine(); }
-
- // Otherwise, there is no previous line.
- else { return null; }
- }
- }
-
- // If we reach this return line, we should be at the correct
- // position to read the previous line.
- return readNextLine();
- }
-
- public void reset() throws IOException {
- if(mark != -1) { file.seek(mark); }
- else { throw new IOException("mark() must be called before reset()."); }
- }
-
- public long skip(long n) throws IOException {
- // Read n characters.
- for(int i = 0; i < n; i++) {
- // Get the skipped character.
- int curChar = file.read();
-
- // If it is invalid, return.
- if(curChar == -1) { return i; }
- }
-
- // If we reached the end of the loop, the requested number of
- // characters have been skipped.
- return n;
- }
-}
+ private RandomAccessFile file;
+ private long mark = -1;
+
+ /**
+ * Constructs an <code>AdvancedReader</code> from the file located
+ * at the given file path.
+ * @param filepath - The path to the file that is to be loaded.
+ * @throws FileNotFoundException - Occurs when there is no file at
+ * the indicated file path.
+ */
+ public AdvancedReader(String filepath) throws FileNotFoundException {
+ file = new RandomAccessFile(filepath, "r");
+ }
+
+ /**
+ * Constructs an <code>AdvancedReader</code> from the indicated file.
+ * @param inputFile - The file that is to be loaded.
+ * @throws FileNotFoundException - Occurs when the referenced file
+ * does not exist.
+ */
+ public AdvancedReader(File inputFile) throws FileNotFoundException {
+ file = new RandomAccessFile(inputFile.getAbsolutePath(), "r");
+ }
+
+ @Override
+ public void close() throws IOException { file.close(); }
+
+ @Override
+ public void mark(int readAheadLimit) throws IOException { mark = file.getFilePointer(); }
+
+ @Override
+ public boolean markSupported() { return true; }
+
+ @Override
+ public int read() throws IOException { return file.read(); }
+
+ @Override
+ public int read(char[] cbuf) throws IOException {
+ // Read a character from the file into each spot in the array.
+ for(int i = 0; i < cbuf.length; i++) {
+ // Get the next character.
+ int curChar = file.read();
+
+ // If the character exists, write it to the array.
+ if(curChar != 0) { cbuf[i] = (char)curChar; }
+
+ // Otherwise, return noting the number of filled slots.
+ else { return i; }
+ }
+
+ // If we reach the end of the loop, all array slots are filled.
+ return cbuf.length;
+ }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ // We will fill the char array until either the indicated number
+ // of slots are filled or until we run out of slots.
+ int[] max = { cbuf.length, off + len };
+
+ // Track the number of slots written to.
+ int slotsFilled = 0;
+
+ // Fill the array slots.
+ for(int i = off; (i < max[0] && i < max[1]); i++) {
+ // Get the next character.
+ int curChar = file.read();
+
+ // If the character is defined, write it.
+ if(curChar != -1) {
+ cbuf[i] = (char)curChar;
+ slotsFilled++;
+ }
+
+ // Otherwise, return noting the number of filled slots.
+ else { return slotsFilled; }
+ }
+
+ // If we reach the end of the loop, all array slots are filled.
+ return slotsFilled;
+ }
+
+ /**
+ * Reads the next line of text. A line is considered to be
+ * terminated by any one of a line feed ('\n'), a carriage return
+ * ('\r'), or a carriage return followed immediately by a linefeed.
+ * @return A String containing the contents of the line, not
+ * including any line-termination characters, or null if the end
+ * of the stream has been reached.
+ * @throws IOException - Occurs if there is an issue reading
+ * the file.
+ */
+ public String readNextLine() throws IOException {
+ // Store whether the new line we found was a carriage return
+ // or a proper newline.
+ boolean readCarriageReturn = false;
+
+ // Add characters to a buffer until we reach either a new line
+ // or a carriage return.
+ int curChar = -1;
+ StringBuffer curLine = new StringBuffer();
+ while((curChar = file.read()) != -1) {
+ if(curChar != '\n' && curChar != '\r') { curLine.append((char)curChar); }
+ else if(curChar == '\r') {
+ readCarriageReturn = true;
+ break;
+ }
+ else { break; }
+ }
+
+ // If we reached this point because we hit the end of the file,
+ // check to make sure that the string buffer contains something.
+ // If it doesn't, then we started at the end of the file and
+ // should return null. Otherwise, just return what is in the
+ // string buffer.
+ if(curChar == -1) {
+ if(curLine.length() == 0) { return null; }
+ else { return curLine.toString(); }
+ }
+
+ // If we found a carriage return as the new line character, then
+ // we need to check if the next line is a newline '\n' character,
+ // since some systems us '/r/n' for a new line signifier.
+ if(readCarriageReturn) {
+ curChar = file.read();
+ if(curChar != '\n') { file.seek(file.getFilePointer() - 1); }
+ }
+
+ // Return the buffer.
+ return curLine.toString();
+ }
+
+ /**
+ * Reads the previous line of text. A line is considered to be
+ * terminated by any one of a line feed ('\n'), a carriage return
+ * ('\r'), or a carriage return followed immediately by a linefeed.
+ * @return A <code>String</code> containing the contents of the
+ * line, not including any line-termination characters, or null
+ * if the beginning of the stream has been reached.
+ * @throws IOException - Occurs if there is an issue reading
+ * the file.
+ */
+ public String readPreviousLine() throws IOException {
+ // Define variables.
+ short newlinesRead = 0;
+ boolean allowDuplicate = false;
+ int lastChar = -1;
+ long offset = file.getFilePointer();
+ int curChar;
+
+ // If we are at the start of the file, return null.
+ if(offset == 0) { return null; }
+
+ while(newlinesRead < 3) {
+ // Decrement the offset.
+ offset -= 1;
+
+ // If the offset is still within the bounds of the file,
+ // then go to it.
+ if(offset >= 0) {
+ // Get the new file position.
+ file.seek(offset);
+
+ // Read the character there.
+ curChar = file.read();
+
+ // If this a new line character, account for it.
+ if(curChar == '\n' || curChar == '\r') {
+ // If we have read a newline, and we then read another
+ // immediately after it, then we will accept that newline
+ // as well, since some systems use
+ if(((lastChar == '\n' && curChar == '\r') || (lastChar == '\r' && curChar == '\n')) && allowDuplicate) {
+ allowDuplicate = false;
+ }
+
+ // If this is the first newline character we have
+ // seen, then we have reached the end of the desired
+ // line. We need to keep going until we find the start.
+ else if(newlinesRead < 3) {
+ newlinesRead++;
+ allowDuplicate = true;
+ }
+ }
+
+ // If a character other than a newline was read after
+ // a newline, then a second newline is always unrelated.
+ else { allowDuplicate = false; }
+
+ // Set the current character to the last read character.
+ lastChar = curChar;
+ }
+ // If the offset has reached zero, but didn't start there,
+ // then we have reached the start of the file. We handle
+ // this case.
+ else {
+ // Set the pointer to the beginning of the file.
+ file.seek(0);
+
+ // If we are looking for the final new line, then the
+ // start of the file counts and we should return.
+ if(newlinesRead == 2) { return readNextLine(); }
+
+ // Otherwise, there is no previous line.
+ else { return null; }
+ }
+ }
+
+ // If we reach this return line, we should be at the correct
+ // position to read the previous line.
+ return readNextLine();
+ }
+
+ @Override
+ public void reset() throws IOException {
+ if(mark != -1) { file.seek(mark); }
+ else { throw new IOException("mark() must be called before reset()."); }
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ // Read n characters.
+ for(int i = 0; i < n; i++) {
+ // Get the skipped character.
+ int curChar = file.read();
+
+ // If it is invalid, return.
+ if(curChar == -1) { return i; }
+ }
+
+ // If we reached the end of the loop, the requested number of
+ // characters have been skipped.
+ return n;
+ }
+}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/LCIOManager.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/LCIOManager.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/LCIOManager.java Tue Nov 4 10:19:31 2014
@@ -0,0 +1,209 @@
+package org.hps.monitoring.ecal.eventdisplay.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.monitoring.ecal.eventdisplay.event.Cluster;
+import org.hps.monitoring.ecal.eventdisplay.event.EcalHit;
+import org.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.lcio.LCIOReader;
+
+/**
+ * Class <code>LCIOManager</code> is an implementation of <code>
+ * EventManager</code> for (S)LCIO files.<br/>
+ * <br/>
+ * <b><span style="color:red">Warning: This class is under construction
+ * and should not be used at this time!</span></b>
+ *
+ * @author Kyle McCarty
+ */
+public class LCIOManager implements EventManager {
+ // Internal variables.
+ private LCIOReader reader;
+ private EventHeader current;
+ private int eventsRead = 0;
+ private final File sourceFile;
+
+ // LCIO collection names.
+ private String clusterCollectionName = "EcalClusters";
+ private String hitCollectionName = "EcalHits";
+
+ public LCIOManager(String inputFilepath) throws IOException {
+ this(new File(inputFilepath));
+ }
+
+ public LCIOManager(File input) throws IOException {
+ // Create an LCIO reader from the file.
+ reader = new LCIOReader(input);
+
+ // Store the source file.
+ sourceFile = input;
+
+ // Read the first event.
+ nextEvent();
+ }
+
+ public void setClusterCollectionName(String clusterCollectionName) {
+ this.clusterCollectionName = clusterCollectionName;
+ }
+
+ public void setHitCollectionName(String hitCollectionName) {
+ this.hitCollectionName = hitCollectionName;
+ }
+
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+
+ @Override
+ public int getEventNumber() {
+ // If there is a currently defined event, get it's event number.
+ if(current != null) { return current.getEventNumber(); }
+
+ // Otherwise, return -1.
+ else { return -1; }
+ }
+
+ @Override
+ public List<Cluster> getClusters() {
+ // If the current event is undefined, return an empty list.
+ if(current == null) { return new ArrayList<Cluster>(); }
+
+ // Otherwise, try to obtain and convert the cluster collection
+ // from the LCIO event.
+ else {
+ // Check to see if the event has a cluster collection.
+ if(current.hasCollection(HPSEcalCluster.class, clusterCollectionName)) {
+ // Get the list of LCIO clusters.
+ List<HPSEcalCluster> lcioList = current.get(HPSEcalCluster.class, clusterCollectionName);
+
+ // Create a list to store event display clusters.
+ List<Cluster> displayList = new ArrayList<Cluster>(lcioList.size());
+
+ // Convert the LCIO clusters to display clusters.
+ for(HPSEcalCluster lcioCluster : lcioList) {
+ displayList.add(toPanelCluster(lcioCluster));
+ }
+
+ // Return the converted list of clusters.
+ return displayList;
+ }
+
+ // If it does not, return an empty list.
+ else { return new ArrayList<Cluster>(); }
+ }
+ }
+
+ @Override
+ public List<EcalHit> getHits() {
+ System.out.println("Event is null: " + (current == null));
+
+ // If the current event is undefined, return an empty list.
+ if(current == null) { return new ArrayList<EcalHit>(); }
+
+ // Otherwise, try to obtain and convert the hit collection from
+ // the LCIO event.
+ else {
+ System.out.println("Check for hits...");
+ // Check to see if the event has a hit collection.
+ if(current.hasCollection(CalorimeterHit.class, hitCollectionName)) {
+ System.out.println("Has hits!");
+ // Get the list of LCIO hits.
+ List<CalorimeterHit> lcioList = current.get(CalorimeterHit.class, hitCollectionName);
+
+ // Create a list to store event display hits.
+ List<EcalHit> displayList = new ArrayList<EcalHit>(lcioList.size());
+
+ // Convert the LCIO clusters to display clusters.
+ for(CalorimeterHit lcioHit : lcioList) {
+ displayList.add(toPanelHit(lcioHit));
+ }
+
+ // Return the converted list of clusters.
+ return displayList;
+ }
+
+ // If it does not, return an empty list.
+ else { return new ArrayList<EcalHit>(); }
+ }
+ }
+
+ @Override
+ public boolean nextEvent() throws IOException {
+ // Try to read the next event.
+ try { current = reader.read(); }
+
+ // If the read action fails, then there is no next event.
+ catch(IOException e) {
+ current = null;
+ return false;
+ }
+
+ // Note that another event has been read.
+ eventsRead++;
+
+ // Otherwise, indicate that an event was read.
+ return true;
+ }
+
+ @Override
+ public boolean previousEvent() throws IOException {
+ // If we are on the first event, there is no previous event.
+ if(eventsRead == 0 || eventsRead == 1) { return false; }
+
+ // Otherwise, reset the reader and skip to the previous event.
+ else {
+ // Create a new reader.
+ reader = new LCIOReader(sourceFile);
+
+ // Skip to immediately before the previous event.
+ reader.skipEvents(eventsRead - 2);
+
+ // Read the next event.
+ try { current = reader.read(); }
+
+ // If the read fails, return false.
+ catch(IOException e) {
+ current = null;
+ return false;
+ }
+
+ // Decrement the number of events read.
+ eventsRead--;
+
+ // Otherwise, indicate that an event was read.
+ return true;
+ }
+ }
+
+ public static final Cluster toPanelCluster(HPSEcalCluster lcioCluster) {
+ // If the argument is null, return null.
+ if(lcioCluster == null) { return null; }
+
+ // Otherwise, get the cluster x/y indices and energy.
+ int ix = lcioCluster.getSeedHit().getIdentifierFieldValue("ix");
+ int iy = lcioCluster.getSeedHit().getIdentifierFieldValue("iy");
+ double energy = lcioCluster.getEnergy();
+
+ // Create and return a panel cluster from the above values.
+ return new Cluster(ix, iy, energy);
+ }
+
+ public static final EcalHit toPanelHit(CalorimeterHit lcioHit) {
+ // If the argument is null, return null.
+ if(lcioHit == null) { return null; }
+
+ // Otherwise, get the cluster x/y indices and energy.
+ int ix = lcioHit.getIdentifierFieldValue("ix");
+ int iy = lcioHit.getIdentifierFieldValue("iy");
+ double energy = lcioHit.getCorrectedEnergy();
+
+ // Create and return a panel hit from the above values.
+ return new EcalHit(ix, iy, energy);
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/TextManager.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/TextManager.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/io/TextManager.java Tue Nov 4 10:19:31 2014
@@ -1,5 +1,6 @@
package org.hps.monitoring.ecal.eventdisplay.io;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
@@ -37,10 +38,10 @@
* Indicates that the event has ended.
*
* @author Kyle McCarty
- **/
+ */
public final class TextManager implements EventManager {
// File reader for reading the input.
- private AdvancedReader reader;
+ private AdvancedReader reader;
// List for storing the hits from the current event.
private ArrayList<EcalHit> hitList = new ArrayList<EcalHit>();
// List for storing the clusters from the current hit.
@@ -51,34 +52,45 @@
private int curEvent = 0;
/**
- * <b>EventManager</b><br/><br/>
- * <code>public <b>EventManager</b>(String filename)</code><br/><br/>
* Initializes an event manager that will read from the indicated file.
* @param filename - The path to the file containing hit information.
- **/
+ */
+ public TextManager(File file) throws IOException {
+ reader = new AdvancedReader(file);
+ }
+
+ /**
+ * Initializes an event manager that will read from the indicated file.
+ * @param filename - The path to the file containing hit information.
+ */
public TextManager(String filename) throws IOException {
- reader = new AdvancedReader(filename);
- }
-
+ reader = new AdvancedReader(filename);
+ }
+
+ @Override
public void close() throws IOException {
reader.close();
open = false;
}
+ @Override
public int getEventNumber() {
- return curEvent;
- }
-
+ return curEvent;
+ }
+
+ @Override
public ArrayList<Cluster> getClusters() {
if (!open) { return null; }
else { return clusterList; }
}
+ @Override
public ArrayList<EcalHit> getHits() {
if (!open) { return null; }
else { return hitList; }
}
+ @Override
public boolean nextEvent() throws IOException {
// We can only read of the reader is open.
if (!open) { return false; }
@@ -115,12 +127,12 @@
// If this is a cluster, add a new cluster object.
if (name.compareTo("Cluster") == 0) {
- // Get the cluster energy, if it is given.
- double clusterEnergy = Double.NaN;
- if(st.hasMoreTokens()) { clusterEnergy = Double.parseDouble(st.nextToken()); }
-
- // Add a new cluster.
- clusterList.add(new Cluster(ix, iy, clusterEnergy));
+ // Get the cluster energy, if it is given.
+ double clusterEnergy = Double.NaN;
+ if(st.hasMoreTokens()) { clusterEnergy = Double.parseDouble(st.nextToken()); }
+
+ // Add a new cluster.
+ clusterList.add(new Cluster(ix, iy, clusterEnergy));
}
// If this is a calorimeter hit, add a new calorimeter hit object.
@@ -131,24 +143,24 @@
// If this is a cluster component hit, add it to the last cluster.
else if(name.compareTo("CompHit") == 0) {
- // There must be a last cluster to process this hit type.
- if(clusterList.size() == 0) {
- System.err.println("File Format Error: A cluster component hit was read, but" +
- " no cluster has been declared. Terminating.");
- System.exit(1);
- }
- else { clusterList.get(clusterList.size() - 1).addComponentHit(ix, iy); }
+ // There must be a last cluster to process this hit type.
+ if(clusterList.size() == 0) {
+ System.err.println("File Format Error: A cluster component hit was read, but" +
+ " no cluster has been declared. Terminating.");
+ System.exit(1);
+ }
+ else { clusterList.get(clusterList.size() - 1).addComponentHit(ix, iy); }
}
// If this is a cluster shared hit, add it to the last cluster.
else if(name.compareTo("SharHit") == 0) {
- // There must be a last cluster to process this hit type.
- if(clusterList.size() == 0) {
- System.err.println("File Format Error: A cluster shared hit was read, but" +
- " no cluster has been declared. Terminating.");
- System.exit(1);
- }
- else { clusterList.get(clusterList.size() - 1).addSharedHit(ix, iy); }
+ // There must be a last cluster to process this hit type.
+ if(clusterList.size() == 0) {
+ System.err.println("File Format Error: A cluster shared hit was read, but" +
+ " no cluster has been declared. Terminating.");
+ System.exit(1);
+ }
+ else { clusterList.get(clusterList.size() - 1).addSharedHit(ix, iy); }
}
// Get the next line.
@@ -159,37 +171,38 @@
return true;
}
+ @Override
public boolean previousEvent() throws IOException {
- // If we are at the first event, do nothing. There is no
- // previous event to display.
- if(curEvent == 1) { return false; }
-
- // Otherwise, loop backward until we find the previous event header.
- String curLine;
- while(true) {
- // Get the previous line.
- curLine = reader.readPreviousLine();
-
- // Otherwise, if it is null, we've reached the start of the file.
- if(curLine == null) {
- System.err.println("Error: Unexpectedly reached SOF.");
- System.exit(1);
- }
-
- // If the previous line is an event, note it.
- if(curLine.substring(0, 5).compareTo("Event") == 0) {
- // Get the event number of the current event.
- StringTokenizer et = new StringTokenizer(curLine);
- et.nextToken();
- int readEvent = Integer.parseInt(et.nextToken());
-
- // If the read event number is one back from the current
- // event, jump back a step and read the event.
- if(readEvent == (curEvent - 1)) {
- reader.readPreviousLine();
- return nextEvent();
- }
- }
- }
- }
-}
+ // If we are at the first event, do nothing. There is no
+ // previous event to display.
+ if(curEvent == 1) { return false; }
+
+ // Otherwise, loop backward until we find the previous event header.
+ String curLine;
+ while(true) {
+ // Get the previous line.
+ curLine = reader.readPreviousLine();
+
+ // Otherwise, if it is null, we've reached the start of the file.
+ if(curLine == null) {
+ System.err.println("Error: Unexpectedly reached SOF.");
+ System.exit(1);
+ }
+
+ // If the previous line is an event, note it.
+ if(curLine.substring(0, 5).compareTo("Event") == 0) {
+ // Get the event number of the current event.
+ StringTokenizer et = new StringTokenizer(curLine);
+ et.nextToken();
+ int readEvent = Integer.parseInt(et.nextToken());
+
+ // If the read event number is one back from the current
+ // event, jump back a step and read the event.
+ if(readEvent == (curEvent - 1)) {
+ reader.readPreviousLine();
+ return nextEvent();
+ }
+ }
+ }
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/ActiveViewer.java Tue Nov 4 10:19:31 2014
@@ -1,13 +1,12 @@
package org.hps.monitoring.ecal.eventdisplay.ui;
-import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.awt.image.BufferedImage;
-import java.io.File;
import java.io.IOException;
-import javax.imageio.ImageIO;
+import javax.swing.JMenuItem;
import org.hps.monitoring.ecal.eventdisplay.io.EventManager;
@@ -15,15 +14,20 @@
* Abstract class <code>ActiveViewer</code> describes a <code>Viewer
* </code> object that is connected to a static data source. It is
* designed to instruct the data source when to provide new events.
+ * <br/><br/>
+ * <code>ActiveViewer</code> is now superseded by <code>FileViewer
+ * </code>, which functions on its own. Any additional file types that
+ * should be supported should be added directly to <code>FileViewer
+ * </code> or a subclass. <code>ActiveViewer</code> will be removed
+ * from coming releases.
*
* @author Kyle McCarty
*/
+@Deprecated
public abstract class ActiveViewer extends Viewer {
- private static final long serialVersionUID = -6107646224627009923L;
- // Stores whether the background color is set or not.
- private boolean background = false;
+ private static final long serialVersionUID = 2L;
// Gets events from some file.
- protected final EventManager em;
+ protected EventManager em;
/**
* Creates an active-type <code>Viewer</code> window which draws
@@ -39,6 +43,15 @@
// Set the data source.
this.em = em;
+
+ // Add an exit command to the file menu.
+ JMenuItem menuExit = new JMenuItem("Exit", KeyEvent.VK_X);
+ menuExit.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { dispose(); }
+ });
+ menu[MENU_FILE].addSeparator();
+ menu[MENU_FILE].add(menuExit);
// Make a key listener to change events.
addKeyListener(new EcalKeyListener());
@@ -59,16 +72,11 @@
/**
* The <code>EcalListener</code> class binds keys to actions.
* Bound actions include:
- * [Right Arrow] :: Next event (stand-alone mode only)
- * [Left Arrow ] :: Previous event (stand-alone mode only)
- * b :: Toggle color-mapping for 0 energy crystals
- * h :: Toggle selected crystal highlighting
- * l :: Toggle logarithmic versus linear scaling
- * s :: Saves the current display to a file
+ * [Right Arrow] :: Next event
+ * [Left Arrow ] :: Previous event
**/
- private class EcalKeyListener implements KeyListener {
- public void keyPressed(KeyEvent e) { }
-
+ private class EcalKeyListener extends KeyAdapter {
+ @Override
public void keyReleased(KeyEvent e) {
// If right-arrow was pressed, go to the next event.
if (e.getKeyCode() == 39) {
@@ -79,7 +87,7 @@
}
}
- // If right-arrow was pressed, go to the next event.
+ // If left-arrow was pressed, go to the next event.
else if (e.getKeyCode() == 37) {
try { displayPreviousEvent(); }
catch (IOException ex) {
@@ -88,63 +96,8 @@
}
}
- // 'b' toggles the default white background.
- else if(e.getKeyCode() == 66) {
- if(background) { ecalPanel.setDefaultCrystalColor(null); }
- else { ecalPanel.setDefaultCrystalColor(Color.GRAY); }
- background = !background;
- }
-
- // 'h' toggles highlighting the crystal under the cursor.
- else if(e.getKeyCode() == 72) { ecalPanel.setSelectionHighlighting(!ecalPanel.isSelectionEnabled()); }
-
- // 'l' toggles linear or logarithmic scaling.
- else if(e.getKeyCode() == 76) {
- if(ecalPanel.isScalingLinear()) { ecalPanel.setScalingLogarithmic(); }
- else { ecalPanel.setScalingLinear(); }
- }
-
- // 'x' toggles x-axis mirroring.
- else if(e.getKeyCode() == 88) {
- ecalPanel.setMirrorX(!ecalPanel.isMirroredX());
- updateStatusPanel();
- }
-
- // 'y' toggles y-axis mirroring.
- else if(e.getKeyCode() == 89) {
- ecalPanel.setMirrorY(!ecalPanel.isMirroredY());
- updateStatusPanel();
- }
-
- // 's' saves the panel to a file.
- else if(e.getKeyCode() == 83) {
- // Make a new buffered image on which to draw the content pane.
- BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
- getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
-
- // Paint the content pane to image.
- getContentPane().paint(screenshot.getGraphics());
-
- // Get the lowest available file name.
- int fileNum = 0;
- File imageFile = new File("screenshot_" + fileNum + ".png");
- while(imageFile.exists()) {
- fileNum++;
- imageFile = new File("screenshot_" + fileNum + ".png");
- }
-
- // Save the image to a PNG file.
- try { ImageIO.write(screenshot, "PNG", imageFile); }
- catch(IOException ioe) {
- System.err.println("Error saving file \"screenshot.png\".");
- }
- System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
- }
-
// Otherwise, print out the key code for the pressed key.
else { System.out.printf("Key Code: %d%n", e.getKeyCode()); }
}
-
- public void keyTyped(KeyEvent e) { }
}
-}
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CalorimeterPanel.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CalorimeterPanel.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CalorimeterPanel.java Tue Nov 4 10:19:31 2014
@@ -5,16 +5,22 @@
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import javax.swing.JPanel;
import org.hps.monitoring.ecal.eventdisplay.event.Association;
+import org.hps.monitoring.ecal.eventdisplay.util.ColorScale;
import org.hps.monitoring.ecal.eventdisplay.util.MultiGradientScale;
+import org.hps.monitoring.ecal.eventdisplay.util.SettingsEvent;
+import org.hps.monitoring.ecal.eventdisplay.util.SettingsListener;
/**
* The class <code>CalorimeterPanel</code> handles the rendering of the
@@ -22,24 +28,24 @@
* rendering a color scale, and marking cluster crystals.
*
* @author Kyle McCarty
- **/
+ */
public final class CalorimeterPanel extends JPanel {
// Java-suggested variable.
- private static final long serialVersionUID = 6292751227464151897L;
+ private static final long serialVersionUID = 2L;
// The color used for rendering seed hits.
private Color clusterColor = Color.GREEN;
// The default color of the calorimeter crystals.
private Color defaultColor = null;
// The color if disabled crystals.
private Color disabledColor = Color.BLACK;
- // The color for the selected crystal.
- private Color selectedColor = new Color(90, 170, 250);
- // Whether to allow highlighting of the selected crystal.
- private boolean enabledSelection = true;
- // Whether the crystals should redraw automatically or not.
- private boolean suppress = false;
+ // The color for the selected crystal.
+ private Color selectedColor = new Color(90, 170, 250);
+ // Whether to allow highlighting of the selected crystal.
+ private boolean enabledSelection = true;
+ // Whether the crystals should redraw automatically or not.
+ private boolean suppress = false;
// The color-mapping scale used by to color calorimeter crystals.
- private MultiGradientScale scale = MultiGradientScale.makeRainbowScale(0.0, 1.0);
+ private ColorScale scale = MultiGradientScale.makeRainbowScale(0.0, 1.0);
// The number of boxes in the x-direction.
private int xBoxes = 1;
// The number of boxes in the y-direction.
@@ -58,6 +64,8 @@
private Point selectedCrystal = null;
// The panel on which the scale is rendered.
private ScalePanel scalePanel = new ScalePanel();
+ // Store all settings listeners.
+ private List<SettingsListener> listenerList = new ArrayList<SettingsListener>();
// Efficiency variables for crystal placement.
private int[] xPosition;
@@ -72,7 +80,7 @@
* Initializes the calorimeter panel.
* @param numXBoxes - The number of crystals in the x-direction.
* @param numYBoxes - The number of crystals in the y-direction.
- **/
+ */
public CalorimeterPanel(int numXBoxes, int numYBoxes) {
// Initialize the base component.
super();
@@ -85,10 +93,10 @@
crystal = new Crystal[xBoxes][yBoxes];
for(int x = 0; x < xBoxes; x++) {
- for(int y = 0; y < yBoxes; y++) {
- crystal[x][y] = new Crystal();
- add(crystal[x][y]);
- }
+ for(int y = 0; y < yBoxes; y++) {
+ crystal[x][y] = new Crystal();
+ add(crystal[x][y]);
+ }
}
// Initialize the size arrays,
@@ -98,6 +106,14 @@
// Add the scale panel.
setLayout(null);
add(scalePanel);
+
+ // Add a component listener to trigger resizing.
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ resize();
+ }
+ });
}
// ================================================================================
@@ -114,18 +130,18 @@
* not correspond to a crystal.
*/
public void addAssociation(Association crystalAssociation) throws IndexOutOfBoundsException {
- // Validate the parent crystal's indices.
- Point parent = crystalAssociation.getParentCrystal();
- if(validateIndices(parent)) {
- // Validate the parent crystal's indices.
- Point child = crystalAssociation.getChildCrystal();
- if(validateIndices(child)) {
- // If both crystal index sets are valid, add the association.
- crystal[parent.x][parent.y].addAssociation(crystalAssociation);
- }
- else { throw new IndexOutOfBoundsException(String.format("Invalid child crystal address (%2d, %2d).", parent.x, parent.y)); }
- }
- else { throw new IndexOutOfBoundsException(String.format("Invalid parent crystal address (%2d, %2d).", parent.x, parent.y)); }
+ // Validate the parent crystal's indices.
+ Point parent = crystalAssociation.getParentCrystal();
+ if(validateIndices(parent)) {
+ // Validate the parent crystal's indices.
+ Point child = crystalAssociation.getChildCrystal();
+ if(validateIndices(child)) {
+ // If both crystal index sets are valid, add the association.
+ crystal[parent.x][parent.y].addAssociation(crystalAssociation);
+ }
+ else { throw new IndexOutOfBoundsException(String.format("Invalid child crystal address (%2d, %2d).", parent.x, parent.y)); }
+ }
+ else { throw new IndexOutOfBoundsException(String.format("Invalid parent crystal address (%2d, %2d).", parent.x, parent.y)); }
}
/**
@@ -136,12 +152,12 @@
* @param energy - The energy to add.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void addCrystalEnergy(int ix, int iy, double energy) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
if (validateIndices(ix, iy)) { crystal[ix][iy].addEnergy(energy); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -153,9 +169,17 @@
* @param energy - The energy to add.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void addCrystalEnergy(Point ixy, double energy) throws IndexOutOfBoundsException {
addCrystalEnergy(ixy.x, ixy.y, energy);
+ }
+
+ /**
+ * Adds a settings listener to the object.
+ * @param listener - The listener to add.
+ */
+ public void addSettingsListener(SettingsListener listener) {
+ if(listener != null) { listenerList.add(listener); }
}
/**
@@ -163,35 +187,35 @@
* from slightly under the smallest recorded value to the highest
* recorded value.
*/
- public void autoScale() {
- // If there is no energy on the calorimeter, just set the
- // scale to some default value.
- if(extremum[0] == Double.MAX_VALUE && extremum[1] == 0.0) {
- scale.setMaximum(1.0);
- scale.setMinimum(0.01);
- }
-
- // If the minimum is defined, set the scale such that it
- // will map that value to the low end and the highest value
- // to the top.
- else if(extremum[0] != Double.MAX_VALUE) {
- scale.setMaximum(extremum[1]);
- scale.setMinimum(extremum[0] / 2);
- }
- }
+ public void autoScale() {
+ // If there is no energy on the calorimeter, just set the
+ // scale to some default value.
+ if(extremum[0] == Double.MAX_VALUE && extremum[1] == 0.0) {
+ scale.setMaximum(1.0);
+ scale.setMinimum(0.01);
+ }
+
+ // If the minimum is defined, set the scale such that it
+ // will map that value to the low end and the highest value
+ // to the top.
+ else if(extremum[0] != Double.MAX_VALUE) {
+ scale.setMaximum(extremum[1]);
+ scale.setMinimum(extremum[0] / 2);
+ }
+ }
/**
* Sets all crystal energies to zero, removes all clusters, and
* clears all highlighting. This <b>does not</b> enable disabled
* crystals.
- **/
+ */
public void clearCrystals() {
for (int ix = 0; ix < xBoxes; ix++) {
for (int iy = 0; iy < yBoxes; iy++) {
- crystal[ix][iy].setState(0.0, false, null);
- crystal[ix][iy].clearAssociations();
- extremum[0] = Double.MAX_VALUE;
- extremum[1] = 0.0;
+ crystal[ix][iy].setState(0.0, false, null);
+ crystal[ix][iy].clearAssociations();
+ extremum[0] = Double.MAX_VALUE;
+ extremum[1] = 0.0;
}
}
}
@@ -209,11 +233,11 @@
* Clears crystal selection and sets it to <code>null</code>.
*/
public void clearSelectedCrystal() {
- // Clear any currently selected crystals.
- if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false); }
-
- // Set the selected crystal to null.
- selectedCrystal = null;
+ // Clear any currently selected crystals.
+ if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false); }
+
+ // Set the selected crystal to null.
+ selectedCrystal = null;
}
/**
@@ -225,11 +249,11 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public double getCrystalEnergy(int ix, int iy) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
- if(validateIndices(ix, iy)) { return crystal[ix][iy].getEnergy(); }
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
+ if(validateIndices(ix, iy)) { return crystal[ix][iy].getEnergy(); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -241,7 +265,7 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public double getCrystalEnergy(Point ixy) throws IndexOutOfBoundsException {
- return getCrystalEnergy(ixy.x, ixy.y);
+ return getCrystalEnergy(ixy.x, ixy.y);
}
/**
@@ -254,11 +278,11 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public Color getCrystalHighlight(int ix, int iy) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
- if(validateIndices(ix, iy)) { return crystal[ix][iy].getHighlight(); }
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
+ if(validateIndices(ix, iy)) { return crystal[ix][iy].getHighlight(); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -271,7 +295,7 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public Color getCrystalHighlight(Point ixy) throws IndexOutOfBoundsException {
- return getCrystalHighlight(ixy.x, ixy.y);
+ return getCrystalHighlight(ixy.x, ixy.y);
}
/**
@@ -284,38 +308,38 @@
* Returns <code>null</code> if the coordinates do not map to a crystal.
*/
public Point getCrystalID(int xCoor, int yCoor) {
- // If either coordinate is negative, return the null result.
- if(xCoor < 0 || yCoor < 0) { return null; }
-
- // If either coordinate is too large, return the nul result.
- if(xCoor > xPosition[xBoxes] || yCoor > yPosition[yBoxes]) {
- return null;
- }
-
- // Make a point to identify the crystal index.
- Point loc = new Point(-1, -1);
-
- // Determine which y index it is.
- for(int y = 0; y < yBoxes; y++) {
- if(yCoor <= yPosition[y + 1]) {
- loc.y = y;
- break;
- }
- }
-
- // Determine which x index it is.
- for(int x = 0; x < xBoxes; x++) {
- if(xCoor <= xPosition[x + 1]) {
- loc.x = x;
- break;
- }
- }
-
- // If either coordinate is not valid, return null.
- if(loc.x == -1 || loc.y == -1) { return null; }
-
- // Return the crystal identifier.
- return getMirroredPoint(loc, mirrorX, mirrorY);
+ // If either coordinate is negative, return the null result.
+ if(xCoor < 0 || yCoor < 0) { return null; }
+
+ // If either coordinate is too large, return the nul result.
+ if(xCoor > xPosition[xBoxes] || yCoor > yPosition[yBoxes]) {
+ return null;
+ }
+
+ // Make a point to identify the crystal index.
+ Point loc = new Point(-1, -1);
+
+ // Determine which y index it is.
+ for(int y = 0; y < yBoxes; y++) {
+ if(yCoor <= yPosition[y + 1]) {
+ loc.y = y;
+ break;
+ }
+ }
+
+ // Determine which x index it is.
+ for(int x = 0; x < xBoxes; x++) {
+ if(xCoor <= xPosition[x + 1]) {
+ loc.x = x;
+ break;
+ }
+ }
+
+ // If either coordinate is not valid, return null.
+ if(loc.x == -1 || loc.y == -1) { return null; }
+
+ // Return the crystal identifier.
+ return getMirroredPoint(loc, mirrorX, mirrorY);
}
/**
@@ -350,6 +374,13 @@
public Set<Point> getNeighbors(int cix, int ciy) { return getNeighbors(new Point(cix, ciy)); }
/**
+ * Gets the color that will be used for zero-energy crystals.
+ * @return Returns the zero-energy crystal color as a <code>Color
+ * </code> object.
+ */
+ public Color getDefaultCrystalColor() { return defaultColor; }
+
+ /**
* Gets the set of valid crystals that immediately surround the
* central crystal. Valid crystals must both have valid indices
* and also be enabled.
@@ -361,43 +392,43 @@
* x/y central crystal coordinates do not correspond to a crystal.
*/
public Set<Point> getNeighbors(Point centralCrystal) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- centralCrystal = getMirroredPoint(centralCrystal, mirrorX, mirrorY);
-
- // Make sure that the root is a valid crystal.
- if(!validateIndices(centralCrystal)) {
+ // Mirror the coordinates if appropriate.
+ centralCrystal = getMirroredPoint(centralCrystal, mirrorX, mirrorY);
+
+ // Make sure that the root is a valid crystal.
+ if(!validateIndices(centralCrystal)) {
throw new IndexOutOfBoundsException(String.format("Invalid central crystal address (%2d, %2d).",
- centralCrystal.x, centralCrystal.y));
- }
-
- // Make a set to store the neighbors in.
- HashSet<Point> neighborSet = new HashSet<Point>();
-
- // Check all the crystals in a 3-by-3 square around the root.
- // If they are valid crystals and they are not disable, then
- // they are neighbors.
- for(int xMod = -1; xMod <= 1; xMod++) {
- for(int yMod = -1; yMod <= 1; yMod++) {
- // Get the possible neighbor.
- Point possibleNeighbor = new Point(centralCrystal.x + xMod, centralCrystal.y + yMod);
-
- // Make sure that the possible neighbor is neither the
- // root crystal nor invalid.
- boolean isRoot = centralCrystal.equals(possibleNeighbor);
- boolean isValid = validateIndices(possibleNeighbor);
-
- // If the neighbor passes these tests, add it to the set
- // if it is active.
- if(!isRoot && isValid) {
- if(!crystal[possibleNeighbor.x][possibleNeighbor.y].isDisabled()) {
- neighborSet.add(getMirroredPoint(possibleNeighbor, mirrorX, mirrorY));
- }
- }
- }
- }
-
- // Return the neighbor set.
- return neighborSet;
+ centralCrystal.x, centralCrystal.y));
+ }
+
+ // Make a set to store the neighbors in.
+ HashSet<Point> neighborSet = new HashSet<Point>();
+
+ // Check all the crystals in a 3-by-3 square around the root.
+ // If they are valid crystals and they are not disable, then
+ // they are neighbors.
+ for(int xMod = -1; xMod <= 1; xMod++) {
+ for(int yMod = -1; yMod <= 1; yMod++) {
+ // Get the possible neighbor.
+ Point possibleNeighbor = new Point(centralCrystal.x + xMod, centralCrystal.y + yMod);
+
+ // Make sure that the possible neighbor is neither the
+ // root crystal nor invalid.
+ boolean isRoot = centralCrystal.equals(possibleNeighbor);
+ boolean isValid = validateIndices(possibleNeighbor);
+
+ // If the neighbor passes these tests, add it to the set
+ // if it is active.
+ if(!isRoot && isValid) {
+ if(!crystal[possibleNeighbor.x][possibleNeighbor.y].isDisabled()) {
+ neighborSet.add(getMirroredPoint(possibleNeighbor, mirrorX, mirrorY));
+ }
+ }
+ }
+ }
+
+ // Return the neighbor set.
+ return neighborSet;
}
/**
@@ -406,6 +437,16 @@
* If no crystal is currently selected, returns <code>null</code>.
*/
public Point getSelectedCrystal() { return getMirroredPoint(selectedCrystal, mirrorX, mirrorY); }
+
+ /**
+ * Gets the list of <code>SettingsListener</code> objects attached
+ * to the component.
+ * @return Returns the object's <code>SettingsListener</code> objects
+ * in an array.
+ */
+ public SettingsListener[] getSettingsListeners() {
+ return listenerList.toArray(new SettingsListener[listenerList.size()]);
+ }
/**
* Determines if the crystal at the given coordinates is a cluster
@@ -419,11 +460,11 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public boolean isCrystalCluster(int ix, int iy) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
- if(validateIndices(ix, iy)) { return crystal[ix][iy].isClusterCenter(); }
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
+ if(validateIndices(ix, iy)) { return crystal[ix][iy].isClusterCenter(); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -438,7 +479,7 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public boolean isCrystalCluster(Point ixy) throws IndexOutOfBoundsException {
- return isCrystalCluster(ixy.x, ixy.y);
+ return isCrystalCluster(ixy.x, ixy.y);
}
/**
@@ -452,11 +493,11 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public boolean isCrystalDisabled(int ix, int iy) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
- if(validateIndices(ix, iy)) { return crystal[ix][iy].isDisabled(); }
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
+ if(validateIndices(ix, iy)) { return crystal[ix][iy].isDisabled(); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -470,7 +511,7 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public boolean isCrystalDisabled(Point ixy) throws IndexOutOfBoundsException {
- return isCrystalDisabled(ixy.x, ixy.y);
+ return isCrystalDisabled(ixy.x, ixy.y);
}
public boolean isMirroredX() { return mirrorX; }
@@ -500,11 +541,19 @@
public boolean isSelectionEnabled() { return enabledSelection; }
/**
+ * Removes the indicated listener from the object if it exists.
+ * @param listener - The listener to remove.
+ */
+ public void removeSettingsListener(SettingsListener listener) {
+ if(listener != null) { listenerList.remove(listener); }
+ }
+
+ /**
* Sets the color of the cluster center marker.
* @param c - The color to be used for cluster center markers. A
* value of <code>null</code> will result in seed hit markers being
* the inverse color of the crystal in which they appear.
- **/
+ */
public void setClusterColor(Color c) { clusterColor = c; }
/**
@@ -515,12 +564,12 @@
* is a cluster center and <code>false</code> if there is not.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void setCrystalCluster(int ix, int iy, boolean cluster) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
if (validateIndices(ix, iy)) { crystal[ix][iy].setClusterCenter(cluster); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -532,7 +581,7 @@
* is a cluster center and <code>false</code> if there is not.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void setCrystalCluster(Point ixy, boolean cluster) throws IndexOutOfBoundsException {
setCrystalCluster(ixy.x, ixy.y, cluster);
}
@@ -545,12 +594,12 @@
* active and <code>false</code> if it is not.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void setCrystalEnabled(int ix, int iy, boolean active) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
if (validateIndices(ix, iy)) { crystal[ix][iy].setDisabled(!active); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -562,7 +611,7 @@
* active and <code>false</code> if it is not.
* @throws IndexOutOfBoundsException Occurs when either of the given
* x/y crystal coordinates do not correspond to a crystal.
- **/
+ */
public void setCrystalEnabled(Point ixy, boolean active) throws IndexOutOfBoundsException {
setCrystalEnabled(ixy.x, ixy.y, active);
}
@@ -577,10 +626,10 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public void setCrystalHighlight(int ix, int iy, Color highlight) throws IndexOutOfBoundsException {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
if (validateIndices(ix, iy)) { crystal[ix][iy].setHighlight(highlight); }
else { throw new IndexOutOfBoundsException(String.format("Invalid crystal address (%2d, %2d).", ix, iy)); }
}
@@ -604,20 +653,23 @@
* map value.
*/
public void setDefaultCrystalColor(Color c) {
- // Only update the crystals if the default color has changed.
- if(c != defaultColor) {
- // Store the new default color.
- defaultColor = c;
-
- // Inform the crystals of the change.
- for(int ix = 0; ix < xBoxes; ix++) {
- for(int iy = 0; iy < yBoxes; iy++) { crystal[ix][iy].setUseDefaultColor(c != null, false); }
- }
-
- // Reset the colors and repaint.
- resetCrystalColors();
- repaint();
- }
+ // Only update the crystals if the default color has changed.
+ if(c != defaultColor) {
+ // Store the new default color.
+ defaultColor = c;
+
+ // Inform the crystals of the change.
+ for(int ix = 0; ix < xBoxes; ix++) {
+ for(int iy = 0; iy < yBoxes; iy++) { crystal[ix][iy].setUseDefaultColor(c != null, false); }
+ }
+
+ // Reset the colors and repaint.
+ resetCrystalColors();
+ repaint();
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_ZERO_ENERGY_COLOR);
+ }
}
/**
@@ -627,45 +679,45 @@
* @param mirrorY - <code>true</code> indicates that the y-axis
* should be mirrored and <code>false</code> that it should not.
*/
- public void setMirror(boolean mirrorX, boolean mirrorY) {
- // Determine whether a given axis should be flipped.
- boolean flipX = (this.mirrorX != mirrorX);
- boolean flipY = (this.mirrorY != mirrorY);
-
- // If the axes are already as requested, then no further action
- // is necessary.
- if(!(flipX || flipY)) { return; }
-
- // Otherwise, mirror as requested.
- this.mirrorX = mirrorX;
- this.mirrorY = mirrorY;
-
- // Loop over the crystals and move them to the appropriate
- // mirrored array position.
- Crystal[][] mirroredCrystal = new Crystal[xBoxes][yBoxes];
- for(int ix = 0; ix < xBoxes; ix++) {
- for(int iy = 0; iy < yBoxes; iy++) {
- // Mirror the coordinates as appropriate.
- int mix = ix;
- int miy = iy;
- if(flipX) { mix = getMirroredX(ix); }
- if(flipY) { miy = getMirroredY(iy); }
-
- // Place the original crystal in its new position.
- mirroredCrystal[mix][miy] = crystal[ix][iy];
- }
- }
-
- // Change the selected crystal to the new one.
- if(selectedCrystal != null) {
- crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false);
- mirroredCrystal[selectedCrystal.x][selectedCrystal.y].setSelected(true);
- }
-
-
- // Replace the original crystal array with the new one and redraw.
- crystal = mirroredCrystal;
- setSize(getSize());
+ public void setMirror(boolean mirrorX, boolean mirrorY) {
+ // Determine whether a given axis should be flipped.
+ boolean flipX = (this.mirrorX != mirrorX);
+ boolean flipY = (this.mirrorY != mirrorY);
+
+ // If the axes are already as requested, then no further action
+ // is necessary.
+ if(!(flipX || flipY)) { return; }
+
+ // Otherwise, mirror as requested.
+ this.mirrorX = mirrorX;
+ this.mirrorY = mirrorY;
+
+ // Loop over the crystals and move them to the appropriate
+ // mirrored array position.
+ Crystal[][] mirroredCrystal = new Crystal[xBoxes][yBoxes];
+ for(int ix = 0; ix < xBoxes; ix++) {
+ for(int iy = 0; iy < yBoxes; iy++) {
+ // Mirror the coordinates as appropriate.
+ int mix = ix;
+ int miy = iy;
+ if(flipX) { mix = getMirroredX(ix); }
+ if(flipY) { miy = getMirroredY(iy); }
+
+ // Place the original crystal in its new position.
+ mirroredCrystal[mix][miy] = crystal[ix][iy];
+ }
+ }
+
+ // Change the selected crystal to the new one.
+ if(selectedCrystal != null) {
+ crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false);
+ mirroredCrystal[selectedCrystal.x][selectedCrystal.y].setSelected(true);
+ }
+
+
+ // Replace the original crystal array with the new one and redraw.
+ crystal = mirroredCrystal;
+ resize();
}
/**
@@ -673,23 +725,39 @@
* @param state - <code>true</code> indicates that the axis should
* be mirrored and <code>false</code> that it should not.
*/
- public void setMirrorX(boolean mirrorX) { setMirror(mirrorX, mirrorY); }
+ public void setMirrorX(boolean mirrorX) {
+ // Process the change.
+ setMirror(mirrorX, mirrorY);
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_X_ORIENTATION);
+ }
/**
* Sets whether to mirror the y-axis on the calorimeter display.
* @param state - <code>true</code> indicates that the axis should
* be mirrored and <code>false</code> that it should not.
*/
- public void setMirrorY(boolean mirrorY) { setMirror(mirrorX, mirrorY); }
+ public void setMirrorY(boolean mirrorY) {
+ // Process the change.
+ setMirror(mirrorX, mirrorY);
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_Y_ORIENTATION);
+ }
/**
* Sets whether the scale should be visible or not.
* @param enabled - <code>true</code> indicates that the scale should
* be visible and <code>false</code> that it should be hidden.
- **/
+ */
public void setScaleEnabled(boolean enabled) {
if (scalePanel.isVisible() != enabled) {
+ // Process the change.
scalePanel.setVisible(enabled);
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_SCALE_VISIBLE);
}
}
@@ -697,36 +765,60 @@
* Sets the maximum value of the color mapping scale. Energies above this
* value will all be the same maximum color.
* @param maximum - The maximum energy to be mapped.
- **/
+ */
public void setScaleMaximum(double maximum) {
- scale.setMaximum(maximum);
+ if(scale.getMaximum() != maximum) {
+ // Process the change.
+ scale.setMaximum(maximum);
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_SCALE_RANGE);
+ }
}
/**
* Sets the minimum value of the color mapping scale. Energies below this
* value will all be the same minimum color.
* @param minimum - The minimum energy to be mapped.
- **/
+ */
public void setScaleMinimum(double minimum) {
- scale.setMinimum(minimum);
+ if(scale.getMinimum() != minimum) {
+ // Process the change.
+ scale.setMinimum(minimum);
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_SCALE_RANGE);
+ }
}
/**
* Sets the color mapping scale behavior to linear mapping.
- **/
+ */
public void setScalingLinear() {
- scale.setScalingLinear();
- resetCrystalColors();
- repaint();
+ if(!isScalingLinear()) {
+ // Process the change in scaling.
+ scale.setScalingLinear();
+ resetCrystalColors();
+ repaint();
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_SCALE_TYPE);
+ }
}
/**
* Sets the color mapping scale behavior to logarithmic mapping.
- **/
+ */
public void setScalingLogarithmic() {
- scale.setScalingLogarithmic();
- resetCrystalColors();
- repaint();
+ if(!isScalingLogarithmic()) {
+ // Process the change in scaling.
+ scale.setScalingLogarithmic();
+ resetCrystalColors();
+ repaint();
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_SCALE_TYPE);
+ }
}
/**
@@ -737,12 +829,12 @@
* x/y crystal coordinates do not correspond to a crystal.
*/
public void setSelectedCrystal(int ix, int iy) {
- // Mirror the coordinates if appropriate.
- if(mirrorX) { ix = getMirroredX(ix); }
- if(mirrorY) { iy = getMirroredY(iy); }
-
+ // Mirror the coordinates if appropriate.
+ if(mirrorX) { ix = getMirroredX(ix); }
+ if(mirrorY) { iy = getMirroredY(iy); }
+
if (validateIndices(ix, iy)) {
- if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false); }
+ if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].setSelected(false); }
crystal[ix][iy].setSelected(true);
selectedCrystal = new Point(ix, iy);
}
@@ -760,8 +852,8 @@
* </code> is <code>null</code>.
*/
public void setSelectedCrystal(Point ixy) throws NullPointerException {
- if(crystal != null) { setSelectedCrystal(ixy.x, ixy.y); }
- else { throw new NullPointerException("Crystal ID must be defined."); }
+ if(crystal != null) { setSelectedCrystal(ixy.x, ixy.y); }
+ else { throw new NullPointerException("Crystal ID must be defined."); }
}
/**
@@ -771,9 +863,9 @@
* is set to <code>null</code>.
*/
public void setSelectedCrystalHighlight(Color c) throws IllegalArgumentException {
- // We do not allow null values for the selected crystal color.
- if(c == null) { throw new IllegalArgumentException("Crystal selection color can not be null."); }
- else { selectedColor = c; }
+ // We do not allow null values for the selected crystal color.
+ if(c == null) { throw new IllegalArgumentException("Crystal selection color can not be null."); }
+ else { selectedColor = c; }
}
/**
@@ -784,92 +876,15 @@
* it should not.
*/
public void setSelectionHighlighting(boolean state) {
- if(enabledSelection != state) {
- enabledSelection = state;
- if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].repaint(); }
- }
- }
-
- public void setSize(Dimension d) { setSize(d.width, d.height); }
-
- public void setSize(int width, int height) {
- // Run the superclass method.
- super.setSize(width, height);
-
- // Resize the scale panel.
- scalePanel.setLocation(width - scaleWidth, 0);
- scalePanel.setSize(scaleWidth, height);
-
- // Determine the width and heights of the calorimeter crystals.
- if (scalePanel.isVisible()) { width = getWidth() - scaleWidth; }
- else { width = getWidth(); }
-
- int boxWidth = width / xBoxes;
- int widthRem = width % xBoxes;
- int boxHeight = height / yBoxes;
- int heightRem = height % yBoxes;
-
- // Set positioning and sizing variables.
- int[] crystalRem = { widthRem, heightRem };
- int curX = 0;
- int curY = 0;
-
- // Loop over the rows of crystals.
- xPosition[0] = 0;
- for(int x = 0; x < xBoxes; x++) {
- // Get the appropriate width for a crystal.
- int crystalWidth = boxWidth;
- if(crystalRem[0] != 0) {
- crystalWidth++;
- crystalRem[0]--;
- }
-
- // Note the x-coordinate for this column.
- xPosition[x + 1] = xPosition[x] + crystalWidth;
-
- // Loop over the columns of crystals.
- for(int y = 0; y < yBoxes; y++) {
- // Get the appropriate height for a crystal.
- int crystalHeight = boxHeight;
- if(crystalRem[1] != 0) {
- crystalHeight++;
- crystalRem[1]--;
- }
-
- // Note the y-coordinate for this row.
- yPosition[y + 1] = yPosition[y] + crystalHeight;
-
- // Set the crystal size and location.
- crystal[x][y].setSize(crystalWidth, crystalHeight);
- crystal[x][y].setLocation(curX, curY);
-
- // Increment the current y-coordinate.
- curY += crystalHeight;
- }
-
- // Increment the current x-coordinate and reset the current y-coordinate.
- curX += crystalWidth;
- curY = 0;
-
- // Reset the height remainder for the next column.
- crystalRem[1] = heightRem;
- }
-
- // Calculate the cluster position variables.
- double ltw = 0.25 * boxWidth;
- double lth = 0.25 * boxHeight;
-
- if(ltw > lth) {
- clusterSpace[0] = (int)Math.round((boxWidth - lth - lth) / 2.0);
- clusterSpace[1] = (int)Math.round(lth);
- clusterSpace[2] = (int)Math.round(lth + lth);
- }
- else {
- clusterSpace[0] = (int)Math.round(ltw);
- clusterSpace[1] = (int)Math.round((boxHeight - ltw - ltw) / 2.0);
- clusterSpace[2] = (int)Math.round(ltw + ltw);
- }
- }
+ if(enabledSelection != state) {
+ // Process the change.
+ enabledSelection = state;
+ if(selectedCrystal != null) { crystal[selectedCrystal.x][selectedCrystal.y].repaint(); }
+
+ // Throw an event.
+ throwSettingsEvent(SettingsEvent.PROPERTY_HOVER_HIGHLIGHT);
+ }
+ }
/**
* Sets whether the panel crystals should repaint automatically
@@ -894,20 +909,20 @@
* @return Returns the appropriately mirrored point.
*/
private Point getMirroredPoint(Point p, boolean flipX, boolean flipY) {
- // Handle the null case.
- if(p == null) { return null; }
-
- // Flip both x and y.
- if(flipX && flipY) { return new Point(getMirroredX(p.x), getMirroredY(p.y)); }
-
- // Flip only x.
- else if(flipX && !flipY) { return new Point(getMirroredX(p.x), p.y); }
-
- // Flip only y.
- else if(!flipX && flipY) { return new Point(p.x, getMirroredY(p.y)); }
-
- // Don't flip anything.
- else { return p; }
+ // Handle the null case.
+ if(p == null) { return null; }
+
+ // Flip both x and y.
+ if(flipX && flipY) { return new Point(getMirroredX(p.x), getMirroredY(p.y)); }
+
+ // Flip only x.
+ else if(flipX && !flipY) { return new Point(getMirroredX(p.x), p.y); }
+
+ // Flip only y.
+ else if(!flipX && flipY) { return new Point(p.x, getMirroredY(p.y)); }
+
+ // Don't flip anything.
+ else { return p; }
}
/**
@@ -926,10 +941,110 @@
* Forces all crystals to revalidate their colors.
*/
private void resetCrystalColors() {
- // Force all the crystals to update their colors.
- for(int ix = 0; ix < xBoxes; ix++) {
- for(int iy = 0; iy < yBoxes; iy++) { crystal[ix][iy].resetColor(); }
- }
+ // Force all the crystals to update their colors.
+ for(int ix = 0; ix < xBoxes; ix++) {
+ for(int iy = 0; iy < yBoxes; iy++) { crystal[ix][iy].resetColor(); }
+ }
+ }
+
+ /**
+ * Sizes and positions all of the components on the panel.
+ */
+ private void resize() {
+ // Get the width and height.
+ int width = getWidth();
+ int height = getHeight();
+
+ // Resize the scale panel.
+ scalePanel.setLocation(width - scaleWidth, 0);
+ scalePanel.setSize(scaleWidth, height);
+
+ // Determine the width and heights of the calorimeter crystals.
+ if (scalePanel.isVisible()) { width = getWidth() - scaleWidth; }
+ else { width = getWidth(); }
+
+ int boxWidth = width / xBoxes;
+ int widthRem = width % xBoxes;
+ int boxHeight = height / yBoxes;
+ int heightRem = height % yBoxes;
+
+ // Set positioning and sizing variables.
+ int[] crystalRem = { widthRem, heightRem };
+ int curX = 0;
+ int curY = 0;
+
+ // Loop over the rows of crystals.
+ xPosition[0] = 0;
+ for(int x = 0; x < xBoxes; x++) {
+ // Get the appropriate width for a crystal.
+ int crystalWidth = boxWidth;
+ if(crystalRem[0] != 0) {
+ crystalWidth++;
+ crystalRem[0]--;
+ }
+
+ // Note the x-coordinate for this column.
+ xPosition[x + 1] = xPosition[x] + crystalWidth;
+
+ // Loop over the columns of crystals.
+ for(int y = 0; y < yBoxes; y++) {
+ // Get the appropriate height for a crystal.
+ int crystalHeight = boxHeight;
+ if(crystalRem[1] != 0) {
+ crystalHeight++;
+ crystalRem[1]--;
+ }
+
+ // Note the y-coordinate for this row.
+ yPosition[y + 1] = yPosition[y] + crystalHeight;
+
+ // Set the crystal size and location.
+ crystal[x][y].setSize(crystalWidth, crystalHeight);
+ crystal[x][y].setLocation(curX, curY);
+
+ // Increment the current y-coordinate.
+ curY += crystalHeight;
+ }
+
+ // Increment the current x-coordinate and reset the current y-coordinate.
+ curX += crystalWidth;
+ curY = 0;
+
+ // Reset the height remainder for the next column.
+ crystalRem[1] = heightRem;
+ }
+
+ // Calculate the cluster position variables.
+ double ltw = 0.25 * boxWidth;
+ double lth = 0.25 * boxHeight;
+
+ if(ltw > lth) {
+ clusterSpace[0] = (int)Math.round((boxWidth - lth - lth) / 2.0);
+ clusterSpace[1] = (int)Math.round(lth);
+ clusterSpace[2] = (int)Math.round(lth + lth);
+ }
+ else {
+ clusterSpace[0] = (int)Math.round(ltw);
+ clusterSpace[1] = (int)Math.round((boxHeight - ltw - ltw) / 2.0);
+ clusterSpace[2] = (int)Math.round(ltw + ltw);
+ }
+
+ }
+
+ /**
+ * Creates an appropriate <code>SettingsEvent</code> and passes it
+ * to all attached <code>SettingsListener</code> objects.
+ * @param propertyCode - The <code>int</code> primitive representing
+ * the setting that has changed.
+ */
+ private void throwSettingsEvent(int propertyCode) {
+ // Create a settings event.
+ SettingsEvent evt = new SettingsEvent(this, propertyCode);
+
+ // Iterate over each settings listener and throw the event.
+ for(SettingsListener lst : listenerList) {
+ lst.settingChanged(evt);
+ }
}
/**
@@ -941,12 +1056,12 @@
* and <code>false</code> if they are not.
*/
private boolean validateIndices(int ix, int iy) {
- boolean lowX = (ix > -1);
- boolean highX = (ix < xBoxes);
- boolean lowY = (iy > -1);
- boolean highY = (iy < yBoxes);
-
- return (lowX && highX && lowY && highY);
+ boolean lowX = (ix > -1);
+ boolean highX = (ix < xBoxes);
+ boolean lowY = (iy > -1);
+ boolean highY = (iy < yBoxes);
+
+ return (lowX && highX && lowY && highY);
}
/**
@@ -967,293 +1082,295 @@
* Class <code>Crystal</code> holds all pertinent information needed
* to display a calorimeter crystal in the panel. It also handles
* drawing itself.
+ *
* @author Kyle McCarty
*/
private class Crystal extends JPanel {
- private static final long serialVersionUID = -5666423016127997831L;
- // The energy stored in the crystal.
- private double energy = 0.0;
- // Whether the crystal can store energy.
- private boolean disabled = false;
- // Whether the crystal is a cluster center.
- private boolean cluster = false;
- // Whether zero-energy crystals should use color mapping.
- private boolean useDefaultColor = false;
- // Whether the crystal is selected.
- private boolean selected = false;
- // What color the crystal should be highlighted in.
- private Color highlight = null;
- // Store associated crystals.
- private ArrayList<Association> componentList = new ArrayList<Association>();
-
- /**
- * Initializes a new calorimeter crystal panel.
- */
- public Crystal() {
- setOpaque(true);
- resetColor();
- }
-
- /**
- * Adds a new associated crystal to this crystal.
- * @param a - The <code>Association</code> object representing
- * the associated crystal and its highlighting color.
- */
- public void addAssociation(Association a) {
- // Add the association.
- componentList.add(a);
-
- // If this crystal is selected, then activate the new crystal.
- if(selected) { setCrystalHighlight(a.getChildCrystal(), a.getHighlight()); }
- }
-
- /**
- * Increments the crystal's energy by the given amount.
- * @param energy - The energy by which the crystal's stored
- * energy should be increased.
- */
- public void addEnergy(double energy) { setEnergy(this.energy + energy); }
-
- /**
- * Clears all the associated crystal from this crystal.
- */
- public void clearAssociations() {
- // Remove the highlighting from any associated crystals,
- // if this crystal is selected.
- if(selected) {
- for(Association a : componentList) { setCrystalHighlight(a.getChildCrystal(), null); }
- }
-
- // Clear the list.
- componentList.clear();
- }
-
- /**
- * Indicates how much energy is stored in the crystal.
- * @return Returns the crystal's energy as a <code>double</code>.
- */
- public double getEnergy() { return energy; }
-
- /**
- * Indicates whether this crystal is also a cluster center.
- * @return Returns <code>true</code> if the crystal is a cluster
- * center and <code>false</code> if it is not.
- */
- public boolean isClusterCenter() { return cluster; }
-
- /**
- * Indicates whether the crystal is disabled.
- * @return Returns <code>true</code> if the crystal is disabled
- * and <code>false</code> if it not.
- */
- public boolean isDisabled() { return disabled; }
-
- public void paint(Graphics g) {
- // If the crystal's redraw is suppressed, do nothing.
- if(suppress) { return; }
-
- // Run the superclass paint method to draw the background.
- super.paint(g);
-
- // Draw the crystal border.
- g.setColor(Color.BLACK);
- g.drawRect(0, 0, getWidth(), getHeight());
- g.drawRect(1, 1, getWidth() - 2, getHeight() - 2);
-
- // If the crystal is not disabled, we may also add a
- // highlight to the crystal.
- if(!disabled) {
- // Highlighting from a crystal being selected overrides
- // any other form of highlighting.
- if(selected && enabledSelection) {
- g.setColor(selectedColor);
- g.drawRect(2, 2, getWidth() - 4, getHeight() - 4);
- }
- // Otherwise, if the crystal has a highlighting color
- // set, apply that color for the highlight.
- else if(getHighlight() != null) {
- g.setColor(getHighlight());
- g.drawRect(2, 2, getWidth() - 4, getHeight() - 4);
- }
- }
-
- // If the crystal contains a cluster, draw the cluster dot.
- if(cluster) {
- g.setColor(clusterColor);
- g.fillOval(clusterSpace[0], clusterSpace[1], clusterSpace[2], clusterSpace[2]);
- }
- }
-
- /**
- * Sets the crystals color to the appropriate value based on
- * its settings.
- */
- public void resetColor() {
- // If the crystal is disabled, it is always disabledColor.
- if(disabled) { setBackground(disabledColor); }
-
- // If the crystal has zero energy and we are using a default
- // color, then we use that.
- else if(energy == 0.0 && useDefaultColor) { setBackground(defaultColor); }
-
- // Otherwise, we use the color chosen by the scale.
- else { setBackground(scale.getColor(energy)); }
- }
-
- /**
- * Sets whether the highlighting on this crystal's associated
- * crystals should be active or not.
- * @param state - <code>true</code> indicates that the crystal
- * highlighting should be active and <code>false</code> that
- * it should be inactive.
- */
- public void setAssociatedActive(boolean state) {
- // If it has any associated crystals, either activate
- // or deactivate their highlighting, as per the current
- // crystal selection state.
- for(Association a : componentList) {
- if(state) { setCrystalHighlight(a.getChildCrystal(), a.getHighlight()); }
- else { setCrystalHighlight(a.getChildCrystal(), null); }
- }
- }
-
- /**
- * Sets whether or not this crystal is a cluster center.
- * @param state - <code>true</code> indicates that this is a
- * cluster center and <code>false</code> that it is not.
- */
- public void setClusterCenter(boolean state) {
- if(cluster != state) {
- cluster = state;
- repaint();
- }
- }
-
- /**
- * Sets whether or not this crystal can store energy.
- * @param state - <code>true</code> means the crystal can not
- * store energy and <code>false</code> that it can.
- */
- public void setDisabled(boolean state) {
- // If the state has changed, reset the color.
- if(disabled != state) {
- disabled = state;
- resetColor();
- }
- }
-
- /**
- * Sets the crystal's stored energy.
- * @param energy - The energy stored in the crystal.
- */
- public void setEnergy(double energy) {
- if(this.energy != energy) {
- this.energy = energy;
- if(energy > extremum[1]) { extremum[1] = energy; }
- if(energy < extremum[0]) { extremum[0] = energy; }
- resetColor();
- }
- }
-
- /**
- * Sets what color the crystal should be highlighted with.
- * Note that selected crystals will always be highlighted with
- * the selected crystal color, though selecting a crystal does
- * not overwrite its highlight color.
- * @param highlight - The color the crystal should be
- * highlighted in.
- */
- public void setHighlight(Color highlight) {
- if(this.highlight != highlight) {
- this.highlight = highlight;
- repaint();
- }
- }
-
- /**
- * Sets whether or not this crystal should be highlighted as
- * a selected crystal.
- * @param state - <code>true</code> means the crystal will be
- * highlighted using the selected color and <code>false</code>
- * will cause it to use the standard highlighting rules.
- */
- public void setSelected(boolean state) {
- if(selected != state) {
- // Store the crystal's state and redraw it.
- selected = state;
- this.repaint();
-
- // Activate or deactivate the associated crystals.
- setAssociatedActive(state);
- }
- }
-
- /**
- * Sets the crystal's energy, cluster center status, and
- * highlighting color. The crystal will redraw itself if needed.
- * @param energy - The crystal's energy.
- * @param cluster - <code>true</code> indicates that the crystal
- * is a cluster center, and <code>false</code> that is not.
- * @param highlight - What color in which the crystal should be
- * highlighted. <code>null</code> indicates that the crystal
- * should not be highlighted.
- */
- public void setState(double energy, boolean cluster, Color highlight) {
- // Track whether the crystal has changed states.
- boolean changed = false;
-
- // Change the energy if needed.
- if(this.energy != energy) {
- this.energy = energy;
- resetColor();
- }
-
- // Change the cluster state if needed.
- if(this.cluster != cluster) {
- this.cluster = cluster;
- changed = true;
- }
-
- // Change the highlighting if needed.
- if(this.highlight != highlight) {
- this.highlight = highlight;
- changed = true;
- }
-
- // If the state has changed, redraw the crystal.
- if(changed) { repaint(); }
- }
-
- /**
- * Sets whether the crystal should use a default color when it
- * has no energy.
- * @param state - <code>true</code> means the crystal will render
- * using a default color when it has no energy and <code>false
- * </code> that it will use the scale mapping color at all times.
- * @param autoRepaint
- */
- public void setUseDefaultColor(boolean state, boolean autoRepaint) {
- // If the state has changed, reset the color.
- if(state != useDefaultColor) {
- useDefaultColor = state;
- if(autoRepaint) { resetColor(); }
- }
- }
-
- /**
- * Gets the highlight color assigned to this crystal.
- * @return Returns the highlight color as a <code>Color</code>
- * object if it exists. Otherwise, returns <code>null</code>.
- */
- public Color getHighlight() { return highlight; }
+ private static final long serialVersionUID = -5666423016127997831L;
+ // The energy stored in the crystal.
+ private double energy = 0.0;
+ // Whether the crystal can store energy.
+ private boolean disabled = false;
+ // Whether the crystal is a cluster center.
+ private boolean cluster = false;
+ // Whether zero-energy crystals should use color mapping.
+ private boolean useDefaultColor = false;
+ // Whether the crystal is selected.
+ private boolean selected = false;
+ // What color the crystal should be highlighted in.
+ private Color highlight = null;
+ // Store associated crystals.
+ private ArrayList<Association> componentList = new ArrayList<Association>();
+
+ /**
+ * Initializes a new calorimeter crystal panel.
+ */
+ public Crystal() {
+ setOpaque(true);
+ resetColor();
+ }
+
+ /**
+ * Adds a new associated crystal to this crystal.
+ * @param a - The <code>Association</code> object representing
+ * the associated crystal and its highlighting color.
+ */
+ public void addAssociation(Association a) {
+ // Add the association.
+ componentList.add(a);
+
+ // If this crystal is selected, then activate the new crystal.
+ if(selected) { setCrystalHighlight(a.getChildCrystal(), a.getHighlight()); }
+ }
+
+ /**
+ * Increments the crystal's energy by the given amount.
+ * @param energy - The energy by which the crystal's stored
+ * energy should be increased.
+ */
+ public void addEnergy(double energy) { setEnergy(this.energy + energy); }
+
+ /**
+ * Clears all the associated crystal from this crystal.
+ */
+ public void clearAssociations() {
+ // Remove the highlighting from any associated crystals,
+ // if this crystal is selected.
+ if(selected) {
+ for(Association a : componentList) { setCrystalHighlight(a.getChildCrystal(), null); }
+ }
+
+ // Clear the list.
+ componentList.clear();
+ }
+
+ /**
+ * Indicates how much energy is stored in the crystal.
+ * @return Returns the crystal's energy as a <code>double</code>.
+ */
+ public double getEnergy() { return energy; }
+
+ /**
+ * Indicates whether this crystal is also a cluster center.
+ * @return Returns <code>true</code> if the crystal is a cluster
+ * center and <code>false</code> if it is not.
+ */
+ public boolean isClusterCenter() { return cluster; }
+
+ /**
+ * Indicates whether the crystal is disabled.
+ * @return Returns <code>true</code> if the crystal is disabled
+ * and <code>false</code> if it not.
+ */
+ public boolean isDisabled() { return disabled; }
+
+ @Override
+ public void paint(Graphics g) {
+ // If the crystal's redraw is suppressed, do nothing.
+ if(suppress) { return; }
+
+ // Run the superclass paint method to draw the background.
+ super.paint(g);
+
+ // Draw the crystal border.
+ g.setColor(Color.BLACK);
+ g.drawRect(0, 0, getWidth(), getHeight());
+ g.drawRect(1, 1, getWidth() - 2, getHeight() - 2);
+
+ // If the crystal is not disabled, we may also add a
+ // highlight to the crystal.
+ if(!disabled) {
+ // Highlighting from a crystal being selected overrides
+ // any other form of highlighting.
+ if(selected && enabledSelection) {
+ g.setColor(selectedColor);
+ g.drawRect(2, 2, getWidth() - 4, getHeight() - 4);
+ }
+ // Otherwise, if the crystal has a highlighting color
+ // set, apply that color for the highlight.
+ else if(getHighlight() != null) {
+ g.setColor(getHighlight());
+ g.drawRect(2, 2, getWidth() - 4, getHeight() - 4);
+ }
+ }
+
+ // If the crystal contains a cluster, draw the cluster dot.
+ if(cluster) {
+ g.setColor(clusterColor);
+ g.fillOval(clusterSpace[0], clusterSpace[1], clusterSpace[2], clusterSpace[2]);
+ }
+ }
+
+ /**
+ * Sets the crystals color to the appropriate value based on
+ * its settings.
+ */
+ public void resetColor() {
+ // If the crystal is disabled, it is always disabledColor.
+ if(disabled) { setBackground(disabledColor); }
+
+ // If the crystal has zero energy and we are using a default
+ // color, then we use that.
+ else if(energy == 0.0 && useDefaultColor) { setBackground(defaultColor); }
+
+ // Otherwise, we use the color chosen by the scale.
+ else { setBackground(scale.getColor(energy)); }
+ }
+
+ /**
+ * Sets whether the highlighting on this crystal's associated
+ * crystals should be active or not.
+ * @param state - <code>true</code> indicates that the crystal
+ * highlighting should be active and <code>false</code> that
+ * it should be inactive.
+ */
+ public void setAssociatedActive(boolean state) {
+ // If it has any associated crystals, either activate
+ // or deactivate their highlighting, as per the current
+ // crystal selection state.
+ for(Association a : componentList) {
+ if(state) { setCrystalHighlight(a.getChildCrystal(), a.getHighlight()); }
+ else { setCrystalHighlight(a.getChildCrystal(), null); }
+ }
+ }
+
+ /**
+ * Sets whether or not this crystal is a cluster center.
+ * @param state - <code>true</code> indicates that this is a
+ * cluster center and <code>false</code> that it is not.
+ */
+ public void setClusterCenter(boolean state) {
+ if(cluster != state) {
+ cluster = state;
+ repaint();
+ }
+ }
+
+ /**
+ * Sets whether or not this crystal can store energy.
+ * @param state - <code>true</code> means the crystal can not
+ * store energy and <code>false</code> that it can.
+ */
+ public void setDisabled(boolean state) {
+ // If the state has changed, reset the color.
+ if(disabled != state) {
+ disabled = state;
+ resetColor();
+ }
+ }
+
+ /**
+ * Sets the crystal's stored energy.
+ * @param energy - The energy stored in the crystal.
+ */
+ public void setEnergy(double energy) {
+ if(this.energy != energy) {
+ this.energy = energy;
+ if(energy > extremum[1]) { extremum[1] = energy; }
+ if(energy < extremum[0]) { extremum[0] = energy; }
+ resetColor();
+ }
+ }
+
+ /**
+ * Sets what color the crystal should be highlighted with.
+ * Note that selected crystals will always be highlighted with
+ * the selected crystal color, though selecting a crystal does
+ * not overwrite its highlight color.
+ * @param highlight - The color the crystal should be
+ * highlighted in.
+ */
+ public void setHighlight(Color highlight) {
+ if(this.highlight != highlight) {
+ this.highlight = highlight;
+ repaint();
+ }
+ }
+
+ /**
+ * Sets whether or not this crystal should be highlighted as
+ * a selected crystal.
+ * @param state - <code>true</code> means the crystal will be
+ * highlighted using the selected color and <code>false</code>
+ * will cause it to use the standard highlighting rules.
+ */
+ public void setSelected(boolean state) {
+ if(selected != state) {
+ // Store the crystal's state and redraw it.
+ selected = state;
+ this.repaint();
+
+ // Activate or deactivate the associated crystals.
+ setAssociatedActive(state);
+ }
+ }
+
+ /**
+ * Sets the crystal's energy, cluster center status, and
+ * highlighting color. The crystal will redraw itself if needed.
+ * @param energy - The crystal's energy.
+ * @param cluster - <code>true</code> indicates that the crystal
+ * is a cluster center, and <code>false</code> that is not.
+ * @param highlight - What color in which the crystal should be
+ * highlighted. <code>null</code> indicates that the crystal
+ * should not be highlighted.
+ */
+ public void setState(double energy, boolean cluster, Color highlight) {
+ // Track whether the crystal has changed states.
+ boolean changed = false;
+
+ // Change the energy if needed.
+ if(this.energy != energy) {
+ this.energy = energy;
+ resetColor();
+ }
+
+ // Change the cluster state if needed.
+ if(this.cluster != cluster) {
+ this.cluster = cluster;
+ changed = true;
+ }
+
+ // Change the highlighting if needed.
+ if(this.highlight != highlight) {
+ this.highlight = highlight;
+ changed = true;
+ }
+
+ // If the state has changed, redraw the crystal.
+ if(changed) { repaint(); }
+ }
+
+ /**
+ * Sets whether the crystal should use a default color when it
+ * has no energy.
+ * @param state - <code>true</code> means the crystal will render
+ * using a default color when it has no energy and <code>false
+ * </code> that it will use the scale mapping color at all times.
+ * @param autoRepaint
+ */
+ public void setUseDefaultColor(boolean state, boolean autoRepaint) {
+ // If the state has changed, reset the color.
+ if(state != useDefaultColor) {
+ useDefaultColor = state;
+ if(autoRepaint) { resetColor(); }
+ }
+ }
+
+ /**
+ * Gets the highlight color assigned to this crystal.
+ * @return Returns the highlight color as a <code>Color</code>
+ * object if it exists. Otherwise, returns <code>null</code>.
+ */
+ public Color getHighlight() { return highlight; }
}
/**
* The local class <b>ScalePanel</b> renders the scale for the calorimeter
* color map.
- **/
+ */
private class ScalePanel extends JPanel {
- private static final long serialVersionUID = -2644562244208528609L;
+ private static final long serialVersionUID = -2644562244208528609L;
protected void paintComponent(Graphics g) {
// Set the text region width.
@@ -1366,4 +1483,4 @@
}
}
}
-}
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/CrystalFilterPanel.java Tue Nov 4 10:19:31 2014
@@ -253,6 +253,9 @@
// Remove the list of filtered crystals.
removeFilter();
+ // Disable the remove filter button.
+ buttonRemove.setEnabled(false);
+
// Disable all of the filter check boxes.
for(JCheckBox check : checkActive) {
check.setSelected(false);
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/DataFileViewer.java Tue Nov 4 10:19:31 2014
@@ -3,14 +3,17 @@
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+import javax.swing.KeyStroke;
-import org.hps.monitoring.ecal.eventdisplay.io.EventManager;
import org.hps.monitoring.ecal.eventdisplay.util.CrystalDataSet;
import org.hps.monitoring.ecal.eventdisplay.util.EcalWiringManager;
@@ -61,7 +64,7 @@
* @throws IOException Occurs if there is an error reading from
* either data source.
*/
- public DataFileViewer(EventManager dataSource, String crystalDataFilePath) throws IOException {
+ public DataFileViewer(File dataSource, String crystalDataFilePath) throws IOException {
// Initialize the super class file.
super(dataSource);
@@ -69,9 +72,7 @@
ewm = new EcalWiringManager(crystalDataFilePath);
// Add the crystal data fields.
- for(String fieldName : fieldNames) {
- addStatusField(fieldName);
- }
+ for(String fieldName : fieldNames) { addStatusField(fieldName); }
// Instantiate the crystal filter panel.
filterPanel = new CrystalFilterPanel(ewm);
@@ -81,38 +82,42 @@
filterWindow.pack();
filterWindow.setResizable(false);
+ // Add a new view menu option to display the filter panel.
+ JMenuItem menuFilter = new JMenuItem("Show Filter", KeyEvent.VK_F);
+ menuFilter.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, ActionEvent.CTRL_MASK));
+ menuFilter.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { filterWindow.setVisible(true); }
+ });
+ menu[MENU_VIEW].addSeparator();
+ menu[MENU_VIEW].add(menuFilter);
+
// Add an action listener to note when the filter window applies
// a crystal filter.
filterPanel.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // Clear the panel highlighting.
- ecalPanel.clearHighlight();
-
- // If the filter panel is active, highlight the crystals
- // that passed the filter.
- if(filterPanel.isActive()) {
- // Get the list of filtered crystals.
- List<Point> filterList = filterPanel.getFilteredCrystals();
-
- // Highlight each of the filtered crystals.
- for(Point crystal : filterList) {
- ecalPanel.setCrystalHighlight(toPanelPoint(crystal), java.awt.Color.WHITE);
- }
- }
- }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Clear the panel highlighting.
+ ecalPanel.clearHighlight();
+
+ // If the filter panel is active, highlight the crystals
+ // that passed the filter.
+ if(filterPanel.isActive()) {
+ // Get the list of filtered crystals.
+ List<Point> filterList = filterPanel.getFilteredCrystals();
+
+ // Highlight each of the filtered crystals.
+ for(Point crystal : filterList) {
+ ecalPanel.setCrystalHighlight(toPanelPoint(crystal), java.awt.Color.WHITE);
+ }
+ }
+ }
});
- // Create a new key listener.
- addKeyListener(new KeyAdapter() {
- @Override
- public void keyReleased(KeyEvent e) {
- // Bring up the filter panel when 'f' is pressed.
- if(e.getKeyCode() == 70) {
- if(!filterWindow.isVisible()) { filterWindow.setVisible(true); }
- else { filterWindow.setVisible(false); }
- }
- }
+ // Kill the filter window on system close.
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) { filterWindow.dispose(); }
});
}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/FileViewer.java Tue Nov 4 10:19:31 2014
@@ -1,12 +1,23 @@
package org.hps.monitoring.ecal.eventdisplay.ui;
import org.hps.monitoring.ecal.eventdisplay.io.EventManager;
+import org.hps.monitoring.ecal.eventdisplay.io.LCIOManager;
+import org.hps.monitoring.ecal.eventdisplay.io.TextManager;
import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
+
+import javax.swing.JFileChooser;
+import javax.swing.JMenuItem;
+import javax.swing.filechooser.FileNameExtensionFilter;
import org.hps.monitoring.ecal.eventdisplay.event.Association;
import org.hps.monitoring.ecal.eventdisplay.event.Cluster;
@@ -20,12 +31,21 @@
*
* @author Kyle McCarty
*/
-public class FileViewer extends ActiveViewer {
+public class FileViewer extends Viewer {
private static final long serialVersionUID = 17058336873349781L;
+
+ // Gets events from some file.
+ protected EventManager em = null;
+
+ // File chooser for opening new files.
+ private JFileChooser fileChooser;
+
// Map cluster location to a cluster object.
private HashMap<Point, Cluster> clusterMap = new HashMap<Point, Cluster>();
+
// Additional status display field names for this data type.
private static final String[] fieldNames = { "Event Number", "Shared Hits", "Component Hits", "Cluster Energy" };
+
// Indices for the field values.
private static final int EVENT_NUMBER = 0;
private static final int SHARED_HITS = 1;
@@ -33,8 +53,6 @@
private static final int CLUSTER_ENERGY = 3;
/**
- * <b>FileViewer</b><br/><br/>
- * <code>public <b>FileViewer</b>()</code><br/><br/>
* Constructs a new <code>Viewer</code> for displaying data read
* from a file.
* @param dataSource - The <code>EventManager</code> responsible
@@ -42,21 +60,71 @@
* @throws NullPointerException Occurs if the event manager is
* <code>null</code>.
*/
- public FileViewer(EventManager dataSource) throws NullPointerException {
- // Initialize the superclass viewer.
- super(dataSource);
+ public FileViewer(File dataSource) throws NullPointerException {
+ // Initialize the superclass.
+ super();
+
+ // Make a key listener to change events.
+ addKeyListener(new EcalKeyListener());
// Add additional fields.
insertStatusField(0, fieldNames[0]);
for(int index = 1; index < fieldNames.length; index++) {
addStatusField(fieldNames[index]);
}
- }
-
- @Override
+
+ // Initialize the file chooser.
+ fileChooser = new JFileChooser(new File("D:\\cygwin64\\home\\Kyle\\background\\compiled\\output\\"));
+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Text Files", "txt"));
+ fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("LCIO Files", "lcio", "slcio"));
+
+ // Add an open file option to the file menu.
+ JMenuItem menuOpen = new JMenuItem("Open File", KeyEvent.VK_O);
+ menuOpen.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Open the file chooser and note what action was taken.
+ int result = fileChooser.showOpenDialog(FileViewer.this);
+
+ // If a file was selected, load it.
+ if(result == JFileChooser.APPROVE_OPTION) {
+ // Get the selected data file.
+ File dataFile = fileChooser.getSelectedFile();
+
+ // Load the indicated file.
+ openDataSource(dataFile);
+ }
+ }
+ });
+ menu[MENU_FILE].addSeparator();
+ menu[MENU_FILE].add(menuOpen);
+
+ // Add an exit command to the file menu.
+ JMenuItem menuExit = new JMenuItem("Exit", KeyEvent.VK_X);
+ menuExit.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { dispose(); }
+ });
+ menu[MENU_FILE].add(menuExit);
+
+ // Set the calorimeter panel to display a logarithmic scale.
+ setUseLogarithmicScale();
+
+ // Set the data source.
+ if(dataSource != null) { openDataSource(dataSource); }
+ }
+
+ /**
+ * Feeds the calorimeter panel the data from the next event.
+ * @throws IOException Occurs when there is an issue with reading the data file.
+ */
public void displayNextEvent() throws IOException { getEvent(true); }
- @Override
+ /**
+ * Feeds the calorimeter panel the data from the previous event.
+ * @throws IOException Occurs when there is an issue with reading the data file.
+ */
public void displayPreviousEvent() throws IOException { getEvent(false); }
@Override
@@ -98,12 +166,11 @@
else { for(String field : fieldNames) { setStatusField(field, ResizableFieldPanel.NULL_VALUE); } }
// Set the event number.
- setStatusField(fieldNames[EVENT_NUMBER], Integer.toString(em.getEventNumber()));
- }
-
- /**
- * <b>displayEvent</b><br/><br/>
- * <code>private void <b>displayEvent</b>(List<EcalHit> hitList, List<Cluster> clusterList)</code><br/><br/>
+ if(em != null) { setStatusField(fieldNames[EVENT_NUMBER], Integer.toString(em.getEventNumber())); }
+ else { setStatusField(fieldNames[EVENT_NUMBER], ResizableFieldPanel.NULL_VALUE); }
+ }
+
+ /**
* Displays the given lists of hits and clusters on the calorimeter
* panel.
* @param hitList - A list of hits for the current event.
@@ -146,8 +213,6 @@
}
/**
- * <b>getEvent</b><br/><br/>
- * <code>private void <b>getEvent</b>(boolean forward)</code><br/><br/>
* Reads either the next or the previous event from the event manager.
* @param forward - Whether the event data should be read forward
* or backward.
@@ -171,4 +236,85 @@
// Display it.
displayEvent(em.getHits(), em.getClusters());
}
-}
+
+ /**
+ * Loads a data source for viewing, if it is a supported data type.
+ * @param dataFile - The file to load.
+ * @return Returns <code>true</code> if the file was successfully
+ * loaded and <code>false</code> if it was not.
+ */
+ private boolean openDataSource(File dataFile) {
+ // Get the file extension.
+ int point = dataFile.getName().lastIndexOf('.');
+ String extension = "";
+ if(point != -1 && point != dataFile.getName().length()) {
+ extension = dataFile.getName().substring(point + 1);
+ }
+
+ // Open the file with a manager appropriate to it.
+ EventManager manager = null;
+ if(extension.compareToIgnoreCase("lcio") == 0 || extension.compareToIgnoreCase("slcio") == 0) {
+ // Try to open it.
+ try { manager = new LCIOManager(dataFile); }
+ catch(IOException exc) {
+ System.err.println("Error reading data file.");
+ }
+ }
+ else if(extension.compareToIgnoreCase("txt") == 0) {
+ try { manager = new TextManager(dataFile); }
+ catch(IOException exc) {
+ System.err.println("Error reading data file.");
+ }
+ }
+ else { System.err.println("Unrecognized file type."); }
+
+ // If the file was successfully loaded, set it as
+ // the current data manager and display the first
+ // event.
+ if(manager != null) {
+ em = manager;
+ displayEvent(manager.getHits(), manager.getClusters());
+ setTitle("HPS Ecal Event Display - " + dataFile.getName());
+ displayEvent(em.getHits(), em.getClusters());
+ updateStatusPanel();
+ return true;
+ }
+
+ // Otherwise, report that the file could not be opened.
+ setTitle("HPS Ecal Event Display");
+ updateStatusPanel();
+ return false;
+ }
+
+ /**
+ * The <code>EcalListener</code> class binds keys to actions.
+ * Bound actions include:
+ * [Right Arrow] :: Next event
+ * [Left Arrow ] :: Previous event
+ **/
+ private class EcalKeyListener extends KeyAdapter {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ // If right-arrow was pressed, go to the next event.
+ if (e.getKeyCode() == 39) {
+ try { displayNextEvent(); }
+ catch (IOException ex) {
+ System.err.println(ex.getMessage());
+ System.exit(1);
+ }
+ }
+
+ // If left-arrow was pressed, go to the next event.
+ else if (e.getKeyCode() == 37) {
+ try { displayPreviousEvent(); }
+ catch (IOException ex) {
+ System.err.println(ex.getMessage());
+ System.exit(1);
+ }
+ }
+
+ // Otherwise, print out the key code for the pressed key.
+ else { System.out.printf("Key Code: %d%n", e.getKeyCode()); }
+ }
+ }
+}
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/OccupancyViewer.java Tue Nov 4 10:19:31 2014
@@ -16,6 +16,7 @@
*
* @author Kyle McCarty
*/
+@Deprecated
public class OccupancyViewer extends ActiveViewer {
private static final long serialVersionUID = 3712604287904215617L;
// The number of events that have been read so far.
Modified: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java (original)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/ui/Viewer.java Tue Nov 4 10:19:31 2014
@@ -3,21 +3,37 @@
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseMotionAdapter;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
+import javax.imageio.ImageIO;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
+import javax.swing.KeyStroke;
import org.hps.monitoring.ecal.eventdisplay.util.CrystalEvent;
import org.hps.monitoring.ecal.eventdisplay.util.CrystalListener;
+import org.hps.monitoring.ecal.eventdisplay.util.SettingsEvent;
+import org.hps.monitoring.ecal.eventdisplay.util.SettingsListener;
/**
* The abstract class <code>Viewer</code> handles initialization of the
@@ -28,18 +44,54 @@
* @author Kyle McCarty
**/
public abstract class Viewer extends JFrame {
- // Java-suggested variable.
- private static final long serialVersionUID = -2022819652687941812L;
+ // Serialization UID.
+ private static final long serialVersionUID = 2L;
+
// A map of field names to field indices.
private Map<String, Integer> fieldMap = new HashMap<String, Integer>();
+
// A list of crystal listeners attached to the viewer.
private ArrayList<CrystalListener> listenerList = new ArrayList<CrystalListener>();
+
+ // Menus and menu items.
+ private final JMenuItem menuScreenshot;
+ private final JCheckBoxMenuItem menuHighlight;
+ private final JCheckBoxMenuItem menuBackground;
+ private final JCheckBoxMenuItem menuMirrorX;
+ private final JCheckBoxMenuItem menuMirrorY;
+ private final JRadioButtonMenuItem[] menuScaling;
+
// The default field names.
private static final String[] defaultFields = { "x Index", "y Index", "Cell Value" };
+
+ // The default crystal color.
+ private static final Color DEFAULT_CRYSTAL_COLOR = Color.GRAY;
+
// Indices for the field values.
private static final int X_INDEX = 0;
private static final int Y_INDEX = 1;
private static final int CELL_VALUE = 2;
+ private static final int MENU_ITEM_LIN_SCALE = 0;
+ private static final int MENU_ITEM_LOG_SCALE = 1;
+ protected static final int MENU_FILE = 0;
+ protected static final int MENU_VIEW = 1;
+ protected static final int MENU_SCALE = 2;
+
+ /**
+ * The root menu bar displayed by the <code>Viewer</code>.
+ */
+ protected final JMenuBar menuRoot;
+
+ /**
+ * The base menus used displayed by the <code>Viewer</code>.
+ */
+ protected final JMenu[] menu;
+
+ /**
+ * Component that allows for scrolling functionality when there
+ * are more status panel entries then can be displayed at once.
+ */
+ protected final JScrollPane statusScroller;
/**
* The component responsible for displaying status information
@@ -61,6 +113,11 @@
* The default color for highlighting cluster shared hits.
*/
public static final Color HIGHLIGHT_CLUSTER_SHARED = Color.YELLOW;
+
+ /**
+ * The default color for generic crystal highlighting.
+ */
+ public static final Color HIGHLIGHT_GENERIC = Color.WHITE;
/**
* Initializes the viewer window and calorimeter panel.
@@ -70,12 +127,21 @@
* arguments are <code>null</code>.
**/
public Viewer() throws NullPointerException {
+ // ==========================================================
+ // ==== Initialize Base Component Properties ================
+ // ==========================================================
+
// Initialize the underlying JPanel.
super();
// Generate the status panel.
statusPanel = new ResizableFieldPanel(100);
statusPanel.setBackground(Color.WHITE);
+ statusScroller = new JScrollPane(statusPanel);
+ statusScroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ statusScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ statusScroller.getVerticalScrollBar().setBlockIncrement(5);
+ statusScroller.getVerticalScrollBar().setUnitIncrement(5);
// Add the default fields.
for(String field : defaultFields) { addStatusField(field); }
@@ -84,6 +150,7 @@
ecalPanel.setScaleMinimum(0.001);
ecalPanel.setScaleMaximum(3.0);
ecalPanel.setScalingLinear();
+ ecalPanel.addSettingsListener(new PropertyUpdater());
// Disable the crystals in the calorimeter panel along the beam gap.
for (int i = -23; i < 24; i++) {
@@ -100,7 +167,7 @@
// Add the panels.
add(ecalPanel);
- add(statusPanel);
+ add(statusScroller);
// Define viewer panel properties.
setTitle("HPS Ecal Event Display");
@@ -110,7 +177,123 @@
setLayout(null);
// Add a listener to update everything when the window changes size
- addComponentListener(new ResizeListener());
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) { resize(); }
+ });
+
+ // ==========================================================
+ // ==== Initialize Menu Properties ==========================
+ // ==========================================================
+
+ // Create a menu bar to render panel options easily accessible.
+ menuRoot = new JMenuBar();
+
+ // Create the base menu options.
+ int MENU_FILE = 0;
+ int MENU_VIEW = 1;
+ int MENU_SCALE = 2;
+ menu = new JMenu[3];
+
+ // ==== Instantiate the File Menu ===========================
+ // ==========================================================
+
+ // Define the file menu.
+ menu[MENU_FILE] = new JMenu("File");
+ menu[MENU_FILE].setMnemonic(KeyEvent.VK_F);
+
+ // Define the screenshot menu item.
+ menuScreenshot = new JMenuItem("Save Screenshot", KeyEvent.VK_S);
+ menuScreenshot.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
+ menuScreenshot.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { saveScreenshot(); }
+ });
+ menu[MENU_FILE].add(menuScreenshot);
+
+ // ==== Instantiate the View Menu ===========================
+ // ==========================================================
+
+ // Define the view menu.
+ menu[MENU_VIEW] = new JMenu("View");
+ menu[MENU_VIEW].setMnemonic(KeyEvent.VK_V);
+
+ // Define the background toggle menu item.
+ menuBackground = new JCheckBoxMenuItem("Zero-Energy Color Mapping", usesZeroEnergyColorMapping());
+ menuBackground.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK));
+ menuBackground.setMnemonic(KeyEvent.VK_Z);
+ menuBackground.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setUseZeroEnergyColorMapping(menuBackground.isSelected());
+ }
+ });
+ menu[MENU_VIEW].add(menuBackground);
+
+ // Define the toggle highlighting menu item.
+ menuHighlight = new JCheckBoxMenuItem("Highlight Active Crystal", usesCrystalHighlighting());
+ menuHighlight.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
+ menuHighlight.setMnemonic(KeyEvent.VK_H);
+ menuHighlight.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setUseCrystalHighlighting(!usesCrystalHighlighting());
+ }
+ });
+ menu[MENU_VIEW].add(menuHighlight);
+
+ // Define the mirror x-axis menu item.
+ menuMirrorX = new JCheckBoxMenuItem("Mirror x-Axis", isMirroredX());
+ menuMirrorX.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
+ menuMirrorX.setMnemonic(KeyEvent.VK_X);
+ menuMirrorX.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { setMirrorX(!isMirroredX()); }
+ });
+ menu[MENU_VIEW].add(menuMirrorX);
+
+ // Define the mirror y-axis menu item.
+ menuMirrorY = new JCheckBoxMenuItem("Mirror y-Axis", isMirroredY());
+ menuMirrorY.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.ALT_MASK));
+ menuMirrorY.setMnemonic(KeyEvent.VK_Y);
+ menuMirrorY.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { setMirrorY(!isMirroredY()); }
+ });
+ menu[MENU_VIEW].add(menuMirrorY);
+
+ // ==== Instantiate the Scale Menu ==========================
+ // ==========================================================
+
+ // Define the scale menu button.
+ menu[MENU_SCALE] = new JMenu("Scale");
+ menu[MENU_SCALE].setMnemonic(KeyEvent.VK_S);
+
+ // Attach the menu to the panel.
+ setJMenuBar(menuRoot);
+
+ // Define the linear/logarithmic menu items.
+ menuScaling = new JRadioButtonMenuItem[2];
+ menuScaling[MENU_ITEM_LIN_SCALE] = new JRadioButtonMenuItem("Linear Scale", usesLinearScale());
+ menuScaling[MENU_ITEM_LOG_SCALE] = new JRadioButtonMenuItem("Logarithmic Scale", usesLogarithmicScale());
+ menuScaling[MENU_ITEM_LIN_SCALE].setMnemonic(KeyEvent.VK_I);
+ menuScaling[MENU_ITEM_LOG_SCALE].setMnemonic(KeyEvent.VK_O);
+ menuScaling[MENU_ITEM_LIN_SCALE].addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { scaleChange(MENU_ITEM_LIN_SCALE); }
+ });
+ menuScaling[MENU_ITEM_LOG_SCALE].addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) { scaleChange(MENU_ITEM_LOG_SCALE); }
+ });
+ menu[MENU_SCALE].add(menuScaling[MENU_ITEM_LIN_SCALE]);
+ menu[MENU_SCALE].add(menuScaling[MENU_ITEM_LOG_SCALE]);
+
+ // ==== Add the Menus to the Root ===========================
+ // ==========================================================
+
+ // Add the menu items to the root.
+ for(JMenuItem menuItem : menu) { menuRoot.add(menuItem); }
}
/**
@@ -120,30 +303,152 @@
* no exception is thrown and no action is performed.
* @param cl - The listener to add.
*/
- public void addCrystalListener(CrystalListener cl) {
+ public final void addCrystalListener(CrystalListener cl) {
if(cl != null) { listenerList.add(cl); }
}
/**
- * Adds a new field to the status panel.
- * @param fieldName - The name to display for the field and that
- * links to the field when calling <code>setStatusField</code>.
- */
- protected void addStatusField(String fieldName) {
- fieldMap.put(fieldName, statusPanel.getFieldCount());
- statusPanel.addField(fieldName);
- }
-
- /**
- * Inserts the field at the indicated location on the status panel.
- * @param index - The index at which to insert the field.
- * @param fieldName - The name to display for the field and that
- * links to the field when calling <code>setStatusField</code>.
- */
- protected void insertStatusField(int index, String fieldName) {
- statusPanel.insertField(index, fieldName);
- fieldMap = statusPanel.getFieldNameIndexMap();
- }
+ * Gets all of the crystal listeners attached to this object.
+ * @return Returns the crystal listeners as an array of <code>
+ * CrystalListener</code> objects.
+ */
+ public final CrystalListener[] getCrystalListeners() {
+ return listenerList.toArray(new CrystalListener[listenerList.size()]);
+ }
+
+ /**
+ * Indicates whether the menu bar is visible or not.
+ * @return Returns <code>true</code> if the menu bar is visible
+ * and <code>false</code> otherwise.
+ */
+ public boolean isMenuVisible() {
+ return menuRoot.isVisible();
+ }
+
+ /**
+ * Indicates whether the calorimeter panel displays the x-axis
+ * in mirrored orientation or not. Mirrored orientation displays
+ * positive LCSim coordinates on the left-hand side and negative
+ * coordinates on the right-hand side. Regular orientation goes
+ * from negative coordinates on the left-hand side to positive
+ * coordinates on the right-hand side.
+ * @return Returns <code>true</code> if the panel is using mirrored
+ * coordinates and <code>false</code> if the panel is using regular
+ * coordinates.
+ */
+ public boolean isMirroredX() {
+ return ecalPanel.isMirroredX();
+ }
+
+ /**
+ * Indicates whether the calorimeter panel displays the y-axis
+ * in mirrored orientation or not. Mirrored orientation displays
+ * positive LCSim coordinates on the bottom side and negative
+ * coordinates on the top side. Regular orientation goes from
+ * negative coordinates on the bottom side to positive coordinates
+ * on the top side.
+ * @return Returns <code>true</code> if the panel is using mirrored
+ * coordinates and <code>false</code> if the panel is using regular
+ * coordinates.
+ */
+ public boolean isMirroredY() {
+ return ecalPanel.isMirroredY();
+ }
+
+ /**
+ * Removes the specified crystal listener so that it no longer
+ * receives crystal events from this component. This method performs
+ * no function, nor does it throw an exception, if the listener
+ * specified by the argument was not previously added to this
+ * component. If listener <code>cl</code> is <code>null</code>, no
+ * exception is thrown and no action is performed.
+ * @param cl - The listener to remove.
+ */
+ public final void removeCrystalListener(CrystalListener cl) {
+ if(cl != null) { listenerList.remove(cl); }
+ }
+
+ /**
+ * Sets the menu bar to be either visible or hidden.
+ * @param isVisible - <code>true</code> indicates that the menu is
+ * visible and <code>false</code> that it is not.
+ */
+ public final void setMenuVisible(boolean isVisible) {
+ menuRoot.setVisible(isVisible);
+ }
+
+ /**
+ * Sets whether to mirror the x-axis on the calorimeter display.
+ * @param state - <code>true</code> indicates that the axis should
+ * be mirrored and <code>false</code> that it should not.
+ */
+ public void setMirrorX(boolean state) {
+ ecalPanel.setMirrorX(state);
+ updateStatusPanel();
+ }
+
+ /**
+ * Sets whether to mirror the y-axis on the calorimeter display.
+ * @param state - <code>true</code> indicates that the axis should
+ * be mirrored and <code>false</code> that it should not.
+ */
+ public void setMirrorY(boolean state) {
+ ecalPanel.setMirrorY(state);
+ updateStatusPanel();
+ }
+
+ /**
+ * Sets the value of the indicated status field on the calorimeter
+ * display.
+ * @param fieldName - The name of the field to set.
+ * @param value - The value to display in relation to the field.
+ * @throws NoSuchElementException Occurs if an invalid field name
+ * is provided for argument <code>fieldName</code>.
+ */
+ public final void setStatusField(String fieldName, String value) throws NoSuchElementException {
+ // Get the index for the indicated field.
+ Integer index = fieldMap.get(fieldName);
+
+ // If it is null, the field does not exist.
+ if(index == null) { throw new NoSuchElementException("Field \"" + fieldName + "\" does not exist."); }
+
+ // Otherwise, set the field.
+ else { statusPanel.setFieldValue(index, value); }
+ }
+
+ /**
+ * Sets whether the calorimeter panel will highlight any crystals
+ * that the mouse cursor passes over.
+ * @param state - <code>true</code> indicates that crystals will
+ * be highlighted and <code>false</code> that they will not.
+ */
+ public void setUseCrystalHighlighting(boolean state) {
+ ecalPanel.setSelectionHighlighting(state);
+ }
+
+ /**
+ * Sets whether zero-energy crystals should be rendered as grey or
+ * whether they should use the minimum-energy color from the color
+ * scale.
+ * @param state - <code>false</code> indicates that zero-energy
+ * crystals will be rendered in grey and <code>true</code> that
+ * they will be rendered as per the color scale.
+ */
+ public void setUseZeroEnergyColorMapping(boolean state) {
+ if(state) { ecalPanel.setDefaultCrystalColor(null); }
+ else { ecalPanel.setDefaultCrystalColor(DEFAULT_CRYSTAL_COLOR); }
+ }
+
+ /**
+ * Sets the calorimeter panel to be displayed using a linear scale.
+ */
+ public void setUseLinearScale() { ecalPanel.setScalingLinear(); }
+
+ /**
+ * Sets the calorimeter panel to be displayed using a logarithmic
+ * scale.
+ */
+ public void setUseLogarithmicScale() { ecalPanel.setScalingLogarithmic(); }
/**
* Converts the calorimeter panel's coordinate pair to the LCSim
@@ -220,58 +525,63 @@
public static final int toPanelY(int ecalY) { return 5 - ecalY; }
/**
- * Sets whether to mirror the x-axis on the calorimeter display.
- * @param state - <code>true</code> indicates that the axis should
- * be mirrored and <code>false</code> that it should not.
- */
- public void setMirrorX(boolean state) { ecalPanel.setMirrorX(state); }
-
- /**
- * Sets whether to mirror the y-axis on the calorimeter display.
- * @param state - <code>true</code> indicates that the axis should
- * be mirrored and <code>false</code> that it should not.
- */
- public void setMirrorY(boolean state) { ecalPanel.setMirrorY(state); }
-
- /**
- * Removes the specified crystal listener so that it no longer
- * receives crystal events from this component. This method performs
- * no function, nor does it throw an exception, if the listener
- * specified by the argument was not previously added to this
- * component. If listener <code>cl</code> is <code>null</code>, no
- * exception is thrown and no action is performed.
- * @param cl - The listener to remove.
- */
- public void removeCrystalListener(CrystalListener cl) {
- if(cl != null) { listenerList.remove(cl); }
- }
-
- public void setSize(int width, int height) {
- super.setSize(width, height);
- resize();
- }
-
- public void setSize(Dimension d) {
- setSize(d.width, d.height);
- }
-
- /**
- * Sets the value of the indicated status field on the calorimeter
- * display.
- * @param fieldName - The name of the field to set.
- * @param value - The value to display in relation to the field.
- * @throws NoSuchElementException Occurs if an invalid field name
- * is provided for argument <code>fieldName</code>.
- */
- public final void setStatusField(String fieldName, String value) throws NoSuchElementException {
- // Get the index for the indicated field.
- Integer index = fieldMap.get(fieldName);
-
- // If it is null, the field does not exist.
- if(index == null) { throw new NoSuchElementException("Field \"" + fieldName + "\" does not exist."); }
-
- // Otherwise, set the field.
- else { statusPanel.setFieldValue(index, value); }
+ * Indicates whether crystal will be highlighted when the cursor
+ * passes over them or not.
+ * @return Returns <code>true</code> if crystals will be highlighted
+ * and <code>false</code> if they will not.
+ */
+ public boolean usesCrystalHighlighting() {
+ return ecalPanel.isSelectionEnabled();
+ }
+
+ /**
+ * Indicates whether zero-energy crystals are colored using the
+ * standard color scale or rendered in grey.
+ * @return Returns <code>false</code> if zero-energy crystal will
+ * be rendered in grey and <code>true</code> if they will use the
+ * regular color scale.
+ */
+ public boolean usesZeroEnergyColorMapping() {
+ return (ecalPanel.getDefaultCrystalColor() == null);
+ }
+
+ /**
+ * Indicates whether the panel is scaled linearly.
+ * @return Returns <code>true</code> if the scaling is linear and
+ * <code>false</code> if the scaling is logarithmic.
+ */
+ public boolean usesLinearScale() {
+ return ecalPanel.isScalingLinear();
+ }
+
+ /**
+ * Indicates whether the panel is scaled logarithmically.
+ * @return Returns <code>true</code> if the scaling is logarithmic
+ * and <code>false</code> if the scaling is linear.
+ */
+ public boolean usesLogarithmicScale() {
+ return ecalPanel.isScalingLogarithmic();
+ }
+
+ /**
+ * Adds a new field to the status panel.
+ * @param fieldName - The name to display for the field and that
+ * links to the field when calling <code>setStatusField</code>.
+ */
+ protected final void addStatusField(String fieldName) {
+ fieldMap.put(fieldName, statusPanel.getFieldCount());
+ statusPanel.addField(fieldName);
+ }
+
+ /**
+ * Inserts the field at the indicated location on the status panel.
+ * @param index - The index at which to insert the field.
+ * @param fieldName - The name to display for the field and that
+ * links to the field when calling <code>setStatusField</code>.
+ */
+ protected final void insertStatusField(int index, String fieldName) {
+ statusPanel.insertField(index, fieldName);
+ fieldMap = statusPanel.getFieldNameIndexMap();
}
/**
@@ -299,7 +609,7 @@
/**
* Handles proper resizing of the window and its components.
- **/
+ */
private void resize() {
// Define the size constants.
int statusHeight = 125;
@@ -309,8 +619,69 @@
ecalPanel.setSize(getContentPane().getWidth(), getContentPane().getHeight() - statusHeight);
// Size and position the status panel.
- statusPanel.setLocation(0, ecalPanel.getHeight());
- statusPanel.setSize(getContentPane().getWidth(), statusHeight);
+ statusScroller.setLocation(0, ecalPanel.getHeight());
+ statusScroller.setSize(getContentPane().getWidth(), statusHeight);
+ statusPanel.setSize(statusScroller.getViewport().getSize());
+ }
+
+ /**
+ * Saves a screenshot to the application root directory.
+ */
+ private void saveScreenshot() {
+ // Make a new buffered image on which to draw the content pane.
+ BufferedImage screenshot = new BufferedImage(getContentPane().getWidth(),
+ getContentPane().getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+ // Paint the content pane to image.
+ getContentPane().paint(screenshot.getGraphics());
+
+ // Get the lowest available file name.
+ int fileNum = 0;
+ File imageFile = new File("screenshot_" + fileNum + ".png");
+ while(imageFile.exists()) {
+ fileNum++;
+ imageFile = new File("screenshot_" + fileNum + ".png");
+ }
+
+ // Save the image to a PNG file.
+ try { ImageIO.write(screenshot, "PNG", imageFile); }
+ catch(IOException ioe) {
+ System.err.println("Error saving file \"screenshot.png\".");
+ }
+ System.out.println("Screenshot saved to: " + imageFile.getAbsolutePath());
+ }
+
+ /**
+ * Handles events generated by the scaling options radio buttons
+ * in the scaling menu.
+ * @param activatingIndex - The index of the radio button that
+ * triggered the event.
+ */
+ private void scaleChange(int activatingIndex) {
+ // If neither radio box is selected, then whichever caused the
+ // activation event was unselected. It should be selected again
+ // and the event ignored.
+ if(!menuScaling[MENU_ITEM_LIN_SCALE].isSelected() && !menuScaling[MENU_ITEM_LOG_SCALE].isSelected()) {
+ menuScaling[activatingIndex].setSelected(true);
+ }
+
+ // Otherwise, whichever did not activate the event should be
+ // unselected and the scaling changed accordingly.
+ else {
+ // If linear scaling activated the event...
+ if(activatingIndex == MENU_ITEM_LIN_SCALE) {
+ menuScaling[MENU_ITEM_LIN_SCALE].setSelected(true);
+ menuScaling[MENU_ITEM_LOG_SCALE].setSelected(false);
+ setUseLinearScale();
+ }
+
+ // If logarithmic scaling activated the event...
+ else {
+ menuScaling[MENU_ITEM_LIN_SCALE].setSelected(false);
+ menuScaling[MENU_ITEM_LOG_SCALE].setSelected(true);
+ setUseLogarithmicScale();
+ }
+ }
}
/**
@@ -318,7 +689,8 @@
* and crystal field information when the cursor leaves the window.
* It also triggers crystal click events.
*/
- private class EcalMouseListener implements MouseListener {
+ private class EcalMouseListener extends MouseAdapter {
+ @Override
public void mouseClicked(MouseEvent e) {
// If there is a selected crystal, trigger a crystal click event.
if(ecalPanel.getSelectedCrystal() != null) {
@@ -333,16 +705,11 @@
}
}
- public void mouseEntered(MouseEvent e) { }
-
+ @Override
public void mouseExited(MouseEvent e) {
ecalPanel.clearSelectedCrystal();
statusPanel.clearFields();
}
-
- public void mousePressed(MouseEvent e) { }
-
- public void mouseReleased(MouseEvent e) { }
}
/**
@@ -351,9 +718,8 @@
* mouse moves over the window. Additionally triggers crystal
* activation and deactivation events.
*/
- private class EcalMouseMotionListener implements MouseMotionListener {
- public void mouseDragged(MouseEvent arg0) { }
-
+ private class EcalMouseMotionListener extends MouseMotionAdapter {
+ @Override
public void mouseMoved(MouseEvent e) {
// Get the panel coordinates.
int x = e.getX();
@@ -428,16 +794,39 @@
}
/**
- * The <code>ResizeListener</code> class ensures that the components remain
- * at the correct size and location when the window is resized.
- **/
- private class ResizeListener implements ComponentListener {
- public void componentResized(ComponentEvent e) { resize(); }
-
- public void componentHidden(ComponentEvent e) { }
-
- public void componentMoved(ComponentEvent e) { }
-
- public void componentShown(ComponentEvent e) { }
- }
-}
+ * Updates the settings panel whenever a tracked property in the
+ * calorimeter panel is updated.
+ *
+ * @author Kyle McCarty
+ */
+ private class PropertyUpdater implements SettingsListener {
+ @Override
+ public void settingChanged(SettingsEvent e) {
+ // If the highlighting behavior has changed...
+ if(e.getID() == SettingsEvent.PROPERTY_HOVER_HIGHLIGHT) {
+ menuHighlight.setSelected(ecalPanel.isSelectionEnabled());
+ }
+
+ // If the scaling type has changed...
+ else if(e.getID() == SettingsEvent.PROPERTY_SCALE_TYPE) {
+ menuScaling[MENU_ITEM_LIN_SCALE].setSelected(ecalPanel.isScalingLinear());
+ menuScaling[MENU_ITEM_LOG_SCALE].setSelected(ecalPanel.isScalingLogarithmic());
+ }
+
+ // If the x-axis orientation has changed...
+ else if(e.getID() == SettingsEvent.PROPERTY_X_ORIENTATION) {
+ menuMirrorX.setSelected(ecalPanel.isMirroredX());
+ }
+
+ // If the y-axis orientation has changed...
+ else if(e.getID() == SettingsEvent.PROPERTY_Y_ORIENTATION) {
+ menuMirrorY.setSelected(ecalPanel.isMirroredY());
+ }
+
+ // If the zero-energy color mapping has changed...
+ else if(e.getID() == SettingsEvent.PROPERTY_ZERO_ENERGY_COLOR) {
+ menuBackground.setSelected(ecalPanel.getDefaultCrystalColor() == null);
+ }
+ }
+ }
+}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsEvent.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsEvent.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsEvent.java Tue Nov 4 10:19:31 2014
@@ -0,0 +1,74 @@
+package org.hps.monitoring.ecal.eventdisplay.util;
+
+import java.awt.AWTEvent;
+
+import org.hps.monitoring.ecal.eventdisplay.ui.CalorimeterPanel;
+
+/**
+ * Class <code>SettingsEvent</code> represents a change that has occurred
+ * to some setting in a <code>CalorimeterPanel</code> object. It stores
+ * both the triggering object and an <code>int</code> primitive which
+ * corresponds to the particular setting that triggered the event.
+ *
+ * @author Kyle McCarty
+ * @see CalorimeterPanel
+ */
+public class SettingsEvent extends AWTEvent {
+ // Local variables.
+ private static final long serialVersionUID = 1L;
+
+ // Event IDs.
+ /**
+ * Indicates that the panel has changed its scaling to either
+ * linear or logarithmic.
+ */
+ public static final int PROPERTY_SCALE_TYPE = AWTEvent.RESERVED_ID_MAX + 1;
+
+ /**
+ * Indicates that the panel's x-axis orientation has changed.
+ */
+ public static final int PROPERTY_X_ORIENTATION = AWTEvent.RESERVED_ID_MAX + 2;
+
+ /**
+ * Indicates that the panel's y-axis orientation has changed.
+ */
+ public static final int PROPERTY_Y_ORIENTATION = AWTEvent.RESERVED_ID_MAX + 3;
+
+ /**
+ * Indicates that the panel's behavior for highlighting crystals
+ * that are under the cursor has changed.
+ */
+ public static final int PROPERTY_HOVER_HIGHLIGHT = AWTEvent.RESERVED_ID_MAX + 4;
+
+ /**
+ * Indicates that the panel's behavior for coloring zero-energy
+ * crystals has changed.
+ */
+ public static final int PROPERTY_ZERO_ENERGY_COLOR = AWTEvent.RESERVED_ID_MAX + 5;
+
+ /**
+ * Indicates that a change has occurred to the panel's scale minimum
+ * or maximum value.
+ */
+ public static final int PROPERTY_SCALE_RANGE = AWTEvent.RESERVED_ID_MAX + 6;
+
+ /**
+ * Indicates that the panel's energy-to-color map has changed.
+ */
+ public static final int PROPERTY_SCALE_COLOR_MAP = AWTEvent.RESERVED_ID_MAX + 7;
+
+ /**
+ * Indicates that the panel's scale has changed visibility.
+ */
+ public static final int PROPERTY_SCALE_VISIBLE = AWTEvent.RESERVED_ID_MAX + 8;
+
+ /**
+ * Instantiates a new <code>SettingsEvent</code> object.
+ * @param source - The calorimeter panel that triggered the event.
+ * @param propertyID - The ID corresponding to the property that
+ * has changed value.
+ */
+ public SettingsEvent(CalorimeterPanel source, int propertyID) {
+ super(source, propertyID);
+ }
+}
Added: java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsListener.java
=============================================================================
--- java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsListener.java (added)
+++ java/trunk/ecal-event-display/src/main/java/org/hps/monitoring/ecal/eventdisplay/util/SettingsListener.java Tue Nov 4 10:19:31 2014
@@ -0,0 +1,17 @@
+package org.hps.monitoring.ecal.eventdisplay.util;
+
+import java.util.EventListener;
+
+/**
+ * Interface <code>SettingsListener</code> tracks changes that occur
+ * in the settings of a <code>CalorimeterPanel</code> object.
+ *
+ * @author Kyle McCarty
+ */
+public interface SettingsListener extends EventListener {
+ /**
+ * Indicates that a setting has changed.
+ * @param e - An event representing the change.
+ */
+ public void settingChanged(SettingsEvent e);
+}
|