001 /* 002 * Copyright 2007, 2012 Stephen Fisher and Junhyong Kim, University of 003 * Pennsylvania. 004 * 005 * This file is part of Glo-DB. 006 * 007 * Glo-DB is free software: you can redistribute it and/or modify it 008 * under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Glo-DB is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Glo-DB. If not, see <http://www.gnu.org/licenses/>. 019 * 020 * @(#)Root.java 021 */ 022 023 package edu.upenn.gloDB.gui; 024 025 import edu.upenn.gloDB.*; 026 import java.awt.*; 027 import java.awt.event.*; 028 import javax.swing.*; 029 import java.net.URL; 030 import java.net.MalformedURLException; 031 032 /** 033 * Base window for GUI. 034 * 035 * @author Stephen Fisher 036 * @version $Id: Root.java,v 1.35.2.28 2007/03/01 21:17:33 fisher Exp $ 037 */ 038 039 public class Root { 040 private static RootFrame rootFrame = null; 041 042 /** 043 * This will contain all error and warning messages. This output 044 * panel can be disabled by setting the 'showMessages' flag to 045 * false. When disabled, all messages printed will be displayed 046 * in the console. 047 */ 048 public static JTextArea messages = new JTextArea(20, 90); 049 050 /** 051 * Flag whether to display messages in the 'messages' panel. If 052 * false, then print the messages in the console. If true, then 053 * messages will only go to the messages panel and not the console. 054 */ 055 public static boolean showMessages = true; 056 057 /** 058 * This will contain all commands that the GUI generates and sends 059 * to the console to be run. The text in this panel can be copied 060 * and pasted into a python file to run directly in the console. 061 */ 062 public static JTextArea history = new JTextArea(10, 90); 063 064 public static JLabel statusBar; 065 066 public static JFrame show() { 067 // only allow one instance of rootFrame 068 if (rootFrame == null) rootFrame = new RootFrame(); 069 rootFrame.show(); 070 return rootFrame; 071 } 072 073 /** 074 * This will add the String to the history and if 'toConsole', 075 * then run the command through the console. 076 */ 077 public static void runCommand(String msg, boolean toConsole) { 078 history.append(msg + "\n"); 079 if (toConsole) GloDBMain.console.exec("print; " + msg); 080 } 081 082 private static class RootFrame extends JFrame implements ActionListener { 083 private JMenuItem loadTrack; 084 private JMenuItem saveTrack; 085 private JMenuItem newSequence; 086 private JMenuItem loadSequence; 087 private JMenuItem saveSequence; 088 private JMenuItem quit; 089 090 private JMenuItem copyHistory; 091 private JMenuItem clearHistory; 092 private JMenuItem selectHistory; 093 private JCheckBoxMenuItem toggleShowMessages; 094 private JMenuItem clearMessages; 095 private JMenuItem queryTracks; 096 // private JMenuItem updateTracks; 097 098 private JMenuItem browseTracks; 099 private JMenuItem browseSequences; 100 private JMenuItem displayTrack; 101 private JMenuItem displaySequence; 102 103 private JMenuItem helpTopics; 104 private JMenuItem viewAPI; 105 private JMenuItem parserDefs; 106 private JMenuItem about; 107 108 private JTextArea messages = Root.messages; 109 private JTextArea history = Root.history; 110 private JLabel statusBar = Root.statusBar; 111 112 public RootFrame() { 113 super("GLO-DB"); 114 115 // this will cause all warnings to be sent here instead of to 116 // the console 117 GloDBUtils.guiMessages = messages; 118 119 // setDefaultCloseOperation(DISPOSE_ON_CLOSE); 120 setDefaultCloseOperation(EXIT_ON_CLOSE); 121 122 // addWindowListener(new WindowAdapter() { 123 // public void windowClosing(WindowEvent e) { System.exit(0); } 124 // }); 125 126 /**** FILE MENU ****/ 127 JMenu fileMenu = new JMenu("File"); 128 fileMenu.setMnemonic(KeyEvent.VK_F); 129 130 loadTrack = addMenuItem(loadTrack, fileMenu, "Load Track", KeyEvent.VK_L, new ImageIcon("icons/load_m.png")); 131 saveTrack = addMenuItem(saveTrack, fileMenu, "Save Track", -1, new ImageIcon("icons/save_m.png")); 132 saveTrack.setMnemonic(KeyEvent.VK_S); 133 fileMenu.addSeparator(); 134 newSequence = addMenuItem(newSequence, fileMenu, "New Sequence", -1, new ImageIcon("icons/new_m.png")); 135 newSequence.setMnemonic(KeyEvent.VK_N); 136 loadSequence = addMenuItem(loadSequence, fileMenu, "Load Sequence", -1, new ImageIcon("icons/load_m.png")); 137 // saveSequence = addMenuItem(saveSequence, fileMenu, "Save Sequence", -1, new ImageIcon("icons/save_m.png")); 138 fileMenu.addSeparator(); 139 quit = addMenuItem(quit, fileMenu, "Quit", KeyEvent.VK_Q, new ImageIcon("icons/quit_m.png")); 140 141 /**** EDIT MENU ****/ 142 JMenu editMenu = new JMenu("Edit"); 143 editMenu.setMnemonic(KeyEvent.VK_E); 144 copyHistory = addMenuItem(copyHistory, editMenu, "Copy History", -1, new ImageIcon("icons/copy_m.png")); 145 copyHistory.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK)); 146 clearHistory = addMenuItem(clearHistory, editMenu, "Clear History", -1, new ImageIcon("icons/clear_m.png")); 147 clearHistory.setMnemonic(KeyEvent.VK_C); 148 selectHistory = addMenuItem(selectHistory, editMenu, "Select All History", -1, new ImageIcon("")); 149 selectHistory.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.CTRL_MASK)); 150 editMenu.addSeparator(); 151 toggleShowMessages = new JCheckBoxMenuItem("Enable Message Window"); 152 toggleShowMessages.addActionListener(this); 153 toggleShowMessages.setSelected(Root.showMessages); 154 toggleShowMessages.setToolTipText("Disabling the Message Window will cause messagaes to be sent to the command line."); 155 editMenu.add(toggleShowMessages); 156 clearMessages = addMenuItem(clearMessages, editMenu, "Clear Messages", -1, new ImageIcon("icons/clear_m.png")); 157 editMenu.addSeparator(); 158 queryTracks = addMenuItem(queryTracks, editMenu, "Query Tracks", KeyEvent.VK_G, new ImageIcon("icons/search_m.png")); 159 // updateTracks = addMenuItem(updateTracks, editMenu, "Update Tracks", -1, null); 160 161 /**** VIEW MENU ****/ 162 JMenu viewMenu = new JMenu("View"); 163 viewMenu.setMnemonic(KeyEvent.VK_V); 164 browseTracks = addMenuItem(browseTracks, viewMenu, "Browse Tracks", -1, new ImageIcon("icons/browse_m.png")); 165 browseSequences = addMenuItem(browseSequences, viewMenu, "Browse Sequences", -1, new ImageIcon("icons/browse_m.png")); 166 viewMenu.addSeparator(); 167 displayTrack = addMenuItem(displayTrack, viewMenu, "Display Track", -1, new ImageIcon("icons/graph_m.png")); 168 displaySequence = addMenuItem(displaySequence, viewMenu, "Display Sequence", -1, new ImageIcon("icons/graph_m.png")); 169 170 /**** HELP MENU ****/ 171 JMenu helpMenu = new JMenu("Help"); 172 helpMenu.setMnemonic(KeyEvent.VK_H); 173 helpTopics = addMenuItem(helpTopics, helpMenu, "Help Topics", -1, new ImageIcon("icons/help_m.png")); 174 viewAPI = addMenuItem(viewAPI, helpMenu, "API Documentation", -1, null); 175 parserDefs = addMenuItem(parserDefs, helpMenu, "Parser Definitions", -1, null); 176 helpMenu.addSeparator(); 177 about = addMenuItem(about, helpMenu, "About", -1, new ImageIcon("icons/info_m.png")); 178 179 // put menu together and add to root pane 180 JMenuBar menuBar = new JMenuBar(); 181 menuBar.add(fileMenu); 182 menuBar.add(editMenu); 183 menuBar.add(viewMenu); 184 // push help menu to the right side 185 menuBar.add(Box.createHorizontalGlue()); 186 menuBar.add(helpMenu); 187 getRootPane().setJMenuBar(menuBar); 188 189 // add messages as a scrolled text area. 190 messages.setEditable(false); 191 JScrollPane messagesSP = new JScrollPane(messages); 192 messagesSP.setBorder(BorderFactory.createLoweredBevelBorder()); 193 JPanel messagesP = new JPanel(false); 194 messagesP.setLayout(new BorderLayout()); 195 messagesP.add(new JLabel(" Messages:"), BorderLayout.NORTH); 196 messagesP.add(messagesSP, BorderLayout.CENTER); 197 198 // add history as a scrolled text area. 199 history.setEditable(false); 200 JScrollPane historySP = new JScrollPane(history); 201 historySP.setBorder(BorderFactory.createLoweredBevelBorder()); 202 JPanel historyP = new JPanel(false); 203 historyP.setLayout(new BorderLayout()); 204 historyP.add(new JLabel(" History:"), BorderLayout.NORTH); 205 historyP.add(historySP, BorderLayout.CENTER); 206 207 // setup main JPanel for window 208 JPanel mainPane = new JPanel(false); 209 mainPane.setLayout(new BorderLayout()); 210 JSplitPane mainSplitP = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 211 messagesP, historyP); 212 mainSplitP.setOneTouchExpandable(true); 213 // provide minimum sizes for the two components in the split pane 214 messagesP.setMinimumSize(new Dimension(700, 400)); 215 historyP.setMinimumSize(new Dimension(700, 200)); 216 // provide a preferred size for the split pane 217 mainSplitP.setPreferredSize(new Dimension(700, 600)); 218 // resize upper panel by 50% more that lower when the window 219 // is expended 220 mainSplitP.setResizeWeight(0.75); 221 mainPane.add(mainSplitP, BorderLayout.CENTER); 222 223 // add status bar at bottom of window. Use a 'spacer' so that 224 // anything added to statusBar later won't be crammed into the 225 // left margin. 226 statusBar = new JLabel(" "); 227 JPanel statusBarP = new JPanel(false); 228 statusBarP.setBorder(BorderFactory.createLoweredBevelBorder()); 229 statusBarP.setLayout(new BorderLayout()); 230 statusBarP.add(new JLabel(" "), BorderLayout.WEST); 231 statusBarP.add(statusBar, BorderLayout.CENTER); 232 mainPane.add(statusBarP, BorderLayout.SOUTH); 233 234 getContentPane().add(mainPane); 235 pack(); 236 237 // set the default window size 238 // setSize(getSize().width + 300, getSize().height + 200); 239 240 // display the window 241 // setVisible(true); 242 show(); 243 } 244 245 //-------------------------------------------------------------------------- 246 // Miscellaneous Methods 247 248 /** Handle menu items. */ 249 public void actionPerformed(ActionEvent e) { 250 // history.append("Event source: " + ((JMenuItem) e.getSource()).getText() + "\n"); 251 252 // erase status bar whenever there is an ActionEvent. 253 statusBar.setText(""); 254 255 if (e.getSource() instanceof JMenuItem) { 256 JMenuItem source = (JMenuItem) e.getSource(); 257 258 if (source == loadTrack) { 259 GUITrackIO.loadTrack(); 260 } else if (source == saveTrack) { 261 String track = GUIUtils.trackSelector(); 262 if (track.length() == 0) return; 263 GUITrackIO.saveTrack(track); 264 } else if (source == loadSequence) { 265 GUISequenceIO.loadSequence(); 266 } else if (source == newSequence) { 267 GUISequenceIO.newSequence(); 268 } else if (source == quit) { 269 System.exit(0); 270 } else if (source == copyHistory) { 271 history.copy(); 272 // exit here so the 'history' routines below don't undo this 273 return; 274 } else if (source == clearHistory) { 275 history.selectAll(); 276 history.replaceSelection(""); 277 return; 278 } else if (source == selectHistory) { 279 history.selectAll(); 280 // exit here so the 'history' routines below don't undo this 281 return; 282 } else if (source == toggleShowMessages) { 283 Root.showMessages = toggleShowMessages.isSelected(); 284 285 if (Root.showMessages) GloDBUtils.guiMessages = messages; 286 else GloDBUtils.guiMessages = null; 287 // GloDBUtils.printMsg("Value of showMessages: " + Boolean.toString(Root.showMessages)); 288 return; 289 } else if (source == clearMessages) { 290 messages.selectAll(); 291 messages.replaceSelection(""); 292 return; 293 } else if (source == queryTracks) { 294 new QueryBuilder(); 295 Root.runCommand("QueryBuilder()", false); 296 } else if (source == displayTrack) { 297 // the following doesn't work because Root() doesn't 298 // get redrawn while waiting on GenomeBrowser() 299 /* 300 // run command here so can change cursor to "wait" 301 // while getting communicating with Genome Browser 302 String track = GUIUtils.trackSelector(); 303 if (track.length() > 0) { 304 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 305 this.repaint(); 306 new ViewHTML(GenomeBrowser.viewTrack(track)); 307 Root.runCommand("genomeBrowserTrack(\"" + track + "\")", false); 308 this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 309 } 310 */ 311 Root.runCommand("viewTrackGenomeBrowser()", true); 312 } else if (source == browseSequences) { 313 Root.runCommand("sequenceBrowser()", true); 314 } else if (source == browseTracks) { 315 Root.runCommand("trackBrowser()", true); 316 } else if (source == helpTopics) { 317 Root.runCommand("help()", true); 318 } else if (source == viewAPI) { 319 try { 320 URL url = new URL("file:documentation/index.html"); 321 new ViewHTML(url); 322 Root.runCommand("viewAPI()", false); 323 } catch (MalformedURLException urlException) { 324 GloDBUtils.printError("API documentation not found."); 325 } 326 } else if (source == parserDefs) { 327 new ViewParserDefs(); 328 Root.runCommand("parserDefs()", false); 329 } else if (source == about) { 330 Root.runCommand("about()", true); 331 } else { 332 statusBar.setText("Menu item not yet available."); 333 GloDBUtils.printMsg("Menu item not yet available."); 334 } 335 336 history.setCaretPosition(history.getDocument().getLength()); 337 } 338 } 339 340 /** Add specified item to specified menu. */ 341 private JMenuItem addMenuItem(JMenuItem item, JMenu menu, String label, int mnemonic, ImageIcon image) { 342 JMenuItem out; 343 if (image == null) { 344 out = new JMenuItem(label); 345 } else { 346 out = new JMenuItem(label, image); 347 } 348 if (mnemonic != -1) { 349 out.setMnemonic(mnemonic); 350 out.setAccelerator(KeyStroke.getKeyStroke(mnemonic, ActionEvent.ALT_MASK)); 351 } 352 out.addActionListener(this); 353 menu.add(out); 354 return out; 355 } 356 357 } // Root.java 358 }