package simple.escp.swing;
import simple.escp.data.DataSource;
import simple.escp.data.EmptyDataSource;
import simple.escp.data.JsonDataSource;
import simple.escp.json.JsonTemplate;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.PlainDocument;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
/**
* A simple editor that uses template and data source in form of JSON string.
*/
public class Editor extends JFrame {
private static final int DEFAULT_FONT_SIZE = 12;
private static final Color EDITOR_BACKGROUND_COLOR = new Color(240, 240, 240);
public static final int TAB_SIZE = 4;
public static final double SPLIT_WEIGHT = 0.85;
private Font editorFont;
private JTabbedPane tabbedPane;
private PrintPreviewPane printPreviewPane;
private JEditorPane templateEditor;
private JEditorPane dataSourceEditor;
private JTextArea consoleOutput;
private JButton clearConsoleButton;
/**
* Create this <code>Editor</code>.
*/
public Editor() {
super("simple-escp Editor");
try {
editorFont = Font.createFont(Font.TRUETYPE_FONT, Thread.currentThread().getContextClassLoader().
getResourceAsStream("DejaVuSansMono.ttf")).deriveFont(Font.PLAIN, DEFAULT_FONT_SIZE);
} catch (FontFormatException | IOException e) {
editorFont = new Font(Font.MONOSPACED, Font.PLAIN, DEFAULT_FONT_SIZE);
}
printPreviewPane = new PrintPreviewPane();
templateEditor = createEditor();
dataSourceEditor = createEditor();
tabbedPane = new JTabbedPane();
tabbedPane.addChangeListener(new TabbedPaneChange());
tabbedPane.addTab("Template Editor", new JScrollPane(templateEditor));
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.addTab("Data Source Editor", new JScrollPane(dataSourceEditor));
tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);
tabbedPane.addTab("Preview", printPreviewPane);
tabbedPane.setMnemonicAt(2, KeyEvent.VK_3);
consoleOutput = new JTextArea();
consoleOutput.setEditable(false);
ErrorConsoleStream consoleStream = new ErrorConsoleStream();
PrintStream consolePrintStream = null;
try {
consolePrintStream = new PrintStream(consoleStream, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
JOptionPane.showMessageDialog(null, "Can't create console stream: " + e.getMessage());
}
System.setOut(consolePrintStream);
System.setErr(consolePrintStream);
JPanel consoleArea = new JPanel();
consoleArea.setLayout(new BorderLayout());
JPanel consoleArea_buttons = new JPanel();
consoleArea_buttons.setLayout(new FlowLayout(FlowLayout.LEADING));
consoleArea_buttons.add(new JLabel("Console Output "));
clearConsoleButton = new JButton("Clear");
clearConsoleButton.addActionListener(new ClearConsoleAction());
consoleArea_buttons.add(clearConsoleButton);
consoleArea.add(consoleArea_buttons, BorderLayout.PAGE_START);
consoleArea.add(new JScrollPane(consoleOutput), BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tabbedPane, consoleArea);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(SPLIT_WEIGHT);
setLayout(new BorderLayout());
add(splitPane, BorderLayout.CENTER);
}
/**
* Create editor.
*
* @return an instance of <code>JEditorPane</code>.
*/
private JEditorPane createEditor() {
JEditorPane editor = new JEditorPane();
editor.setFont(editorFont);
editor.getDocument().putProperty(PlainDocument.tabSizeAttribute, TAB_SIZE);
UIDefaults defaults = new UIDefaults();
defaults.put("EditorPane[Enabled].backgroundPainter", EDITOR_BACKGROUND_COLOR);
editor.putClientProperty("Nimbus.Overrides", defaults);
editor.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
editor.setBackground(EDITOR_BACKGROUND_COLOR);
return editor;
}
/**
* Everything starts from this method.
*
* @param args the arguments passed from command line.
*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Can't use Nimbus Look And Feel: " + e.getMessage());
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
Editor editor = new Editor();
editor.pack();
editor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
editor.setVisible(true);
editor.setExtendedState(JFrame.MAXIMIZED_BOTH);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
});
}
/**
* This is an event handler that will refresh the preview content when user switched to that tab.
*/
private class TabbedPaneChange implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
if (tabbedPane.getSelectedIndex() == 2) {
JsonTemplate template = new JsonTemplate(templateEditor.getText());
String jsonSource = dataSourceEditor.getText().trim();
DataSource ds = "".equals(jsonSource) ? new EmptyDataSource() : new JsonDataSource(jsonSource);
printPreviewPane.display(template, ds);
}
}
}
/**
* This <code>OutputStream</code> will capture stream and display it in text area.
*/
private class ErrorConsoleStream extends OutputStream {
private StringBuffer buffer = new StringBuffer();
@Override
public void write(int b) throws IOException {
buffer.append((char) b);
}
@Override
public void flush() throws IOException {
consoleOutput.append(buffer.toString());
buffer = new StringBuffer();
}
}
/**
* This action will clear the content of console text area.
*/
private class ClearConsoleAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
consoleOutput.setText(null);
}
}
}