Simple Text Editor


Today, early in the morning I made my first notepad clone... with less options and solutions !
So today I am going to show you ! How to make a less of a notepad in java !

Packages we will need
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FileReader;
import java.io.FileWriter;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.text.DefaultEditorKit;

The class
public class NotedPad extends JFrame {

Base variables.
        private static final long serialVersionUID = 1L;

private JTextArea area = new JTextArea();
private JFileChooser dialog = new JFileChooser(System.getProperty("user.dir"));
private String currentFile = "Untitled";
private boolean changed = false;

Our JTextArea will be the area where you can write documents and etc...
Also if you are unfamiliar with JFileChooser, then try to read more about the swing lib in Javas API page. Also by changed it will represent our flag of when things in our area changes.

Constructor Part #1
        public NotedPad() {
area.setFont(new Font("Monospaced", Font.PLAIN, 12));
JScrollPane scroll = new JScrollPane(area, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
add(scroll, BorderLayout.CENTER);

JMenuBar mBar = new JMenuBar();
setJMenuBar(mBar);
JMenu mFile = new JMenu("File");
JMenu mEdit = new JMenu("Edit");
mBar.add(mFile);
mBar.add(mEdit);
So here we are our area and the toolbar we will use... with JScrollPane we will be able to view a bit more of our text and area...Most likely as anything else :>
Constructor Part #2
                mFile.add(New);
mFile.add(Open);
mFile.add(Save);
mFile.add(Quit);
mFile.add(SaveAs);
mFile.addSeparator();

for (int i=0; i<4; i++) {
mFile.getItem(i).setIcon(null);

mEdit.add(Cut);
mEdit.add(Copy);
mEdit.add(Past);

mEdit.getItem(0).setText("Cut");
mEdit.getItem(1).setText("Copy");
mEdit.getItem(2).setText("Past");
Now by adding methods and arguments we haven't implemented from the beginning will of course complain in an active IDE...However fear not we will come to the point what New/Open/Save/Quit/SaveAs are...
While adding we also position them in a correct order with our for loop and set every icon to null.
Constructor Part #3
                        JToolBar tool = new JToolBar();
add(tool, BorderLayout.NORTH);
tool.add(New);
tool.add(Open);
tool.add(Save);
tool.addSeparator();

JButton btnCut = tool.add(Cut), btnCopy = tool.add(Copy), btnPast = tool.add(Past);
btnCut.setText(null); btnCut.setIcon(new ImageIcon(this.getClass().getResource("cut.gif")));
btnCopy.setText(null); btnCopy.setIcon(new ImageIcon(this.getClass().getResource("copy.gif")));
btnPast.setText(null); btnPast.setIcon(new ImageIcon(this.getClass().getResource("paste.gif")));

Save.setEnabled(false);
SaveAs.setEnabled(false);

setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
area.addKeyListener(k1);
setTitle(currentFile);
setSize(400, 400);
setLocationRelativeTo(this);
setVisible(true);
}
}
We are currently adding our functions and giving some proper icons for our toolbar items ! Note we are adding in icons and giving null text to each item.
Our Save and SaveAs functions will represent the standard every time we launch the application...hence it's false...

Listener
        private KeyListener k1 = new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
changed = true;
Save.setEnabled(true);
SaveAs.setEnabled(true);
}
};
Now here we have our listener which will listen when any key is pressed thus making the changed statement true and allowing us to save or saveas.Quite good right?

Action #0
        Action New = new AbstractAction("New") {
private static final long serialVersionUID = 1L;

@Override
public void actionPerformed(ActionEvent evt) {
area.setText(null);
}
};
Action #1
        Action Open = new AbstractAction("Open", new ImageIcon(this.getClass().getResource("open.gif"))) {
private static final long serialVersionUID = 1L;

@Override
public void actionPerformed(ActionEvent evt) {
saveOld();
if (dialog.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
readInFile(dialog.getSelectedFile().getAbsolutePath());
}
SaveAs.setEnabled(true);
}
};
By pressing on our ItemIcon we will trigger an Action(Abstract one). Also by triggering the Icon action we will be able to preserve the moment of our text. Resulting us to be able choose where to save and use it later

Action #2
       Action Save = new AbstractAction("Save", new ImageIcon(this.getClass().getResource("save.gif"))) {
private static final long serialVersionUID = 1L;

@Override
public void actionPerformed(ActionEvent evt) {
if (!currentFile.equals("Untitled"))
saveFile(currentFile);
else
saveFileAs();
}
};
So here is our save function. We will be able to save our current file. So by playing along I thought like this. If the currentFile doesn't equal to Untitled then just save it as it's called... else save as thus allowing the sure to give it a title 

Action #3
        Action SaveAs = new AbstractAction("Save As...") {
private static final long serialVersionUID = 1L;

@Override
public void actionPerformed(ActionEvent evt) {
saveFileAs();
}
};
Nothing much with this action. We are just allowing the user to saveAs...thus giving it a title...

Action #4
        Action Quit = new AbstractAction("Quit") {
private static final long serialVersionUID = 1L;

@Override
public void actionPerformed(ActionEvent evt) {
saveOld();
System.exit(0); // for close this frame
}
};
A quit function is needed also we are saving the old one. Which means... we will see later on 

Action Maping
        ActionMap am = area.getActionMap();
Action Cut = am.get(DefaultEditorKit.cutAction);
Action Copy = am.get(DefaultEditorKit.copyAction);
Action Past = am.get(DefaultEditorKit.pasteAction);
By allowing us, to give absolute correct power we are using the DefaultEditorKit in the Swing package...(IO too..)

Methods #1
        private void saveFileAs() {
if (dialog.showSaveDialog(null) == JFileChooser.APPROVE_OPTION)
saveFile(dialog.getSelectedFile().getAbsolutePath());
}
So now we have defined what saveFileAs will result to. However what will saveFile do, is something I will return to.

Methods #2
        private void saveOld() {
if (changed) {
if (JOptionPane.showConfirmDialog(this, "Would you like to save " + currentFile + " ?", "Save", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
saveFile(currentFile);
}
}
By using a saveOld giving us an option to save the changed state thus naming it old doesn't seem wrong, right~?

Method #3
       private void readInFile(String fileName) {
try {
FileReader r = new FileReader(fileName);
area.read(r, null);
r.close();
currentFile = fileName;
setTitle(currentFile);
changed = false;
} catch (Exception e) {
Toolkit.getDefaultToolkit().beep();
JOptionPane.showMessageDialog(this, "Editor can't find the file called " + fileName);
}
}
As we are allowed to save, how do we open a file? Easy making a filereader method... The beep sound isn't required however I feel that making it kinda "cooler" why not give it an extra touch?

Method #4
        private void saveFile(String fileName) {
try {
FileWriter w = new FileWriter(fileName);
area.write(w);
w.close();
currentFile = fileName;
setTitle(currentFile);
changed = false;
Save.setEnabled(false);
} catch (Exception e) {}
}
Our savefile method. Allowing the user to define a name for the title as well to his/her document. 

The main
        public static void main(String[] args) {
new NotedPad();
}
}
Creating a new TextEditor everytime we launch !
Hope you enjoyed to follow this tutorial as I created it for you guys !
Cheers !

Download Icon

You see this tutorial with my video:

Part 1:




Part 2:




Part 3:



Full Video:

0 comments

Post a Comment