/* 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();
}});
}
}