/* MEPer.java * This file is part of source files of MEPer. * It create the main window and starts the program. * * @author Shengjun Pan */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.text.*; import java.io.*; public class MEPer extends JFrame { static int initWidth=1000; static int initHeight=618; boolean ispc; JToolBar toolbar; JTextPane editor; JLabel graph; JLabel statusLabel; JButton saveButton; JButton previewButton; JButton helpButton; Action saveAction; Action previewAction; Action helpAction; JDialog helpWindow=null; EditorFilter editorFilter; String workingDir; static String helpTitle = "Metapost Editor and Previewer v1.0"; static String dirName= "MetaPostPreview"; static String metapost = "mpost -interaction=nonstopmode preview.mp end"; static String convert = "convert preview.eps preview.png"; static String ghostscript = " -dBATCH -dNOPAUSE -dQUIET"+ " -dEPSCrop -dEPSFitPage -dGraphicsAlphaBits=4 -dTextAlphaBits=4"+ " -sDEVICE=pngalpha -sOutputFile=preview.png preview.eps"; private void saveFile() { try { FileWriter outputStream = new FileWriter(workingDir+File.separator+"preview.mp"); outputStream.write(editor.getText()); outputStream.close(); saveButton.setEnabled(false); } catch (Throwable t){} } private void consumeRuntime(Process proc) { final BufferedReader errorConsumer = new BufferedReader(new InputStreamReader(proc.getErrorStream())); final BufferedReader outputConsumer = new BufferedReader(new InputStreamReader(proc.getInputStream())); Thread errorThread = new Thread() { public void run() { String nextline; try { while ( (nextline = errorConsumer.readLine()) != null); } catch (Throwable t){} }}; Thread outputThread = new Thread(){ public void run() { String nextline; try { while ( (nextline = outputConsumer.readLine()) != null); } catch (Throwable t){} }}; errorThread.start(); outputThread.start(); } private void createActions(){ saveAction = new AbstractAction () { public void actionPerformed(ActionEvent e) { saveFile(); statusLabel.setText("preview.mp saved in directory: "+ workingDir); editor.requestFocus(); }}; previewAction = new AbstractAction(){ public void actionPerformed(ActionEvent e) { saveFile(); SwingUtilities.invokeLater(new Runnable () { public void run() { try { File previewmp= new File(workingDir+File.separator+"preview.mp"); File preview1= new File(workingDir+File.separator+"preview.1"); File previeweps= new File(workingDir+File.separator+"preview.eps"); File previewpng= new File(workingDir+File.separator+"preview.png"); (new File(workingDir+File.separator+"preview.1")).delete(); (new File(workingDir+File.separator+"preview.eps")).delete(); (new File(workingDir+File.separator+"preview.png")).delete(); File dir = new File(workingDir); Process proc=null; if(previewmp.exists()) { statusLabel.setText("Generating preview image..."); proc = Runtime.getRuntime().exec(metapost,null,dir); if(proc != null) { consumeRuntime(proc); proc.waitFor(); proc = null; } else { statusLabel.setText("Error on running metapost."); return; } } else { statusLabel.setText("Can't find file: preview.mp"); return; } if(preview1.exists()) { preview1.renameTo(previeweps); statusLabel.setText("preview.1 renamed to preview.eps."); } else { statusLabel.setText("Cant' find file: preview.1"); return; } if(previeweps.exists()) { // try convert proc = Runtime.getRuntime().exec(convert, null,dir); if(proc != null) { consumeRuntime(proc); proc.waitFor(); proc=null; } else statusLabel.setText("Error on running ImageMagick." + "Try ghostscript..."); // try ghostscript if(!previewpng.exists()) { proc = Runtime.getRuntime().exec(ghostscript, null,dir); if(proc != null) { consumeRuntime(proc); proc.waitFor(); proc=null; } else { statusLabel.setText("Error on running ghostscript."); return; } } } else { statusLabel.setText("Can't find file: preview.eps"); return; } if(previewpng.exists()) { statusLabel.setText("Reloading preview image..."); ((ImageIcon)graph.getIcon()).getImage().flush(); ImageIcon img = new ImageIcon(workingDir+File.separator+"preview.png"); graph.setIcon(img); graph.repaint(); statusLabel.setText(" preview.[mp|eps|png] saved in directory: "+ workingDir); } else { statusLabel.setText("Can't find file: preview.png"); return; } } catch (Throwable t) {} editor.requestFocus(); }}); }}; helpAction = new AbstractAction () { public void actionPerformed(ActionEvent e) { if(helpWindow==null){ helpWindow = new JDialog(); JTextArea infoPane = new JTextArea(); infoPane.setEditable(false); infoPane.setAlignmentX(Component.CENTER_ALIGNMENT); //URL readmeURL = this.getClass().getResource("README.txt"); try { String nextline; InputStream is = this.getClass().getResourceAsStream("README.txt"); InputStreamReader isr = new InputStreamReader(is); BufferedReader inputStream = new BufferedReader(isr); nextline = inputStream.readLine(); infoPane.getDocument().insertString(infoPane.getDocument().getLength(), nextline, null); while(!(nextline = inputStream.readLine()).equals(null)) infoPane.getDocument().insertString(infoPane.getDocument().getLength(), "\n"+nextline, null); inputStream.close(); } catch(Throwable t) {} Container helpPane = helpWindow.getContentPane(); helpPane.setLayout(new BoxLayout(helpPane,BoxLayout.Y_AXIS)); JLabel titleLabel = new JLabel(helpTitle); titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); helpPane.add(titleLabel); infoPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); helpPane.add(infoPane); JButton closeButton = new JButton(new AbstractAction() { public void actionPerformed(ActionEvent e) { helpWindow.setVisible(false); editor.requestFocus(); }}); closeButton.setText("Close"); closeButton.setAlignmentX(Component.CENTER_ALIGNMENT); helpPane.add(closeButton); helpWindow.addWindowListener( new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { helpWindow.setVisible(false); editor.requestFocus(); }}); helpWindow.pack(); } int topX, topY; topX = (MEPer.this.getWidth()-helpWindow.getWidth())/2; topY = (MEPer.this.getHeight()-helpWindow.getHeight())/3; Point helpLocation =MEPer.this.getLocation(); helpLocation.translate(topX, topY); helpWindow.setLocation(helpLocation); helpWindow.setVisible(true); } }; } public MEPer() { String osName=System.getProperty("os.name").toLowerCase(); ispc = osName.indexOf("win")!=-1; ghostscript = (ispc?"gsWin32":"gs") + ghostscript; workingDir = System.getProperty("user.dir"); File newdir = new File(System.getProperty("user.home") + File.separator+ dirName); if(newdir.exists() || newdir.mkdir()) { workingDir = newdir.getAbsolutePath(); System.setProperty("user.dir", workingDir); } // Create a toolbar toolbar = new JToolBar(); createActions(); saveButton = new JButton(saveAction); saveButton.setText("Save"); saveButton.setToolTipText("Ctr+S"); toolbar.add(saveButton); previewButton = new JButton(previewAction); previewButton.setText("Preview"); previewButton.setToolTipText("Ctr+P"); toolbar.add(previewButton); toolbar.add(Box.createHorizontalGlue()); helpButton = new JButton(helpAction); helpButton.setText("Help"); toolbar.add(helpButton); statusLabel = new JLabel(); statusLabel.setText("Working directory: "+System.getProperty("user.dir")); statusLabel.setFont(new Font(Font.SERIF,Font.PLAIN,12)); //Create a text pane for the editing area editor = new JTextPane(); editorFilter = new EditorFilter(editor, saveButton); ((AbstractDocument)editor.getDocument()).setDocumentFilter(editorFilter); editor.getInputMap().put(KeyStroke.getKeyStroke("ctrl S"), "save"); editor.getInputMap().put(KeyStroke.getKeyStroke("ctrl P"), "preview"); editor.getActionMap().put("save", saveAction); editor.getActionMap().put("preview", previewAction); /* */ // load file "preview.mp" into editor BufferedReader inputStream; String mpName = workingDir+File.separator+"preview.mp"; try { boolean loadTemplate = false; if ((new File(mpName)).exists()) inputStream = new BufferedReader(new FileReader(mpName)); else{ statusLabel.setText("Can't load preview.mp; using template instead."); loadTemplate=true; InputStream is = this.getClass().getResourceAsStream("template.mp"); InputStreamReader isr = new InputStreamReader(is); inputStream = new BufferedReader(isr); } String nextline; nextline = inputStream.readLine(); editor.getDocument().insertString(editor.getDocument().getLength(), nextline, null); while(!((nextline = inputStream.readLine())==null)) editor.getDocument().insertString(editor.getDocument().getLength(), "\n"+nextline, null); inputStream.close(); if(loadTemplate) editor.setCaretPosition(editor.getDocument().getLength()-12); } catch(Throwable t) {} saveButton.setEnabled(false); JScrollPane editorScrollPane = new JScrollPane(editor); graph = new JLabel(); graph.setOpaque(true); graph.setBackground(Color.WHITE); ImageIcon img = new ImageIcon(workingDir+File.separator+"preview.png"); graph.setIcon(img); graph.setHorizontalAlignment(SwingConstants.CENTER); graph.setVerticalAlignment(SwingConstants.CENTER); JScrollPane imagePane = new JScrollPane(graph); editorScrollPane.setPreferredSize(new Dimension(initWidth/2,initHeight)); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, editorScrollPane, imagePane); this.getContentPane().add(toolbar,BorderLayout.PAGE_START); this.getContentPane().add(splitPane, BorderLayout.CENTER); this.getContentPane().add(statusLabel,BorderLayout.PAGE_END); addWindowListener( new WindowAdapter() { @Override public void windowOpened( WindowEvent e ){ editor.requestFocus();} @Override public void windowClosing(WindowEvent e) { if( saveButton.isEnabled()) { int response = JOptionPane.showConfirmDialog( MEPer.this, "Save file before exit?", "Closing...", JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) saveFile(); }} }); } private static void initialize() { MEPer mainFrame = new MEPer(); mainFrame.setTitle("MetaPost Editor and Previewer"); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int topX = (int)((screenSize.getWidth()-initWidth)/2); if(topX<0) topX=0; int topY =(int)((screenSize.getHeight()-initHeight)/3); if(topY<0) topY=0; mainFrame.setPreferredSize(new Dimension(initWidth,initHeight)); mainFrame.setLocation(topX, topY); mainFrame.pack(); mainFrame.setVisible(true); } public static void main(String args[]) { SwingUtilities.invokeLater(new Runnable() { public void run() { initialize(); }}); } }