//===================================================================== // File: FragmentMap.java // Class: FragmentMap // Package: AFLPgui // // Author: James J. Benham // Date: December 5, 2000 // Contact: james_benham@hmc.edu // // Genographer v1.4 - Computer assisted scoring of gels. // Copyright (C) 1998 Montana State University // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; version 2 // of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // The GNU General Public License is distributed in the file GPL //===================================================================== package AFLPgui; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Label; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.Panel; import java.awt.PrintJob; import java.awt.ScrollPane; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import AFLPcore.Bin; import AFLPcore.BinOperation; import AFLPcore.Cutoff; import AFLPcore.CutoffFunction; import AFLPcore.DataList; import AFLPcore.FeatureList; import AFLPcore.ImportFilter; import AFLPcore.Gel; import AFLPcore.GelOperation; import AFLPcore.Lane; import AFLPcore.LaneOperation; import AFLPcore.Manager; import AFLPcore.Option; import AFLPcore.ProgOptions; /** * This is the main GenoGrapher program window. It displays all of the * data and manages the classes. It takes care of all of the menu items * and switches between different data view. It can display the data as * a standard gel image, as a set of thumbnails for the current bin, * a graph of the bin, a trace, or as text analysis. These view are * actually created in seperate classes. Each of these views has it's own * button bar and info bar, but this class picks which one to display. * *
It also handles the printing of the views as well as saving, opening,
* importing, and exporting files. Most of the views do a lot of work in
* their respective classes, but this one manages them all.
*
* @author James J. Benham
* @version 1.6.0
* @date September 3, 2001
*/
public class FragmentMap extends Frame implements ActionListener,
WindowListener
{
private static final String HELP_FILE = "help.html";
private final String ICON = "geno.gif";
public static final int GEL = 0;
public static final int THUMBNAIL = 1;
public static final int GRAPH = 2;
public static final int TRACE = 3;
public static final int ANALYSIS = 4;
// Constants for the printer
private static final int PAGE_H_ADJUST = 36;
private static final int PAGE_V_ADJUST = 33;
private static final int PAGE_HEADER_SPACE = 20;
protected static int BAR_HEIGHT = 22;
// Menu Items
protected MenuItem newItem;
protected MenuItem openItem;
protected MenuItem saveItem;
protected MenuItem saveAsItem;
protected MenuItem importItem;
protected MenuItem exportItem;
protected MenuItem printItem;
protected MenuItem exitItem;
protected MenuItem laneDeleteItem;
protected MenuItem laneOpItem[];
protected MenuItem binRedrawItem;
protected MenuItem binOpItem[];
protected MenuItem gelRedrawItem;
protected MenuItem gelOpItem[];
protected MenuItem viewGelItem;
protected MenuItem viewThumbnailItem;
protected MenuItem viewGraphItem;
protected MenuItem viewTraceItem;
protected MenuItem viewAnalysisItem;
protected MenuItem helpItem;
protected MenuItem aboutItem;
// Buttons on button bar
protected Button newButton;
protected Button openButton;
protected Button saveButton;
protected Button printButton;
// Program variables
protected Gel gel;
protected GelView gelView;
protected Thumbnail thumbnail;
protected GraphView graph;
protected TraceView trace;
protected AnalysisView analysis;
protected ScrollPane mainPanel;
protected ButtonBar buttonBar;
protected Bar infoBar;
protected Bar statusBar;
protected Panel bottomP;
protected Label statusLabel;
protected double defaultCutoff;
protected int currentView; // the type of thing currently displayed.
protected Bin currentBin; // The bin that is selected or viewed
// Dialogs
protected MultiFileDialog importDialog;
protected FileDialog fileDialog;
protected ErrorDialog errorDialog;
// File management variables
protected String currentFile;
protected String currentDir;
protected boolean modified;
/**
* Create a new FragmentMap. This is the main program window.
*/
public FragmentMap()
{
this(null);
}
/**
* Create a new FragmentMap. This is the main program window.
*
* @param command line parameters. The only value accepted is
* the path for the program files. It should be
* the same as the startup directory.
*/
public FragmentMap(String argv[])
{
setTitle("GenoGrapher");
gel = new Gel();
setLayout(new BorderLayout(0, 0));
setBackground(Color.white);
setSize(638, 440);
setIconImage(getToolkit().getImage(ICON));
File homePath;
boolean goodValue = false;;
if((argv != null) && (argv.length >= 1))
{
homePath = new File(argv[0]);
goodValue = homePath.exists();
if(!goodValue) {
System.err.println("Bad command line parameter for home path.");
} else {
// Added by B. Master 10/25/2000
ProgOptions.homePath = homePath.getAbsolutePath();
System.out.println("Genographer path set to: "
+ ProgOptions.homePath);
}
}
// Path wasn't an argument, so try looking at the current directory.
// Also, path could have been bad.
if(!goodValue)
{
// Set some of the options.
homePath = new File(".");
String tempSt = homePath.getAbsolutePath();
if(tempSt.endsWith("."))
tempSt = tempSt.substring(0, tempSt.length() - 1);
ProgOptions.homePath = tempSt;
}
// Make sure we have a trailing path seperator
if(! ProgOptions.homePath.endsWith(File.separator))
ProgOptions.homePath += File.separator;
ProgOptions.readOptions();
// Create Components
gelView = new GelView(gel, this);
thumbnail = new Thumbnail(gel.getLanes(), gel.getBins(), this);
graph = new GraphView(gel.getLanes(), gel.getBins(), this);
trace = new TraceView(this);
analysis = new AnalysisView(this);
buttonBar = gelView.getButtonBar();
infoBar = gelView.getInfoBar();
statusBar = new Bar();
defaultCutoff = 0;
// Make a panel for the bottom.
bottomP = new Panel();
programInitialize();
currentBin = null;
switchTo("Gel");
// Create the file import dialog
importDialog = new MultiFileDialog(this, "Import");
fileDialog = new FileDialog(this);
errorDialog = new ErrorDialog(this);
// create the help file.
try{
FeatureList.generateFileList();
} catch(IOException e) {
errorDialog.showError(e);
}
currentFile = null;
addWindowListener(this);
}
/**
* Change the program display so that it displays the type specified.
* Possible values are: "Gel" "Thumbnail" "Graph" "Trace" and "Analysis".
* This will handle switching the button bars as well as the main window.
*
* @param value the view to switch the display to.
*/
public void switchTo(String value)
{
// Retrieve the currently selected bin before we switch
switch(currentView)
{
case GEL:
currentBin = gelView.getCurrentBin();
break;
case THUMBNAIL:
currentBin = thumbnail.getBin();
break;
case GRAPH:
currentBin = graph.getBin();
break;
}
if(value.equals("Gel"))
showGelImage();
else if(value.equals("Thumbnail"))
showThumbnail();
else if(value.equals("Graph"))
showGraph();
else if(value.equals("Trace"))
showTrace();
else if(value.equals("Analysis"))
showAnalysis();
// get the buttons on the button bar that we need to handle
// button bar is set appropriately by the above
newButton = buttonBar.getNewButton();
openButton = buttonBar.getOpenButton();
saveButton = buttonBar.getSaveButton();
printButton = buttonBar.getPrintButton();
}
/**
* Display the gel image. This method will set the main display as
* well as the button bar and info bar to the correct objects.
*/
private void showGelImage()
{
currentView = GEL;
gelView.setCurrentBin(currentBin);
mainPanel.removeAll();
mainPanel.add(gelView);
remove(buttonBar);
buttonBar = gelView.getButtonBar();
add(buttonBar, "North");
bottomP.remove(infoBar);
infoBar = gelView.getInfoBar();
bottomP.add(infoBar, "North");
gelView.syncDisplay();
validate();
}
/**
* Displays the thumbnails for the currently selected bin. It also
* sets the bars to the appropriate values and initializes the
* thumbnail class by giveing it either the selected lanes, or if there
* are no selected lanes, all of the lanes. It also sets the range
* to match that of the current bin and tells the thumbnail which bin
* to use.
*/
private void showThumbnail()
{
currentView = THUMBNAIL;
// set the bin
thumbnail.setBin(currentBin);
// and a list of all the bins so it can switch if neccessary
thumbnail.setBinList(gel.getBins());
if(gel.getSelectedLanes().isEmpty())
thumbnail.setLanes(gel.getLanes());
else
thumbnail.setLanes(gel.getSelectedLanes());
thumbnail.init();
mainPanel.removeAll();
mainPanel.add(thumbnail);
remove(buttonBar);
buttonBar = thumbnail.getButtonBar();
add(buttonBar, "North");
bottomP.remove(infoBar);
infoBar = thumbnail.getInfoBar();
bottomP.add(infoBar, "North");
validate();
}
/**
* Displays the graph of the current bin. It is initialized using
* the current bin and either the selected lanes or all the lanes if
* none are selected. The correct bars are selected also.
*/
private void showGraph()
{
currentView = GRAPH;
// initialize it with the current bin, and all the bins and lanes
if(gel.getSelectedLanes().isEmpty())
graph.init(currentBin, gel.getLanes(), gel.getBins());
else
graph.init(currentBin, gel.getSelectedLanes(), gel.getBins());
mainPanel.removeAll();
mainPanel.add(graph);
remove(buttonBar);
buttonBar = graph.getButtonBar();
add(buttonBar, "North");
bottomP.remove(infoBar);
infoBar = graph.getInfoBar();
bottomP.add(infoBar, "North");
validate();
}
/**
* Displays the lane trace, setting the bars to the appropriate value.
* The trace displays either the first selected lane, or if there are
* no selected lanes, the first lane in the gel.
*/
private void showTrace()
{
currentView = TRACE;
// Pick a lane. Try the first one from the selected lanes first,
// then take the first lane, null if no lanes.
if(gel.getSelectedLanes().isEmpty())
{
//try all lanes.
if(gel.getLanes().isEmpty())
trace.init(null, gel.getLanes());
else
trace.init((Lane) gel.getLanes().dataAt(0), gel.getLanes());
}
else
trace.init((Lane) gel.getSelectedLanes().dataAt(0),
gel.getSelectedLanes());
mainPanel.removeAll();
mainPanel.add(trace);
remove(buttonBar);
buttonBar = trace.getButtonBar();
add(buttonBar, "North");
bottomP.remove(infoBar);
infoBar = trace.getInfoBar();
bottomP.add(infoBar, "North");
validate();
}
/**
* Displays the analysis output, with the correct bars. The analysis
* view is initialized with the current gel
*/
private void showAnalysis()
{
currentView = ANALYSIS;
analysis.init(gel);
mainPanel.removeAll();
mainPanel.add(analysis);
mainPanel.setScrollPosition(0, 0);
remove(buttonBar);
buttonBar = analysis.getButtonBar();
add(buttonBar, "North");
bottomP.remove(infoBar);
infoBar = analysis.getInfoBar();
bottomP.add(infoBar, "North");
validate();
}
/**
* Reads the specified files in to the gel. The import filter is
* retrieved from the dialog used to select the files. Any options
* for the filter are presented in an options dialog.
*
* @param files the list of files to import.
*/
private void importFiles(File files[])
{
ImportFilter filter = importDialog.getFilter();
statusLabel.setText("Importing using " + filter.getName());
// Show the options
OptionDialog optDialog = new OptionDialog(filter.getOptions(),
this,
filter.getName()+" Parameters");
optDialog.setVisible(true);
if(!optDialog.isCanceled())
{
Option[] opts = optDialog.getOptions();
filter.setOptions(opts);
// Conveted from lane to lane[] by Philip DeCamp 6/25/2001
Lane [] ln = null;
for(int i=0; i < files.length; i++)
{
try{
// read in the lane
ln = filter.readLane(files[i]);
// add it to the gel
// Begin --Added 6/25/2001 by Philip DeCamp
for(int j = 0; j < ln.length; j++)
if(ln[j] != null){
gel.addLane(ln[j]);
setCutoff(ln[j]);
}
// End --Added 6/25/2001 by Philip DeCamp
statusLabel.setText(filter.getName() + ": Imported " +
ln[0].getName() + " from " +
files[i].getAbsolutePath() + " (" +
(i+1) + " of " + files.length +
" files)");
}
catch(IOException ioE){
if(ioE instanceof FileNotFoundException)
errorDialog.showError(ioE);
else
{
errorDialog.showError(new IOException("Error on import. " +
ioE.getMessage()));
}
}
}
// adjust the intensity
gel.setIntensity(gel.getGlobalMaxIntensity());
// see if the size has been set, if not base the sizes off lane 0
if(!gelView.isSizeSet())
gelView.setGelSizeToMax(0);
statusLabel.setText("Import Complete. Rebuilding gel image...");
gelView.refresh(true);
} // if(!optDialog.isCanceled())
statusLabel.setText("Ready.");
}
/**
* Reads the specified file in to the program. The file should be the
* result of writing out a gel. This is the format used by the program.
* This is the result of an open operation.
*
* @param fileName the name of a gel file written by the program.
*
* @see AFLPcore.Gel#read
* @see FragmentMap#writeFile
*/
public void readFile(String fileName)
{
try
{
statusLabel.setText("Reading " + fileName);
FileInputStream fs = new FileInputStream(fileName);
BufferedInputStream bs = new BufferedInputStream(fs);
DataInputStream inStream = new DataInputStream(bs);
gel.read(inStream);
inStream.close();
fs.close();
statusLabel.setText("Read completed. Building gel image...");
// rebuild the gel image
gelView.refresh(true);
showGelImage();
statusLabel.setText("Ready.");
}
catch(IOException e)
{
statusLabel.setText("Read failed. Ready");
errorDialog.showError(new IOException("Error while reading in file " +
fileName + "." +
e.getMessage()));
}
}
/**
* Writes the gel out to the specified file name. This will write all of
* the information in the program session. In other words, it saves the
* session. The file can be restored with the readFile
* method.
*
* @param fileName the name of the file to write to.
*
* @see AFLPcore.Gel#write
* @see FragmentMap#readFile
*/
public void writeFile(String fileName)
{
try
{
statusLabel.setText("Writing " + fileName);
FileOutputStream fs = new FileOutputStream(fileName);
BufferedOutputStream bs = new BufferedOutputStream(fs);
DataOutputStream outStream = new DataOutputStream(bs);
gel.write(outStream);
outStream.close();
fs.close();
statusLabel.setText("Gel saved as " + fileName + ". Ready.");
}
catch (IOException e)
{
statusLabel.setText("Write failed! Ready.");
errorDialog.showError(new IOException("Couldn't write file." +
e.getMessage()));
}
}
/**
* Sets the inital cutoff level for the specified lane. The inital cutoff
* is set to 50% of the max value in the lane, and has only one level.
* The default cutoff function, defined by FeatureList
is
* used.
*
* @param ln the lane to set the cutoff for.
*/
private void setCutoff(Lane ln)
{
// Set some cutoffs initially: 1 level, start at beginning, 50% of max
// in lane.
Cutoff ct = new Cutoff(ln.getMinSize(), 1);
// Retrieve the default and then clone it so this lane gets it's own
// cutoff function.
CutoffFunction ctfn;
ctfn = (CutoffFunction) FeatureList.getCutoffMgr().getDefault();
ctfn = (CutoffFunction) ctfn.clone();
if(defaultCutoff == 0)
defaultCutoff = 0.5*ln.getMaxHeight(ln.getMinSize(), ln.getMaxSize());
Option[] opts = ctfn.getOptions();
opts[0].setValue(defaultCutoff);
ctfn.setOptions(opts);
ct.setCutoffFunction(ctfn, 0);
ln.addCutoff(ct);
}
/**
* Prompts the user for a name for a file to be saved, by presenting
* a file dialog box.
*/
private void saveFileAs()
{
String oldFile = currentFile;
String oldDir = currentDir;
{
fileDialog.setTitle("Save file...");
fileDialog.setMode(FileDialog.SAVE);
if(currentFile == null)
fileDialog.setFile("");
else
fileDialog.setFile(currentFile);
fileDialog.show();
currentFile = fileDialog.getFile();
currentDir = fileDialog.getDirectory();
}
if(currentFile != null)
{
writeFile(currentDir + currentFile);
statusLabel.setText("Saved " + currentDir + currentFile);
}
else
{
// Canceled, so set things back to the way they were
currentFile = oldFile;
currentDir = oldDir;
}
}
/**
* Prints the specified data to the printer. The user selects
* the printer using the system dependent print dialog, or equivalent.
* If the gel is specified, then it will be printed. Or the thumbnails
* could be printed. The data is specified by comparing the specified value
* to constants in this class. Note: The gel does not seem to print
* well at all. It seems to print in black and white, instead of grey
* scale. The others seem to print fine.
*
* @param displayType corresponds to one of the constants declared in this
* class: GEL
, THUMBNAIL
,
* GRAPH
, TRACE
, or
* ANALYSIS
.
*/
private void print(int displayType)
{
// Get the neccessary system resources
Toolkit tk = Toolkit.getDefaultToolkit();
PrintJob pJob = tk.getPrintJob(this, "AFLP print stuff", null);
if(pJob != null)
{
Graphics g = pJob.getGraphics();
Dimension d = pJob.getPageDimension();
int width = d.width - PAGE_H_ADJUST;
int height = d.height - PAGE_V_ADJUST - PAGE_HEADER_SPACE;
// Set the font for the graphics
g.setFont(new Font("SansSerif", Font.PLAIN, 10));
int oldWidth;
int oldHeight;
int gWidth;
int oldBorder;
int oldSpace;
String name;
Bin bin;
switch(displayType)
{
case GEL:
oldBorder = gel.getGelTopBorder();
oldWidth = gel.getLaneWidth();
oldSpace = gel.getLaneBorder();
// create the percent of the gel that the lane width occupies,
// as compared to that occupied by the lane borders.
double lanePercentage = 3.0/4.0;
gel.setLaneWidth((int)(width/gel.getNumLanes()*lanePercentage));
gel.setLaneBorder((int) (width/gel.getNumLanes() *
(1 - lanePercentage)));
GelView pageView = new GelView(gel, this);
pageView.setGelLength(height);
// create a little frame for the view, just to make it work.
Frame tempFrame = new Frame("Print renderer");
tempFrame.setLayout(null);
tempFrame.setBounds(0, 0, 1, 1);
tempFrame.add(pageView);
tempFrame.setVisible(true);
pageView.paint(g);
tempFrame.setVisible(false);
gel.setLaneWidth(oldWidth);
gel.setLaneBorder(oldSpace);
break;
case THUMBNAIL:
// figure out how many pages we need.
DataList lanes = thumbnail.getLanes();
int thumbWidth = thumbnail.getThumbnailSize().width;
int thumbHeight = thumbnail.getThumbnailSize().height;
int numThumbnails = lanes.size();
int numPerRow = width/thumbWidth;
int numPerColumn = height/thumbHeight;
int numPerPage = numPerRow * numPerColumn;
if(numPerPage < 1)
{
throw new IllegalArgumentException("Thumbnail won't fit on" +
" a page!");
// return; not reached
}
// draw some header info
bin = thumbnail.getBin();
name = bin.getName();
if(!name.equals(""))
name = name + ": ";
g.drawString(name + bin.getLocation() + "+/-" + bin.getRange() +
" " + bin.getScoreInfo()[0],
0, height + PAGE_HEADER_SPACE);
thumbnail.setViewWidth(width);
if(numPerPage >= numThumbnails)
{
thumbnail.print(g);
}
else
{
int firstLane = 0;
DataList tempLanes;
while(firstLane < numThumbnails)
{
tempLanes = new DataList();
for(int i=firstLane; i < (firstLane + numPerPage); i++)
tempLanes.addData(lanes.dataAt(i));
thumbnail.setLanes(tempLanes);
thumbnail.print(g);
// get the next page
g.dispose();
g = pJob.getGraphics();
firstLane += numPerPage;
}
thumbnail.setLanes(lanes);
}
break;
case GRAPH:
bin = graph.getBin();
oldWidth = graph.getWidth();
oldHeight= graph.getHeight();
gWidth = graph.getGraphWidth();
graph.setWidth(width);
graph.setHeight(height);
graph.setGraphWidth(width - 20);
graph.paint(g);
graph.setWidth(oldWidth);
graph.setHeight(oldHeight);
graph.setGraphWidth(gWidth);
name = bin.getName();
if(!name.equals(""))
name = name + ": ";
g.drawString(name + bin.getLocation() + "+/-" + bin.getRange() +
" " + bin.getScoreInfo()[0],
0, height + PAGE_HEADER_SPACE);
break;
case TRACE:
oldWidth = trace.getWidth();
oldHeight = trace.getHeight();
trace.setWidth(width);
trace.setHeight(height);
trace.print(g);
trace.setWidth(oldWidth);
trace.setHeight(oldHeight);
break;
case ANALYSIS:
TextPrinter textP = new TextPrinter(pJob);
textP.printString(analysis.getText(), g);
break;
}
g.dispose();
pJob.end();
statusLabel.setText("Done Printing. Ready.");
}
}
/**
* This will export the specified data view out to a file. A dialog
* box will be presented to allow the user to select a file name.
* Only the gel and analysis currently support exporting. The gel is
* exported as a PNG file, which can be read by several graphics programs.
* The analysis is exported as a simple text file.
*
* @param view corresponds to one of the constants declared in this
* class: GEL
, THUMBNAIL
,
* GRAPH
, TRACE
, or
* ANALYSIS
. Only GEL
and
* ANALYSIS
are currently supported.
*/
public void exportView(int view)
{
String exportFile;
String exportDir;
String oldDir = currentDir;
{
fileDialog.setTitle("Export file...");
fileDialog.setMode(FileDialog.SAVE);
fileDialog.setFile("");
fileDialog.show();
exportFile = fileDialog.getFile();
exportDir = fileDialog.getDirectory();
}
if(exportFile == null)
{
// Canceled, so set things back to the way they were
currentDir = oldDir;
}
else
{
try
{
FileOutputStream fs;
BufferedOutputStream bs;
switch(view) {
case GEL:
// Check the file extension.
int nameLength = exportFile.length();
if(nameLength < 4) {
exportFile += ".png";
} else {
String temp = exportFile.substring(nameLength - 4);
if(!temp.equalsIgnoreCase(".png")) {
exportFile += ".png";
}
}
fs = new FileOutputStream(exportDir + exportFile);
bs = new BufferedOutputStream(fs);
DataOutputStream outStream = new DataOutputStream(bs);
gel.writePNG(outStream);
outStream.close();
statusLabel.setText("Exported gel to " + exportDir +
exportFile + ". Ready.");
bs.close();
fs.close();
break;
case ANALYSIS:
fs = new FileOutputStream(exportDir + exportFile);
bs = new BufferedOutputStream(fs);
byte output[] = analysis.getText().getBytes();
bs.write(output, 0, output.length);
bs.flush();
statusLabel.setText("Exported analysis to " + exportDir +
exportFile + ". Ready.");
bs.close();
fs.close();
break;
default:
statusLabel.setText("Exporting this type is not " +
"supported. Ready.");
}
}
catch (IOException except)
{
errorDialog.showError(new IOException("Couldn't write file." +
except.getMessage()));
}
}
}
/**
* Displays an about dialog box for the program.
*/
protected void showAbout()
{
AboutDialog aboutD = new AboutDialog(this, "About Genographer");
aboutD.show();
}
/**
* Handles the events from buttons and menu items.
*/
public void actionPerformed(ActionEvent e)
{
try{
if((e.getSource() == openItem) ||
(e.getSource() == openButton))
{
fileDialog.setTitle("Open file...");
fileDialog.setMode(FileDialog.LOAD);
fileDialog.setDirectory(currentDir);
fileDialog.setFile("");
fileDialog.show();
currentFile = fileDialog.getFile();
currentDir = fileDialog.getDirectory();
if(currentFile != null)
{
readFile(currentDir + currentFile);
}
}
else if((e.getSource() == saveItem) ||
(e.getSource() == saveButton))
{
if(currentFile == null)
saveFileAs();
else
{
writeFile(currentDir + currentFile);
}
}
else if(e.getSource() == saveAsItem)
{
saveFileAs();
}
else if(e.getSource() == importItem)
{
importDialog.setVisible(true);
File files[] = importDialog.getFiles();
if(files != null)
importFiles(files);
}
else if((e.getSource() == newItem) ||
(e.getSource() == newButton))
{
gel = new Gel();
gelView = new GelView(gel, this);
switchTo("Gel");
}
else if((e.getSource() == printItem) ||
(e.getSource() == printButton))
{
print(currentView);
}
else if(e.getSource() == exportItem)
{
exportView(currentView);
}
else if(e.getSource() == exitItem)
{
endProgram();
}
else if(e.getSource() == viewGelItem)
{
switchTo("Gel");
}
else if(e.getSource() == viewThumbnailItem)
{
switchTo("Thumbnail");
}
else if(e.getSource() == viewGraphItem)
{
switchTo("Graph");
}
else if(e.getSource() == viewTraceItem)
{
switchTo("Trace");
}
else if(e.getSource() == viewAnalysisItem)
{
switchTo("Analysis");
}
else if(e.getSource() == gelRedrawItem)
{
if(currentView == GEL)
gelView.refresh(true);
}
else if(e.getSource() == binRedrawItem)
{
switch(currentView)
{
case THUMBNAIL:
thumbnail.refresh();
break;
case GRAPH:
graph.refresh();
break;
}
}
else if(e.getSource() == helpItem)
{
ProgOptions.showHelp(HELP_FILE);
}
else if(e.getSource() == aboutItem)
{
showAbout();
}
else if(e.getSource() == laneDeleteItem)
{
DataList lanesToDelete = gel.getSelectedLanes();
// Change it into an array
if(!lanesToDelete.isEmpty())
{
// this will give us the list, since once we start deleting,
// the list pointed to by lanesToDelete will start to change
// to.
Lane toDelete[] = new Lane[lanesToDelete.size()];
for(int i=0; i < toDelete.length; i++)
toDelete[i] = (Lane) lanesToDelete.dataAt(i);
for(int i=0; i < toDelete.length; i++)
gel.removeLane(toDelete[i]);
}
// update the display
gelView.refresh(true);
}
else
{
// Handle events from the operations
String opName;
opName = getName(laneOpItem, e);
if(opName != null)
{
// lane operation
LaneOperation laneOp;
laneOp = (LaneOperation) FeatureList.getLaneOpMgr().get(opName);
// see if we should use selected lanes or not.
if(gel.getSelectedLanes().isEmpty())
laneOp.doLaneOp(gel.getLanes());
else
laneOp.doLaneOp(gel.getLanes());
}
opName = getName(binOpItem, e);
if(opName != null)
{
// bin operation
BinOperation binOp;
binOp = (BinOperation) FeatureList.getBinOpMgr().get(opName);
if(binOp.isMultiBin())
binOp.doBinOp(gel.getBins());
else
{
if(gelView.getCurrentBin() != null)
binOp.doBinOp(gelView.getCurrentBin());
}
}
opName = getName(gelOpItem, e);
if(opName != null)
{
// gel operation
GelOperation gelOp;
gelOp = (GelOperation) FeatureList.getGelOpMgr().get(opName);
if(gel != null)
gelOp.doGelOp(gel);
}
}
// Refresh the current display. It may not be neccessary, but
// it may also be, so take the conservative approach and do it.
switch(currentView)
{
case GEL:
gelView.refresh(true);
case THUMBNAIL:
thumbnail.refresh();
break;
case GRAPH:
graph.refresh();
break;
}
}
catch(Throwable error)
{
// Take care of any error that might occur. All the errors come
// from the event thread, which will go through here some of the
// time.
errorDialog.showError(error);
}
}
/**
* exits the program when the window is closed.
*/
public void windowClosing(WindowEvent e)
{
endProgram();
}
/**
* Clean up before the program quits.
*/
private void endProgram()
{
// What kind of clean up do we need to do
System.exit(0);
}
/**
* Gives the name associated with a given action event. The
* menu items come from the FeatureList
. The action
* event is compared to all of the items, to see if one of them
* originated it. If so, then the name of that item is returned.
*
* @param items menu items that the event e
should be
* compared to.
* @param e the event for which we wish to obtain a name.
*
* @return either the name (label) of the item that generated the event
* or null
if none of the items produced the event.
*/
private String getName(MenuItem items[], ActionEvent e)
{
String name = null;
for(int i=0; i < items.length; i++)
if(e.getSource() == items[i])
name = items[i].getLabel();
return name;
}
/**
* Does a lot of laying out of the window, and menu construction.
*/
private void programInitialize()
{
// Make all the other things.
ControlBar controls = new ControlBar(this);
//=================== Make the menu ==================
MenuBar menuBar = new MenuBar();
// File menu
Menu fileMenu = new Menu("File");
newItem = new MenuItem("New");
openItem = new MenuItem("Open");
saveItem = new MenuItem("Save");
saveAsItem = new MenuItem("Save As...");
importItem = new MenuItem("Import...");
exportItem = new MenuItem("Export...");
printItem = new MenuItem("Print...");
exitItem = new MenuItem("Exit");
newItem.addActionListener(this);
openItem.addActionListener(this);
saveAsItem.addActionListener(this);
saveItem.addActionListener(this);
importItem.addActionListener(this);
exportItem.addActionListener(this);
printItem.addActionListener(this);
exitItem.addActionListener(this);
fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(saveAsItem);
fileMenu.add(new MenuItem("-"));
fileMenu.add(importItem);
fileMenu.add(exportItem);
fileMenu.add(new MenuItem("-"));
fileMenu.add(printItem);
fileMenu.add(new MenuItem("-"));
fileMenu.add(exitItem);
menuBar.add(fileMenu);
// Lane menu
Menu laneMenu = new Menu("Lane");
laneDeleteItem = new MenuItem("Delete Marked Lanes.");
laneDeleteItem.addActionListener(this);
laneMenu.add(laneDeleteItem);
menuBar.add(laneMenu);
laneOpItem = addMenu(laneMenu, FeatureList.getLaneOpMgr());
// Bin menu
Menu binMenu = new Menu("Bin");
binRedrawItem = new MenuItem("Redraw Bin");
binRedrawItem.addActionListener(this);
binMenu.add(binRedrawItem);
menuBar.add(binMenu);
binOpItem = addMenu(binMenu, FeatureList.getBinOpMgr());
// Gel menu
Menu gelMenu = new Menu("Gel");
gelRedrawItem = new MenuItem("Redraw Gel");
gelRedrawItem.addActionListener(this);
gelMenu.add(gelRedrawItem);
menuBar.add(gelMenu);
gelOpItem = addMenu(gelMenu, FeatureList.getGelOpMgr());
// View menu
Menu viewMenu = new Menu("View");
viewGelItem = new MenuItem("Gel");
viewThumbnailItem = new MenuItem("Thumbnail");
viewGraphItem = new MenuItem("Graph");
viewTraceItem = new MenuItem("Trace");
viewAnalysisItem = new MenuItem("Analysis");
viewGelItem.addActionListener(this);
viewThumbnailItem.addActionListener(this);
viewGraphItem.addActionListener(this);
viewTraceItem.addActionListener(this);
viewAnalysisItem.addActionListener(this);
viewMenu.add(viewGelItem);
viewMenu.add(viewThumbnailItem);
viewMenu.add(viewGraphItem);
viewMenu.add(viewTraceItem);
viewMenu.add(viewAnalysisItem);
menuBar.add(viewMenu);
// Help menu
Menu helpMenu = new Menu("Help");
helpItem = new MenuItem("Contents...");
aboutItem = new MenuItem("About");
helpItem.addActionListener(this);
aboutItem.addActionListener(this);
helpMenu.add(helpItem);
helpMenu.add(aboutItem);
menuBar.add(helpMenu);
//Add labels to status/info bars
statusLabel = new Label("Copyright (c) Montana" +
" State University 1998. Licensed under GNU" +
" General Public License. See help for details.");
statusBar.setLayout(null);
statusBar.add(statusLabel);
statusLabel.setBounds(5, 3, 800, 18);
mainPanel = new ScrollPane();
mainPanel.add(gelView);
add(mainPanel, "Center");
mainPanel.setVisible(true);
// Add all of the components
setMenuBar(menuBar);
add(controls, "West");
controls.setBounds(0, 0, 89, 200);
add(buttonBar, "North");
buttonBar.setBounds(0, 0, getSize().width, 32);
bottomP.setLayout(new BorderLayout());
bottomP.add(infoBar, "North");
bottomP.add(statusBar, "South");
// Different width b/c second one has bottom border
infoBar.setBounds(0, 0, getSize().width, BAR_HEIGHT);
statusBar.setBounds(0, BAR_HEIGHT + 1, getSize().width, BAR_HEIGHT + 1);
add(bottomP, "South");
}
/**
* Adds Operation
s from the specified Manager
* to the specified menu and stores the menu items. If the manager
* contains anything, the mehtod will add a separator to the menu before
* it adds any of the items.
*
* @param menu the menu to add the items to.
* @param mgr the manager to retrieve the operations from
*
* @return an array containing all of the menu items added.
*
* @see AFLPcore.Manager
*/
public MenuItem[] addMenu(Menu menu, Manager mgr)
{
String names[] = mgr.getNames();
MenuItem items[] = new MenuItem[names.length];
if(names.length > 0)
menu.add(new MenuItem("-"));
for(int i=0; i < names.length; i++)
{
items[i] = new MenuItem(names[i]);
menu.add(items[i]);
items[i].addActionListener(this);
}
return items;
}
// ==================Unused methods required by interfaces=================
/**Unused*/public void windowOpened(WindowEvent e) {}
/**Unused*/public void windowClosed(WindowEvent e) {}
/**Unused*/public void windowIconified(WindowEvent e) {}
/**Unused*/public void windowDeiconified(WindowEvent e) {}
/**Unused*/public void windowActivated(WindowEvent e) {}
/**Unused*/public void windowDeactivated(WindowEvent e) {}
}