package org.seqcode.projects.seqview; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; 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.net.URL; import java.sql.SQLException; import java.util.ArrayList; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JRadioButtonMenuItem; import javax.swing.JTextField; import org.seqcode.genome.location.Region; import org.seqcode.gseutils.NotFoundException; import org.seqcode.projects.seqview.components.RegionListPanel; import org.seqcode.projects.seqview.components.RegionPanel; import org.seqcode.projects.seqview.components.SaveRegionsAsFasta; import org.seqcode.projects.seqview.components.SeqViewOptionsFrame; import org.seqcode.projects.seqview.components.SeqViewOptionsPane; import org.seqcode.projects.seqview.components.SeqViewStatus; import org.seqcode.projects.seqview.components.SeqViewStatusBar; import org.seqcode.viz.DynamicAttribute; /** * SeqView is a driver class that derives a little from WarpDrive's RegionFrame. * * It aims to be the top-level class, running the others, whereas WarpOptionsFrame * was the top-level class in WarpDrive. * This class assumes you will view one genome version at a time (RegionFrame did not). * If you switch genomes, the current session should be wiped out. * * @author mahony * */ public class SeqView extends JFrame { protected SeqViewOptions options; protected SeqViewOptionsFrame optionsFrame; protected SeqViewOptionsPane optionsPane; protected RegionPanel regPanel=null; protected SeqViewStatus status; protected SeqViewStatusBar statusBar; protected boolean imageraster; private File currDirectory = new File(System.getProperty("user.home")); public SeqView(String[] args) throws NotFoundException, SQLException, IOException { //Set up the browser window setSize(700,500); setLocation(50,50); setJMenuBar(createDefaultJMenuBar()); imageraster = true; this.setLayout(new BorderLayout(0,0)); status = new SeqViewStatus(); status.setStatus("Loading genome", Color.red); statusBar = new SeqViewStatusBar(status); statusBar.setPreferredSize(new Dimension(getWidth(), SeqViewOptions.STATUS_BAR_HEIGHT)); setTitle("Loading genome information..."); this.setBackground(Color.black); add(statusBar, BorderLayout.PAGE_END); setVisible(true); //Load command-line options options = SeqViewOptions.parseCL(args); setTitle(options.getGenome().getSpeciesName() + " " + options.getGenome().getVersion()); regPanel = new RegionPanel(options, status, currDirectory); add(regPanel, BorderLayout.CENTER); status.setStatus("Genome loaded... loading experiment list", Color.red); //Initiate options pane & frame optionsPane = new SeqViewOptionsPane(options); optionsFrame = new SeqViewOptionsFrame(optionsPane, this); status.setStatus("Genome loaded", Color.black); //Close operations this.setDefaultCloseOperation(EXIT_ON_CLOSE); final SeqView thisviewer = this; this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { if(regPanel!=null && !regPanel.isClosed()) regPanel.handleWindowClosing(); if(!optionsFrame.isClosed()){ optionsFrame.close(); } thisviewer.dispose(); } }); } public String getVersion(){ return "Version 0.2, Aug-2014"; } public RegionPanel getRegionPanel() { return regPanel; } public SeqViewOptions getOptions(){return options;} /** * Update the viewer's options, changing genomes if required. * @param opts */ public void updateOptions(SeqViewOptions opts){ if(regPanel ==null){ //regPanel should have been created in the constructor, so if this is true, something is wrong. //Nevertheless: regPanel = new RegionPanel(opts, status, currDirectory); add(regPanel, BorderLayout.PAGE_START); }else if ( options==null || !options.getGenome().equals(opts.getGenome())) { //Overwrite panel for different genome setTitle(opts.getGenome().getSpeciesName() + " " + opts.getGenome().getVersion()); regPanel.reinit(opts); } else { if (options != null && opts.getGenome().equals(options.getGenome())) { SeqViewOptions diffopts = opts.clone(); diffopts.differenceOf(options); regPanel.addPaintersFromOpts(diffopts); } } options=opts; this.repaint(); } private JMenuBar createDefaultJMenuBar() { JMenuBar jmb = new JMenuBar(); JMenu filemenu, editmenu, imagemenu, navigationmenu, displaymenu, aboutmenu, toolsmenu; JMenuItem item; final SeqView thisviewer = this; jmb.add((filemenu = new JMenu("File"))); filemenu.add((item = new JMenuItem("Add Data Tracks"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { optionsPane = new SeqViewOptionsPane(regPanel.getCurrentOptions()); optionsFrame = new SeqViewOptionsFrame(optionsPane, thisviewer); } catch (NotFoundException e1) { e1.printStackTrace(); } } }); filemenu.add((item = new JMenuItem("Add Track From Region File"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(thisviewer.getRegionPanel()!=null && !thisviewer.getRegionPanel().isClosed()) thisviewer.getRegionPanel().addTrackFromFile(false); } }); filemenu.add((item = new JMenuItem("Add Track From GFF File"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(thisviewer.getRegionPanel()!=null && !thisviewer.getRegionPanel().isClosed()) thisviewer.getRegionPanel().addTrackFromFile(true); } }); filemenu.add((item = new JMenuItem("Save Region as FASTA"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new SaveRegionsAsFasta(thisviewer.getRegionPanel().getRegion()); } }); filemenu.addSeparator(); filemenu.add((item = new JMenuItem("Exit"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(thisviewer.getRegionPanel()!=null && !thisviewer.getRegionPanel().isClosed()) thisviewer.getRegionPanel().close(); System.exit(0); } }); jmb.add((editmenu = new JMenu("Edit"))); editmenu.add((item = new JMenuItem("Configure All SeqData Tracks"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { thisviewer.getRegionPanel().configSeqDataTracksBatch(); } }); jmb.add((imagemenu = new JMenu("Image"))); imagemenu.add((item = new JMenuItem("Save Image"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new ImageConfigurationFrame(thisviewer); } }); jmb.add((navigationmenu = new JMenu("Navigation"))); /*navigationmenu.add((item = new JMenuItem("Binding Event List"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { RegionListPanel rlp = new RegionListPanel(thisviewer.getRegionPanel(),null); RegionListPanel.makeFrame(rlp); new BindingScanSelectFrame(thisviewer.getRegionPanel().getGenome(),rlp); } }); */ navigationmenu.add((item = new JMenuItem("Open Region List"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser chooser; chooser = new JFileChooser(currDirectory); int v = chooser.showOpenDialog(null); if(v == JFileChooser.APPROVE_OPTION) { File f = chooser.getSelectedFile(); currDirectory = chooser.getCurrentDirectory(); java.util.List<Region> regions = RegionPanel.readRegionsFromFile(regPanel.getGenome(),f.getAbsolutePath(),false); RegionListPanel p = new RegionListPanel(regPanel, regions); RegionListPanel.makeFrame(p); } } }); navigationmenu.add((item = new JMenuItem("New Region List"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { RegionListPanel p = new RegionListPanel(regPanel, new ArrayList<Region>()); RegionListPanel.makeFrame(p); } }); ButtonGroup group = new ButtonGroup(); jmb.add(displaymenu = new JMenu("Display")); displaymenu.add((item = new JRadioButtonMenuItem("Screen"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DynamicAttribute.getGlobalAttributes().setType(DynamicAttribute.SCREEN); thisviewer.repaint(); } }); item.setSelected(true); group.add(item); displaymenu.add((item = new JRadioButtonMenuItem("Display"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DynamicAttribute.getGlobalAttributes().setType(DynamicAttribute.DISPLAY); thisviewer.repaint(); } }); group.add(item); displaymenu.add((item = new JRadioButtonMenuItem("Print"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DynamicAttribute.getGlobalAttributes().setType(DynamicAttribute.PRINT); thisviewer.repaint(); } }); group.add(item); //TODO: uncomment this to bring back the WeightMatrix browser option //jmb.add(toolsmenu = new SeqViewToolsMenu(panel)); jmb.add((aboutmenu = new JMenu("Help"))); aboutmenu.add((item = new JMenuItem("About"))); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new AboutMessage(thisviewer.getVersion()); } }); return jmb; } class ImageConfigurationFrame extends JFrame implements ActionListener { private SeqView parent; private ButtonGroup rasterGroup; private JRadioButton pngButton, svgButton; private JTextField widthfield, heightfield; private JButton savebutton, cancelbutton; private int imagewidth, imageheight; public ImageConfigurationFrame(SeqView p) { parent = p; rasterGroup = new ButtonGroup(); pngButton = new JRadioButton("PNG"); pngButton.setMnemonic(KeyEvent.VK_P); pngButton.setSelected(parent.imageraster); svgButton = new JRadioButton("SVG"); svgButton.setMnemonic(KeyEvent.VK_S); svgButton.setSelected(!parent.imageraster); rasterGroup.add(pngButton); rasterGroup.add(svgButton); JLabel widthlabel = new JLabel("Width"); JLabel heightlabel = new JLabel("Height"); imagewidth = parent.getRegionPanel().getWidth(); imageheight = parent.getRegionPanel().getHeight(); widthfield = new JTextField(Integer.toString(imagewidth)); heightfield = new JTextField(Integer.toString(imageheight)); savebutton = new JButton("Save"); cancelbutton = new JButton("Cancel"); savebutton.addActionListener(this); cancelbutton.addActionListener(this); JPanel toppanel = new JPanel(); toppanel.setLayout(new BorderLayout()); JPanel buttonpanel = new JPanel(); buttonpanel.add(savebutton); buttonpanel.add(cancelbutton); toppanel.add(buttonpanel,BorderLayout.SOUTH); JPanel infopanel = new JPanel(); infopanel.setLayout(new BorderLayout()); JPanel formatpanel = new JPanel(new GridLayout(1, 0)); formatpanel.add(pngButton); formatpanel.add(svgButton); infopanel.add(formatpanel,BorderLayout.NORTH); JPanel textpanel = new JPanel(); textpanel.setLayout(new GridLayout(2,2)); textpanel.add(widthlabel); textpanel.add(widthfield); textpanel.add(heightlabel); textpanel.add(heightfield); infopanel.add(textpanel,BorderLayout.CENTER); toppanel.add(infopanel,BorderLayout.CENTER); getContentPane().add(toppanel); setMinimumSize(new Dimension(150,150)); setSize(getPreferredSize()); pack(); setVisible(true); } public void actionPerformed (ActionEvent e) { if (e.getSource() == savebutton) { parent.imageraster = pngButton.isSelected(); JFileChooser chooser; chooser = new JFileChooser(currDirectory); int v = chooser.showSaveDialog(null); if(v == JFileChooser.APPROVE_OPTION) { File f = chooser.getSelectedFile(); currDirectory = chooser.getCurrentDirectory(); boolean raster = imageraster; if (f.getAbsolutePath().matches(".svg")) { raster = false; }else if (f.getAbsolutePath().matches(".png")) { raster = true; } try { regPanel.saveImage(f,imagewidth,imageheight,raster); } catch (IOException ex) { ex.printStackTrace(); } } this.dispose(); } else if (e.getSource() == cancelbutton) { this.dispose(); } } } class AboutMessage extends JFrame implements ActionListener { private JButton okbutton; public AboutMessage(String version) { JLabel iconlabel=null; try{ URL picURL = getClass().getResource("/edu/psu/compbio/seqcode/gse/seqview/SeqViewLogo.png"); if(picURL!=null){ ImageIcon icon = new ImageIcon(picURL, "SeqView"); iconlabel = new JLabel(icon); iconlabel.setPreferredSize(new Dimension(249,161)); } String text = "<html><center>"+ "<p>"+version+ "<p>"+ "<p>Written by Shaun Mahony"+ "<p>"+ "<p>Based on the GSE library,"+ "<p>by Alex Rolfe & Tim Danford"+ "<p>(Gifford Lab, CSAIL, MIT)"+ "</html>"; javax.swing.JLabel messagelabel = new javax.swing.JLabel(text); okbutton = new JButton("OK"); okbutton.addActionListener(this); JPanel toppanel = new JPanel(); toppanel.setLayout(new GridBagLayout()); if(iconlabel!=null) toppanel.add(iconlabel); else{ javax.swing.JLabel svlabel = new javax.swing.JLabel(new String("<html><center><font size=\"+2\" color=\"blue\">SeqView</font></html>")); toppanel.add(svlabel); } toppanel.add(messagelabel); JPanel buttonpanel = new JPanel(); buttonpanel.add(okbutton); toppanel.add(buttonpanel); getContentPane().add(toppanel); pack(); setMinimumSize(new Dimension(300,250)); setPreferredSize(new Dimension(300,250)); setLocation(100,100); setVisible(true); } catch (NullPointerException e) { e.printStackTrace(); } } public void actionPerformed (ActionEvent e) { if (e.getSource() == okbutton) { this.dispose(); } } } /** * The main driver for SeqView * @param args * @throws NotFoundException * @throws SQLException * @throws IOException */ public static void main(String args[]) throws NotFoundException, SQLException, IOException { try{ SeqView viewer = new SeqView(args); } catch (Exception e) { e.printStackTrace(); } } }