Saturday, November 23, 2013

How to create a text editor like Notepad in Java

I previously posted on how to code using the Java programming language by creating a Tic-Tac-Toe game, complete with basic AI as computer opponent and a two-player mode. This time, let me show you how to code a simple text editor that functions like the Microsoft Notepad for Windows. The source code is contained in one .java file, containing all the necessary lines and class imports needed to launch the functions and graphical user interface. While the code is also shown below, I also made the source code (.java) and the compiled runnable program (.jar) themselves available for download.

Notepad using Java

Notepad in Java features

  • Menu bar for File, Edit, and Help
  • Ability to create a new notepad
  • Save and load a .TXT file.
  • Edit texts with cut, copy, and paste functions
  • About dialog box
  • Resizable window
  • Keyboard shortcuts for several functions

As seen in the features above, our Java copy does not completely imitate everything that Notepad does. For instance, there’s no option to change Font settings, enable/disable Word Wrap, display/hide the status bar (for showing line and column position of the text cursor), and a help and support window for a comprehensive features lists of the text editor. Though present, the Undo function is only for show in our Java program and won’t revert any recent actions done by the user. Other differences are also present, many of which are subtle.

Notepad in Java (source code)

This program has been compiled using Eclipse SDK.

import javax.swing.*;
 
import java.awt.*;
import java.awt.event.*;
import java.util.Scanner;
import java.io.*;
import javax.swing.text.DefaultEditorKit;
 
 
public class Notepad extends JFrame implements ActionListener {
    private JTextArea textArea = new JTextArea();
    private JScrollPane areaScrollPane;
    private JMenuBar menuBar = new JMenuBar();    
    private JMenu file = new JMenu();
    private JMenu edit = new JMenu();
    private JMenu format = new JMenu();
    private JMenu view = new JMenu();
    private JMenu help = new JMenu();
    private JMenuItem openFile = new JMenuItem();
    private JMenuItem saveFile = new JMenuItem();
    private JMenuItem close = new JMenuItem();
    private JMenuItem newFile = new JMenuItem();
    private JMenuItem undo = new JMenuItem();
    private JMenuItem cut = new JMenuItem(new DefaultEditorKit.CutAction());
    private JMenuItem copy = new JMenuItem(new DefaultEditorKit.CopyAction());
    private JMenuItem paste = new JMenuItem(new DefaultEditorKit.PasteAction());
    private JMenuItem delete = new JMenuItem();
    private JMenuItem wordwrap = new JMenuItem();
    private JMenuItem about = new JMenuItem();
 
    public Notepad() {
        this.setSize(500, 300);
        this.setTitle("Java Notepad");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.textArea.setFont(new Font("Century Gothic", Font.BOLD, 12));
        this.textArea.setDragEnabled(true);
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(textArea);
        this.areaScrollPane = new JScrollPane(textArea);
        this.areaScrollPane.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        this.areaScrollPane.setHorizontalScrollBarPolicy(
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        this.areaScrollPane.setPreferredSize(new Dimension(250, 250));
        this.getContentPane().add(areaScrollPane);
 
        this.setJMenuBar(this.menuBar);
        this.menuBar.add(this.file);
        this.menuBar.add(this.edit);
        this.menuBar.add(this.help);
 
        this.file.setText("File");
        this.edit.setText("Edit");
        this.format.setText("Format");
        this.view.setText("View");
        this.help.setText("Help");
 
        this.newFile.setText("New");
        this.newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        this.newFile.addActionListener(this);
        this.newFile.setMnemonic(KeyEvent.VK_N);
        this.file.add(this.newFile);
 
        this.openFile.setText("Open");
        this.openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
        this.openFile.addActionListener(this);
        this.openFile.setMnemonic(KeyEvent.VK_O);
        this.file.add(this.openFile);
 
        this.saveFile.setText("Save");
        this.saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
        this.saveFile.addActionListener(this);
        this.saveFile.setMnemonic(KeyEvent.VK_S);
        this.file.add(this.saveFile);
 
        this.close.setText("Close");
        this.close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.CTRL_MASK));
        this.close.setMnemonic(KeyEvent.VK_F4);
        this.close.addActionListener(this);
        this.file.add(this.close);
 
        this.undo.setText("Undo");        
        this.undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
        this.undo.setMnemonic(KeyEvent.VK_U);
        this.undo.addActionListener(this);
        this.edit.add(this.undo);
        
        this.cut.setText("Cut");
        this.cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
        this.cut.setMnemonic(KeyEvent.VK_T);
        this.edit.add(this.cut);
 
        this.copy.setText("Copy");
        this.copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
        this.copy.setMnemonic(KeyEvent.VK_C);
        this.copy.addActionListener(this);
        this.edit.add(this.copy);
 
        this.paste.setText("Paste");
        this.paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK));
        this.paste.setMnemonic(KeyEvent.VK_P);
        this.paste.addActionListener(this);
        this.edit.add(this.paste);
 
        this.about.setText("Authors");
        this.about.addActionListener(this);
        this.help.add(this.about);
    }
 
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == this.close)
            this.dispose();
 
        else if (e.getSource() == this.openFile) {
            JFileChooser open = new JFileChooser();
            int option = open.showOpenDialog(this);
            if (option == JFileChooser.APPROVE_OPTION) {
                this.textArea.setText("");
                try {
                    Scanner scan = new Scanner(new FileReader(open
                            .getSelectedFile().getPath()));
                    while (scan.hasNext())
                        this.textArea.append(scan.nextLine() + "\n");
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
 
        else if (e.getSource() == this.saveFile) {
            JFileChooser save = new JFileChooser();
            int option = save.showSaveDialog(this);
            if (option == JFileChooser.APPROVE_OPTION) {
                try {
                    BufferedWriter out = new BufferedWriter(new FileWriter(save
                            .getSelectedFile().getPath()));
                    out.write(this.textArea.getText());
                    out.close();
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
 
        else if (e.getSource() == this.newFile) {
            JOptionPane jp = new JOptionPane();
            Object[] options = { "Save", "Don't Save", "Cancel" };
            int button = jp.showOptionDialog(null,
                    "Do you want to save changes to" + getTitle(), "Notepad",
                    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
                    null, options, options[0]);
            if (button == 0) {
                JFileChooser newFile = new JFileChooser();
                int option = newFile.showSaveDialog(this);
                if (option == JFileChooser.APPROVE_OPTION) {
                    try {
                        BufferedWriter out = new BufferedWriter(new FileWriter(
                                newFile.getSelectedFile().getPath()));
                        out.write(this.textArea.getText());
                        out.close();
                    } catch (Exception ex) {
                        System.out.println(ex.getMessage());
                    }
                }
            } else if (button == 1) {
                textArea.setText(null);
            } else if (button == 2) {
 
            }
        } else if (e.getSource() == this.about) {
            JOptionPane jp = new JOptionPane();
            jp.showMessageDialog(null,
                    "Created by Conan Hughes");
        }
    }
 
    public static void main(String args[]) {
        Notepad app = new Notepad();
        app.setVisible(true);
    }
}