/** * G4blGui.java -- run G4beamline with a Graphical User Interface. * * NOTE: this program expects to be run: * java -cp $G4BL_DIR/share/g4beamline G4blGui [input.file] * It uses the user classpath to find the G4beamline install directory, * expecting the classpath to be the share/g4beamline directory under * $G4BL_DIR. * * Copyright 2007-2012 by Tom Roberts, all rights reserved. * This program is released under the Gnu Public License. */ import java.io.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.net.URL; public class G4blGui extends WindowAdapter implements ActionListener, HyperlinkListener { // CopyThread will copy a sub-process' stderr/stdout to stderr/stdout. static class CopyThread extends Thread { BufferedReader in; PrintStream out; CopyThread(InputStream _in, PrintStream _out) { super(); in = new BufferedReader(new InputStreamReader(_in)); out = _out; start(); } public void run() { try { String line; while( (line=in.readLine()) != null) out.println(line); in.close(); } catch(Exception e) { } } }; JFrame frame; JButton runButton; JTextField inputFileField; JTextField outputFileField; JTextField paramField; JTextField otherViewerField; JCheckBox historootEventsField; JSpinner nViewerEventsField; JSpinner nViewerRunsField; String viewer; JTextArea outputArea; boolean doScroll; BufferedWriter outputFile; JScrollPane helpScroll; JScrollPane outputScroll; JEditorPane helpPane; Process g4beamlineProcess; Process wiredProcess; JScrollBar scroll; int lastScroll; boolean aborted; String osName; String system="."; Map<String,String> env; File currentDirectory; File inputFile; String filesep; String pathsep; String g4bl_dir; boolean needToRunWired; String g4blProcessID; public G4blGui(String[] args) { aborted = false; filesep = System.getProperty("file.separator"); pathsep = System.getProperty("path.separator"); osName = System.getProperty("os.name"); currentDirectory = new File(System.getProperty("user.dir")); String ext = ""; if(osName.startsWith("Windows")){ currentDirectory = new File(System.getProperty("user.home")); ext = ".exe"; } if(!currentDirectory.exists() || !currentDirectory.isDirectory()) currentDirectory = new File(System.getProperty("user.home")); inputFile = null; viewer = "none"; outputArea = null; doScroll = true; outputFile = null; g4beamlineProcess = null; wiredProcess = null; lastScroll = 0; needToRunWired = false; // handle args[] -- change directory to directory containing input.file if(args.length == 1) { inputFile = new File(args[0]); File d = inputFile.getParentFile(); if(inputFile == null || d == null || !inputFile.exists() || !d.exists() || !d.isDirectory()) inputFile = null; // fail silently else currentDirectory = d; } // find the installation directory G4BL_DIR g4bl_dir = Util.findG4blDir(); if(g4bl_dir == null) { JOptionPane.showMessageDialog(frame, "Cannot determine install directory.\n"); System.exit(1); } File dir = new File(g4bl_dir); // find SYSTEM if(osName.startsWith("Windows")) system = "WIN32"; else if(osName.startsWith("Mac")) system = "Darwin"; else if(osName.startsWith("Linux")) system = "Linux"; System.out.printf("SYSTEM='%s'\n",system); // Get the current environmennt into a writable Map<> env = new HashMap<String,String>(); Map<String,String> oldenv = System.getenv(); Iterator<String> iter = oldenv.keySet().iterator(); while(iter.hasNext()) { String key = iter.next(); String val = oldenv.get(key); env.put(key,val); } env.put("G4BL_DIR",g4bl_dir); // check for G4BEAMLINE set if(!env.containsKey("G4BEAMLINE")) { env.put("G4BEAMLINE",g4bl_dir + "/bin/g4beamline"); } else { System.out.printf("G4BEAMLINE='%s'\n",env.get("G4BEAMLINE")); } // set ROOTSYS if(!env.containsKey("ROOTSYS")) env.put("ROOTSYS",""); // Put physics datasets into the environment (not overwriting) String geant4_data = Util.findGeant4Data(); while(geant4_data == null) try { int ok = JOptionPane.showConfirmDialog(null, "The Geant4Data are not found; they are required to run G4beamline.\n"+ "If you already have them, you can manually copy or link them to\n"+ " "+g4bl_dir+"/Geant4Data\n"+ "Otherwise, select Yes to run G4blData to download them,\n"+ "or No to exit G4beamline.","Error",JOptionPane.YES_NO_OPTION); if(ok == JOptionPane.NO_OPTION) System.exit(1); // Geant4Data does not exist -- run G4blData runG4blData(); geant4_data = Util.findGeant4Data(); } catch(Exception e) { System.out.println(e.toString()); } File data = new File(geant4_data); String[] list = data.list(); if(list != null) { for(int j=0; j<list.length; ++j) { File f = new File(data,list[j]); if(!f.exists() || !f.isDirectory()) continue; if(list[j].startsWith("G4ABLA")) { env.put("G4ABLADATA",f.getAbsolutePath()); } else if(list[j].startsWith("G4EMLOW")) { env.put("G4LEDATA",f.getAbsolutePath()); } else if(list[j].startsWith("G4NDL")) { env.put("G4NEUTRONHPDATA",f.getAbsolutePath()); } else if(list[j].startsWith("G4NEUTRONXS")) { env.put("G4NEUTRONXSDATA",f.getAbsolutePath()); } else if(list[j].startsWith("G4PII")) { env.put("G4PIIDATA",f.getAbsolutePath()); } else if(list[j].startsWith("PhotonEvaporation")) { env.put("G4LEVELGAMMADATA",f.getAbsolutePath()); } else if(list[j].startsWith("RadioactiveDecay")) { env.put("G4RADIOACTIVEDATA",f.getAbsolutePath()); } else if(list[j].startsWith("RealSurface")) { env.put("G4REALSURFACEDATA",f.getAbsolutePath()); } } } // Create the window. frame = new JFrame("G4beamline"); frame.setIconImage(Toolkit.getDefaultToolkit().getImage(g4bl_dir +"/share/g4beamline/g4blicon.png")); frame.addWindowListener(this); Box header = Box.createVerticalBox(); // header row 1 header.add(Box.createVerticalStrut(5)); Box row = Box.createHorizontalBox(); row.add(Box.createHorizontalStrut(5)); row.add(new JLabel(" Input file: ")); inputFileField = new JTextField(15); inputFileField.setEditable(false); if(inputFile != null) inputFileField.setText(inputFile.getPath()); row.add(inputFileField); row.add(Box.createHorizontalStrut(5)); JButton browseButton = new JButton("Browse"); browseButton.addActionListener(this); row.add(browseButton); row.add(new JLabel(" Output file: ")); outputFileField = new JTextField(10); outputFileField.setText("g4bl.out"); row.add(outputFileField); row.add(Box.createHorizontalStrut(15)); JButton b = new JButton("Help"); b.addActionListener(this); row.add(b); row.add(Box.createHorizontalStrut(15)); header.add(row); // header row 2 header.add(Box.createVerticalStrut(5)); row = Box.createHorizontalBox(); row.add(Box.createRigidArea(new Dimension(5,0))); row.add(new JLabel("Parameters: ")); paramField = new JTextField(40); row.add(paramField); row.add(Box.createHorizontalStrut(5)); historootEventsField = new JCheckBox("HistoRoot Events"); //historootEventsField.addActionListener(this); row.add(historootEventsField); row.add(Box.createHorizontalStrut(5)); header.add(row); // header row 3 header.add(Box.createVerticalStrut(5)); row = Box.createHorizontalBox(); row.add(Box.createRigidArea(new Dimension(5,0))); JPanel viewerPanel = new JPanel(); viewerPanel.setBackground(new Color(255,255,180)); // pale yellow viewerPanel.setOpaque(true); viewerPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); viewerPanel.add(new JLabel(" Viewer: ")); ButtonGroup group = new ButtonGroup(); JRadioButton button = new JRadioButton("none",true); button.addActionListener(this); button.setOpaque(false); group.add(button); viewerPanel.add(button); button = new JRadioButton("best"); button.addActionListener(this); button.setOpaque(false); group.add(button); viewerPanel.add(button); button = new JRadioButton("Other:"); button.addActionListener(this); button.setOpaque(false); group.add(button); viewerPanel.add(button); otherViewerField = new JTextField(10); otherViewerField.setMaximumSize(otherViewerField.getPreferredSize()); viewerPanel.add(otherViewerField); viewerPanel.add(new JLabel(" events/run: ")); nViewerEventsField = new JSpinner(new SpinnerNumberModel(1,1,9999,1)); nViewerEventsField.setValue(1); nViewerEventsField.setMaximumSize(nViewerEventsField.getPreferredSize()); viewerPanel.add(nViewerEventsField); viewerPanel.add(new JLabel(" # runs: ")); nViewerRunsField = new JSpinner(new SpinnerNumberModel(1,1,99,1)); nViewerRunsField.setValue(10); nViewerRunsField.setMaximumSize(nViewerRunsField.getPreferredSize()); viewerPanel.add(nViewerRunsField); viewerPanel.doLayout(); // fix the size of the viewer panel viewerPanel.setMinimumSize(viewerPanel.getPreferredSize()); viewerPanel.setMaximumSize(viewerPanel.getPreferredSize()); row.add(viewerPanel); row.add(Box.createGlue()); row.add(new JLabel(" ")); runButton = new JButton(" Run "); // spaces so "Abort" will fit runButton.addActionListener(this); frame.getRootPane().setDefaultButton(runButton); row.add(runButton); row.add(Box.createHorizontalStrut(15)); header.add(row); header.add(Box.createVerticalStrut(5)); frame.getContentPane().add(header,BorderLayout.PAGE_START); displayHelp(); // Display the window. frame.pack(); frame.setVisible(true); // scroll back to the top of outputArea javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { scroll.setValue(scroll.getMinimum()); } }); } // all listener actions come here (except Hyperlink) public void actionPerformed(ActionEvent event) { String eventName = event.getActionCommand(); //System.out.printf("event=%s\n",eventName); if(eventName.equals(" Run ")) { aborted = false; outputSetup(); try { if(wiredProcess != null) wiredProcess.destroy(); wiredProcess = null; deleteStaleFiles(); g4beamlineProcess = runG4beamline(); if(g4beamlineProcess != null) new RunMonitorThread().start(); } catch(Exception e) { JOptionPane.showMessageDialog(frame, "Program Failed - Exception\n" + e.toString()); System.out.printf("Program Failed - Exception: %s\n", e.toString()); } } else if(eventName.equals("Abort")) { aborted = true; runButton.setText(" Run "); doAbort(); } else if(eventName.equals("Browse")) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(currentDirectory); if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { inputFile = chooser.getSelectedFile(); currentDirectory = chooser.getCurrentDirectory(); inputFileField.setText(inputFile.getPath()); } } else if(eventName.equals("none")) { viewer = "none"; } else if(eventName.equals("best")) { viewer = "best"; if(osName.startsWith("Linux") || osName.startsWith("Mac")) { if(System.getenv("DISPLAY") == null) JOptionPane.showMessageDialog(frame, "X-windows is needed but DISPLAY is not set."); } } else if(eventName.equals("Other:")) { viewer = "Other"; } else if(eventName.equals("Help")) { displayHelp(); } } void displayHelp() { // HTML JEditorPane for help text (replaced by outputArea when // Run is pushed) if(helpScroll != null) return; try { if(outputScroll != null) frame.getContentPane().remove(outputScroll); outputScroll = null; outputArea = null; helpPane = new JEditorPane("file:" + g4bl_dir + filesep + "share/g4beamline/Help.html"); helpPane.setEditable(false); helpPane.setPreferredSize(new JTextArea(32,60).getPreferredSize()); helpPane.addHyperlinkListener(this); JScrollPane s = new JScrollPane(helpPane); helpScroll = s; scroll = s.getVerticalScrollBar(); frame.getContentPane().add(s,BorderLayout.CENTER); frame.validate(); } catch(Exception e) { System.out.printf("Error: %s\n",e.toString()); } } void runG4blData() throws Exception { // Use a separate Java VM so we can wait on it. String cmd[] = new String[4]; cmd[0] = "java"; cmd[1] = "-classpath"; cmd[2] = g4bl_dir+"/share/g4beamline"; cmd[3] = "G4blData"; System.out.println("Running '"+cmd[0]+" "+cmd[1]+" "+cmd[2]+" "+cmd[3]+"'"); Process proc = Runtime.getRuntime().exec(cmd); new CopyThread(proc.getErrorStream(),System.err); new CopyThread(proc.getInputStream(),System.out); proc.waitFor(); } public void hyperlinkUpdate(HyperlinkEvent e) { if(helpPane == null) return; URL url = e.getURL(); if(url == null) return; if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { String s = url.toString(); if(url.getRef() != null) { helpPane.scrollToReference(url.getRef()); } else if(s.endsWith("file:/G4blData")) { try { runG4blData(); } catch(Exception ee) { } } } } /** doabort() will abort G4beamline. * seems to work, even though it might be just killing the shell. **/ void doAbort() { if(g4beamlineProcess != null) { if(g4blProcessID.length() > 0) { try { if(Runtime.getRuntime(). exec("kill -2 "+g4blProcessID).waitFor()==0) Thread.sleep(1000); } catch(Exception e) { /* ignore */} } if(g4beamlineProcess != null) { g4beamlineProcess.destroy(); g4beamlineProcess = null; try { Thread.sleep(1000); } catch(Exception e) { } } scroll.setValue(scroll.getMaximum()); } } /** doabort() will abort G4beamline. * Doesn't use Process.destroy() as that might refer to a shell. **/ void doAbortOLD() { try { if(osName.startsWith("Windows")) { // Some systems don't have taskkill, so try // them both, ignoring errors. try { Runtime.getRuntime().exec("tskill g4beamline"); } catch(Exception e1) { /* ignore error */ } Runtime.getRuntime().exec("taskkill /f /im g4beamline.exe"); } else { Runtime.getRuntime().exec("killall g4beamline"); } } catch(Exception e) { /* ignore error */ } } /** user close of the main window comes here **/ public void windowClosing(WindowEvent event) { doAbort(); if(wiredProcess != null) wiredProcess.destroy(); System.exit(0); } /** * runG4beamline() -- run the program with its environment set up * for portability, do everything of the g4bl script, here in Java. **/ Process runG4beamline() throws java.io.IOException { // verify input.file has been selected, and its directory if(currentDirectory == null || !currentDirectory.isDirectory() || inputFile == null || !inputFile.exists()) { JOptionPane.showMessageDialog(frame, "No input file selected.\n" + "Use the Browse button to select one."); return null; } // display data sets to the user, and verify their presence int nData=0; if(env.containsKey("G4ABLADATA")) { ++nData; System.out.printf("G4ABLADATA='%s'\n",env.get("G4ABLADATA")); } if(env.containsKey("G4LEDATA")) { ++nData; System.out.printf("G4LEDATA='%s'\n",env.get("G4LEDATA")); } if(env.containsKey("G4NEUTRONHPDATA")) { ++nData; System.out.printf("G4NEUTRONHPDATA='%s'\n",env.get("G4NEUTRONHPDATA")); } if(env.containsKey("G4NEUTRONXSDATA")) { ++nData; System.out.printf("G4NEUTRONXSDATA='%s'\n",env.get("G4NEUTRONXSDATA")); } if(env.containsKey("G4PIIDATA")) { ++nData; System.out.printf("G4PIIDATA='%s'\n",env.get("G4PIIDATA")); } if(env.containsKey("G4LEVELGAMMADATA")) { ++nData; System.out.printf("G4LEVELGAMMADATA='%s'\n",env.get("G4LEVELGAMMADATA")); } if(env.containsKey("G4RADIOACTIVEDATA")) { ++nData; System.out.printf("G4RADIOACTIVEDATA='%s'\n",env.get("G4RADIOACTIVEDATA")); } if(env.containsKey("G4REALSURFACEDATA")) { ++nData; System.out.printf("G4REALSURFACEDATA='%s'\n",env.get("G4REALSURFACEDATA")); } if(nData == 0) { JOptionPane.showMessageDialog(frame, "Geant4 data files not found"); return null; } // get library search paths (different for each OS) if(system.equals("Linux")) { String ld_library_path = env.get("LD_LIBRARY_PATH"); if(ld_library_path == null) ld_library_path = ""; ld_library_path = g4bl_dir + "/lib" + pathsep + ld_library_path; env.put("LD_LIBRARY_PATH",ld_library_path); System.out.printf("LD_LIBRARY_PATH=%s\n",ld_library_path); } else if(system.equals("Darwin")) { String dyld_library_path = env.get("DYLD_LIBRARY_PATH"); if(dyld_library_path == null) dyld_library_path = ""; dyld_library_path = g4bl_dir + "/lib" + pathsep + dyld_library_path; env.put("DYLD_LIBRARY_PATH",dyld_library_path); System.out.printf("DYLD_LIBRARY_PATH=%s\n",dyld_library_path); } else if(system.equals("WIN32")) { String path = env.get("PATH"); if(path == null) path = env.get("Path"); if(path == null) path = ""; path += pathsep + g4bl_dir + "/bin"; env.put("PATH",path); System.out.printf("PATH=%s\n",path); } // get the updated environment into an array for Runtime.exec() String[] envarray = new String[env.size()]; Iterator<String> iter = env.keySet().iterator(); int i = 0; while(iter.hasNext()) { String key = iter.next(); String val = env.get(key); envarray[i++] = key + "=" + val; } // get viewer, determine actual viewer String v = viewer; if(v.equals("Other")) v = otherViewerField.getText(); if(v.startsWith("Wired")) v = "Wired"; if(v.startsWith("wired")) v = "Wired"; if(v.equals("best")) { if(osName.startsWith("Windows")) v = "OIWin32"; else v = "OIX"; } needToRunWired = v.equals("Wired"); //System.out.printf("v=%s viewer=%s\n",v,viewer); // execute command, permitting spaces in g4bl_dir and inputFile String cmd = "/path/to/g4beamline /path/to/input.file viewer=" + v + " " + paramField.getText() + " "; // (ends with ' ') Vector<String> cmdv = new Vector<String>(); StringBuilder sb = new StringBuilder(); for(int pos=0; pos<cmd.length(); ++pos) { char c = cmd.charAt(pos); if(c == ' ') { if(sb.length() > 0) { cmdv.add(sb.toString()); sb.setLength(0); } continue; } if(c == '"' || c == '\'') { // quotes themselves are omitted ++pos; while(pos < cmd.length() && cmd.charAt(pos) != c) sb.append(cmd.charAt(pos++)); continue; } sb.append(c); } if(historootEventsField.isSelected()) { String d = inputFile.getParent(); if(d == null) d = "."; cmdv.add("eventcuts file='" + d + "/histo_event.txt'"); } cmdv.set(0,env.get("G4BEAMLINE")); cmdv.set(1,inputFile.getAbsolutePath()); String[] cmdarray = (String [])cmdv.toArray(new String[0]); System.out.printf("exec prog:%s\n",cmdarray[0]); for(i=1; i<cmdarray.length; ++i) System.out.printf(" arg%d:%s\n",i,cmdarray[i]); Process process = Runtime.getRuntime().exec(cmdarray,envarray, currentDirectory); if(process == null) JOptionPane.showMessageDialog(frame,"Program failed.\n" + "exec returned null"); return process; } /** * runWired() -- run the Wired program **/ Process runWired() throws java.io.IOException { Process process=null; String[] cmdarray=null; if(osName.startsWith("Windows")) { // Windows cmd is very finicky -- call just hangs, but // this cumbersome workaround using start seems to work. // NOTE: assumes Wired is installed into C:\Wired cmdarray = new String[8]; cmdarray[0] = "cmd"; cmdarray[1] = "/C"; cmdarray[2] = "start"; cmdarray[3] = "/B"; cmdarray[4] = "/DC:\\Wired\\bin"; cmdarray[5] = "wired.bat"; } else { cmdarray = new String[3]; cmdarray[0] = g4bl_dir + "/Wired/bin/wired"; } cmdarray[cmdarray.length-2] = "-file"; cmdarray[cmdarray.length-1] = inputFile.getParent() + "/G4Data0.heprep"; try { System.out.printf("runWired"); for(int i=0; i<cmdarray.length; ++i) System.out.printf(" %s",cmdarray[i]); System.out.printf("\n"); process = Runtime.getRuntime().exec(cmdarray); if(process == null) System.out.printf("runWired NULL\n"); } catch(java.io.IOException e) { System.out.printf("runWired exception %s\n",e.toString()); throw e; } return process; } /** deleteStaleFiles() will delete *.heprep in the directory **/ void deleteStaleFiles() { if(inputFile == null || !viewer.equals("none")) return; File dir = inputFile.getParentFile(); File[] list = dir.listFiles(); if(list != null) { for(int i=0; i<list.length; ++i) { if(list[i].getPath().endsWith(".heprep")) list[i].delete(); } } } /** outputSetup() will setup outputFile and outputArea. **/ void outputSetup() { if(outputArea == null) { if(helpScroll != null) frame.getContentPane().remove(helpScroll); helpScroll = null; helpPane = null; outputArea = new JTextArea(); outputArea.setEditable(false); outputArea.setFont(new Font("Monospaced",Font.PLAIN,12)); outputScroll = new JScrollPane(outputArea); scroll = outputScroll.getVerticalScrollBar(); frame.getContentPane().add(outputScroll, BorderLayout.CENTER); frame.validate(); } outputArea.setText(""); doScroll = true; if(outputFile != null) try { outputFile.close(); } catch(Exception e) { } try { outputFile = new BufferedWriter(new FileWriter( new File(currentDirectory,outputFileField.getText()))); } catch(Exception e) { JOptionPane.showMessageDialog(frame, "Cannot write Output File!"); } } /** outputClose() will close outputFile **/ void outputClose() { try { outputFile.close(); } catch(Exception e) { } outputFile = null; } /** outputLine() will output 1 line to the output file and outputArea. **/ synchronized void outputLine(String line) { doScroll = (scroll.getValue() >= scroll.getMaximum()-scroll.getVisibleAmount()-64 || scroll.getValue() >= lastScroll || line.startsWith("g4beamline: simulation aborted")); try { outputFile.write(line + "\n"); } catch(Exception e) { } int nLines = outputArea.getLineCount(); if(nLines > 20000) try { // when huge, just keep last lines outputArea.replaceRange( "-- DELETED (full output kept in output file) --\n", outputArea.getLineStartOffset(0), outputArea.getLineStartOffset(nLines-15000)); } catch(Exception e) { } outputArea.append(line + '\n'); if(doScroll) { scroll.setValue(scroll.getMaximum()); lastScroll = scroll.getValue(); } } /** internal class RunMonitorThread copies G4beamline stdout to * outputLine() and handles the finalization of output stuff when * G4beamline exits. This is the place where we know that gbeamline * has exited, so some rather surprising stuff is here (e.g. * runButton, other threads, ....). * (readline() will return null when G4beamline exits.) **/ class RunMonitorThread extends Thread { public RunMonitorThread() { } public void run() { if(g4beamlineProcess == null) return; // outputSetup() already called. runButton.setText("Abort"); try { StderrThread stderrThread = new StderrThread(); stderrThread.start(); StdinThread stdinThread = new StdinThread(); stdinThread.start(); g4blProcessID = ""; try { BufferedReader in = new BufferedReader( new InputStreamReader( g4beamlineProcess.getInputStream())); String line; while((line=in.readLine()) != null) { if(g4blProcessID.length() == 0 && line.startsWith("G4beamline Process ID")) g4blProcessID = line.split(" ")[3]; outputLine(line); } in.close(); } catch(Exception e) { System.err.println(e); outputArea.append(e.toString() + "\nProgram output is probably lost.\n\n"); } sleep(100); // 100 ms to give them a chance to finish stdinThread.interrupt(); stderrThread.interrupt(); } catch(Exception e) { System.err.println(e); outputArea.append(e.toString() + "\nProgram output is probably lost.\n\n"); } finally { try { if(g4beamlineProcess.waitFor() != 0 || aborted) { needToRunWired = false; if(!aborted) JOptionPane.showMessageDialog(frame, "Program Failed"); } if(aborted) outputArea.append("\n*** User Abort ***\n\n"); } catch(Exception e) { /* ignore exception */ } } if(g4beamlineProcess != null) g4beamlineProcess.destroy(); g4beamlineProcess = null; scroll.setValue(scroll.getMaximum()); outputClose(); if(needToRunWired) { outputArea.append("\n... Running the Wired3 event viewer ...\n"); // jump to bottom of outputArea for this message scroll.setValue(scroll.getMaximum()); try { wiredProcess=runWired(); } catch(Exception e) { } } outputArea.append("\n\n\n"); if(doScroll) { try { sleep(100); } catch(Exception e) { } scroll.setValue(scroll.getMaximum()); } runButton.setText(" Run "); } } /** internal class StderrThread copies G4beamline stderr to outputLine() * (readline() will return null when G4beamline exits.) **/ class StderrThread extends Thread { public StderrThread() { } public void run() { if(g4beamlineProcess == null) return; BufferedReader in=null; try { in = new BufferedReader( new InputStreamReader(g4beamlineProcess.getErrorStream())); String line; while((line=in.readLine()) != null) { outputLine(line); } } catch(Exception e) { System.err.println(e); outputArea.append(e.toString() + "\nProgram output is probably lost.\n\n"); } try { if(in != null) in.close(); } catch(Exception e) { } } }; /** internal class StdinThread writes "/run/beamOn N" to stdin. **/ class StdinThread extends Thread { public StdinThread() { } public void run() { if(g4beamlineProcess == null) return; BufferedWriter stdin=null; try { int nViewerEvents = (Integer)nViewerEventsField.getValue(); int nRuns = (Integer)nViewerRunsField.getValue(); stdin = new BufferedWriter( new OutputStreamWriter( g4beamlineProcess.getOutputStream())); for(int i=0; i<nRuns; ++i) { stdin.write("/run/beamOn "+nViewerEvents); stdin.newLine(); } stdin.write("exit"); stdin.newLine(); } catch(Exception e) { System.err.println("Error in StdinThread: " + e + "\n"); } try { if(stdin != null) stdin.close(); } catch(Exception e) { } } } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. **/ private static void createAndShowGUI(String[] args) { // Use window system decorations. Uncomment for LookAndFeel //JFrame.setDefaultLookAndFeelDecorated(true); new G4blGui(args); } /** * main program -- create and display GUI **/ static String[] mainArgs; public static void main(String[] args) { mainArgs = args; System.out.printf("This java console window gets error messages and" +" status information.\nIt can usually be ignored.\n"); //Schedule a job for the event-dispatching thread: //creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(mainArgs); } }); } }