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