/*
* EditorWindow.java
* $Date$
* $Author$
* $Revision$
*/
package cz.tkubin.editor;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
/**
*
* @author cathack
*/
public class EditorWindow extends JFrame {
protected static final String DEFAULT_WINDOW_TITLE = "Text editor";
protected static final String NO_FILENAME = "(new document)";
protected static final String DOC_CHANGED_TITLE_SUFFIX = " *";
protected static final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12);
protected static final int DEFAULT_ROWS_COUNT = 0;
protected static final int DEFAULT_COLUMNS_COUNT = 0;
protected static final int BORDER = 10;
protected static final boolean DEFAULT_WRAP_TEXT = false;
private JTextArea textArea;
private JCheckBoxMenuItem cWrap;
private JFileChooser chooser;
private File currentFile;
private boolean documentOpen;
private boolean documentChanged;
public EditorWindow() {
super(DEFAULT_WINDOW_TITLE);
// GUI
this.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
actionQuit(true);
}
});
this.setPreferredSize(new Dimension(800, 600));
//contents
Container pane = this.getContentPane();
pane.setLayout(new BorderLayout(BORDER, BORDER));
textArea = new JTextArea(DEFAULT_ROWS_COUNT, DEFAULT_COLUMNS_COUNT);
textArea.setFont(DEFAULT_FONT);
textArea.addKeyListener(new KeyAdapter() {
@Override public void keyTyped(KeyEvent e) {
setDocumentChanged(true);
}
});
pane.add(new JScrollPane(textArea));
setJMenuBar(createMenuBar());
pack();
// filechooser
chooser = new JFileChooser();
chooser.setFileFilter(new FileFilter() {
private static final String EXTENSION = ".txt";
@Override public boolean accept(File pathname) {
return (pathname.isDirectory() || pathname.getName().endsWith(EXTENSION));
}
@Override public String getDescription() {
return "Text file (*" + EXTENSION + ")";
}
});
// init
setCurrentFile(null);
setDocumentOpen(false);
documentChanged = false;
}
private JMenuBar createMenuBar() {
JMenuBar mb = new JMenuBar();
// File
JMenu menuFile = new JMenu("File");
menuFile.setMnemonic('F');
// File -> New
JMenuItem mNew = new JMenuItem("New");
mNew.setMnemonic('N');
mNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
mNew.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionNew();
}
});
menuFile.add(mNew);
// File -> Open
JMenuItem mOpen = new JMenuItem("Open ...");
mOpen.setMnemonic('O');
mOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
mOpen.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionOpen();
}
});
menuFile.add(mOpen);
// File -> Save
JMenuItem mSave = new JMenuItem("Save");
mSave.setMnemonic('S');
mSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
mSave.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionSave();
}
});
menuFile.add(mSave);
// File -> Save as
JMenuItem mSaveAs = new JMenuItem("Save as ...");
mSaveAs.setMnemonic('a');
mSaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK));
mSaveAs.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionSaveAs();
}
});
menuFile.add(mSaveAs);
// File -> Close
JMenuItem mClose = new JMenuItem("Close");
mClose.setMnemonic('C');
mClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.CTRL_MASK));
mClose.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionClose();
}
});
menuFile.add(mClose);
menuFile.addSeparator();
// File -> Quit
JMenuItem mQuit = new JMenuItem("Quit");
mQuit.setMnemonic('Q');
mQuit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
mQuit.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionQuit();
}
});
menuFile.add(mQuit);
// View
JMenu menuView = new JMenu("View");
menuView.setMnemonic('V');
// View -> Wrap text
cWrap = new JCheckBoxMenuItem("Wrap text", DEFAULT_WRAP_TEXT);
cWrap.setMnemonic('W');
cWrap.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.CTRL_MASK));
cWrap.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
actionToggleWrap();
}
});
menuView.add(cWrap);
mb.add(menuFile);
mb.add(menuView);
return mb;
}
protected void setCurrentFile(File file) {
this.currentFile = file;
resetWindowTitle();
}
protected String getCurrentFileName() {
if (currentFile == null)
return NO_FILENAME;
else
return currentFile.getName();
}
protected void setDocumentChanged(boolean changed) {
if (this.documentChanged != changed) {
this.documentChanged = changed;
resetWindowTitle();
}
else
this.documentChanged = changed;
}
protected void setDocumentOpen(boolean open) {
this.documentOpen = open;
this.textArea.setVisible(open);
this.textArea.setEditable(open);
resetWindowTitle();
}
protected void resetWindowTitle() {
if (documentOpen)
this.setTitle(DEFAULT_WINDOW_TITLE + " - " + getCurrentFileName() + (documentChanged ? DOC_CHANGED_TITLE_SUFFIX : ""));
else
this.setTitle(DEFAULT_WINDOW_TITLE);
}
protected void showErrorDialog(Exception e) {
JOptionPane.showMessageDialog(this, e.getMessage(), e.getClass().getName(), JOptionPane.ERROR_MESSAGE);
}
private int showYesNoCancelDialog(String message, String title) {
Object[] options = {"Yes", "No", "Cancel"};
return JOptionPane.showOptionDialog(this, message, title,
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[2]);
}
private int showYesNoDialog(String message, String title) {
Object[] options = {"Yes", "No"};
return JOptionPane.showOptionDialog(this, message, title,
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
}
private boolean testChangedDocumentClosing() {
return testChangedDocumentClosing(false);
}
private boolean testChangedDocumentClosing(boolean mustResponse) {
if (documentOpen && documentChanged) {
int response;
if (mustResponse)
response = showYesNoDialog(getCurrentFileName() + " isn't saved. Do you want to save it?", "File isn't saved");
else
response = showYesNoCancelDialog(getCurrentFileName() + " isn't saved. Do you want to save it?", "File isn't saved");
if (response == 0)
actionSave();
if (response == 2)
return true;
}
return false;
}
protected File openFileDialog() {
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
return chooser.getSelectedFile();
else
return null;
}
protected File saveFileDialog() {
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
return chooser.getSelectedFile();
else
return null;
}
private void openDocument(File file) throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuffer sb = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
if (sb.length() > 0)
sb.deleteCharAt(sb.length() - 1);
textArea.setText(sb.toString());
setDocumentOpen(true);
setCurrentFile(file);
setDocumentChanged(false);
}
private void saveDocument(File file) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
String[] lines = textArea.getText().split("\\n");
boolean firstLine = true;
for (String line : lines) {
if (firstLine)
firstLine = false;
else
writer.newLine();
writer.write(line);
}
writer.close();
setDocumentChanged(false);
}
protected void actionNew() {
if (testChangedDocumentClosing())
return;
textArea.setText("");
setCurrentFile(null);
setDocumentOpen(true);
setDocumentChanged(false);
}
protected void actionOpen() {
if (testChangedDocumentClosing())
return;
File file = openFileDialog();
if (file == null)
return;
try {
openDocument(file);
} catch (FileNotFoundException ex) {
showErrorDialog(ex);
} catch (IOException ex) {
showErrorDialog(ex);
}
}
protected void actionSave() {
if (documentOpen) {
if (currentFile == null) {
actionSaveAs();
return;
}
if (documentChanged) {
try {
saveDocument(currentFile);
} catch (IOException ex) {
showErrorDialog(ex);
}
}
}
}
protected void actionSaveAs() {
if (documentOpen) {
File file = saveFileDialog();
if (file == null)
return;
try {
saveDocument(file);
setCurrentFile(file);
} catch (IOException ex) {
showErrorDialog(ex);
}
}
}
protected void actionClose() {
if (documentOpen) {
if (testChangedDocumentClosing())
return;
setCurrentFile(null);
setDocumentOpen(false);
setDocumentChanged(false);
}
}
protected void actionQuit() {
actionQuit(false);
}
protected void actionQuit(boolean mustResponse) {
if (testChangedDocumentClosing(mustResponse))
return;
System.exit(0);
}
protected void actionToggleWrap() {
textArea.setLineWrap(cWrap.getState());
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
new EditorWindow().setVisible(true);
}
});
}
}