I am going to show how to perform undo algorithm on your Java Swing application. I hope before you tried to understand undo algorithm, understand how to create following simple text application as I am going to perform undo algorithm on it.
Here’s the Simple Text Application source code
1: package UndoSwingTutorialPackage; 2: 3: import java.awt.event.ActionEvent; 4: import java.awt.event.InputEvent; 5: import java.awt.event.KeyEvent; 6: import javax.swing.*; 7: 8: public class SimpleTextApplication extends JFrame{ 9: 10: /** 11: * 12: */ 13: private static final long serialVersionUID = -4626161399740482146L; 14: 15: SimpleTextApplication(){ 16: super(); 17: JTextArea text = new initialTextField(); 18: 19: setTitle("Simple Text Application"); 20: 21: getContentPane().add(text); 22: 23: } 24: 25: class initialTextField extends JTextArea{ 26: /** 27: * 28: */ 29: private static final long serialVersionUID = 1L; 30: 31: initialTextField(){ 32: super(); 33: 34: initialShortcutKey(this); 35: 36: setColumns(40); 37: setLineWrap(true); 38: setRows(5); 39: setEditable(true); 40: 41: 42: } 43: 44: void initialShortcutKey(JComponent component){ 45: 46: /* 47: * Never tried to use keyListener as it wouldn't work on component 48: * For more detail on the reason of keyListener, please find the answer on your own 49: * 50: * On swing, we have to specify which component is listen to key and which key 51: * We have to use InputMap and ActionMap instead of KeyListener 52: * 53: */ 54: 55: InputMap im = component.getInputMap(JComponent.WHEN_FOCUSED); 56: ActionMap am = component.getActionMap(); 57: 58: /* 59: * When the JTextArea is focused (Precisely JTextArea is focused all the times), 60: * Component JTextArea is listened to space key by getKeyStroke( KeyEvent.VK_SPACE ,0 ) 61: */ 62: im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0), "listenSpacebarKey"); 63: am.put("listenSpacebarKey", new AbstractAction(){ 64: 65: /** 66: * 67: */ 68: private static final long serialVersionUID = 1L; 69: 70: @Override 71: public void actionPerformed(ActionEvent arg0) { 72: 73: 74: } 75: }); 76: 77: im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z,InputEvent.CTRL_MASK), "listenCtrlzKey"); 78: am.put("listenCtrlzKey", new AbstractAction(){ 79: 80: /** 81: * 82: */ 83: private static final long serialVersionUID = 1L; 84: 85: @Override 86: public void actionPerformed(ActionEvent arg0) { 87: 88: 89: } 90: }); 91: } 92: } 93: 94: 95: public static void main(String[] args){ 96: JFrame frame = new SimpleTextApplication(); 97: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 98: frame.pack(); 99: frame.setLocation(250,250); 100: frame.setVisible(true); 101: } 102: 103: }
I hope you wouldn’t get confused on this simple application. On JTextArea component, keyEvent indicate when spacebar is pressed. But you will found it nothing is happened, when spacebar is pressed, I blank it for the purpose of performing some undo action later on.
JTextArea
keyEvent
Long introduction is over and I hope you wouldn’t get confused as it is just beginning.
As what SimpleTextApplication shows, spacebar key and Ctrl+Z key is indicated as it is pressed. Before explain how to use it, tried the complete work and understand how complete work is worked. Following code is the complete work.
SimpleTextApplication
1: package UndoSwingTutorialPackage; 2: 3: import javax.swing.JTextArea; 4: 5: public class MyUndoWork { 6: 7: protected String[] memory; 8: protected String tempMemory; 9: protected int currentNumber = 0; 10: private int max = 100; 11: 12: MyUndoWork(JTextArea textComponent){ 13: super(); 14: memory = new String[max]; 15: 16: /* 17: * initial the first layer memory value 18: * If textComponent is found, put the text that exists on it at initial 19: * Else initial the memory with blank text "" 20: */ 21: if(textComponent != null){ 22: memory[0] = textComponent.getText(); 23: tempMemory = textComponent.getText(); 24: }else{ 25: memory[0] = ""; 26: tempMemory = ""; 27: } 28: 29: } 30: 31: public void updateUndoMemory(String temp){ 32: 33: /* 34: * Prevent duplicate data is store into undo Memory 35: */ 36: if(!tempMemory.equals(temp)){ 37: 38: //Store previous data that store in tempMemory into memory 39: storingDataForUndo(tempMemory); 40: 41: //update tempMemory into latest content 42: tempMemory = temp; 43: } 44: } 45: 46: protected void storingDataForUndo(String value1){ 47: 48: if(currentNumber < max ){ 49: 50: /* 51: * If there is no overflow of memory 52: * Store the tempData into memory and 53: */ 54: memory[currentNumber] = value1; 55: currentNumber++; 56: }else if(currentNumber >= max){ 57: /* 58: * If data stores into memory is overflow 59: * Dispose the most bottom level memory and level down one of every memory 60: * Put the new data into top level memory 61: */ 62: for(int i = 0;i < max-1 ;i++){ 63: memory[i ]= memory[i + 1]; 64: } 65: currentNumber = max-1; 66: memory[currentNumber] = value1; 67: currentNumber++; 68: } 69: } 70: 71: public String releaseDataForUndo(){ 72: 73: if(currentNumber > 0){ 74: currentNumber--; 75: System.out.println("currentNumber : "+currentNumber); 76: 77: /* 78: * Once undo is pressed and memory is release 79: * previous content that stored into tempMemory must be released 80: * and update it to latest current content 81: * 82: */ 83: 84: tempMemory = memory[currentNumber]; 85: return memory[currentNumber]; 86: 87: }else{ 88: currentNumber = 0; 89: tempMemory = memory[currentNumber]; 90: return memory[currentNumber]; 91: } 92: } 93: } 94:
1: package UndoSwingTutorialPackage; 2: 3: import java.awt.event.ActionEvent; 4: import java.awt.event.InputEvent; 5: import java.awt.event.KeyEvent; 6: import javax.swing.*; 7: 8: public class SimpleTextApplication extends JFrame{ 9: 10: /** 11: * 12: */ 13: private static final long serialVersionUID = -4626161399740482146L; 14: 15: MyUndoWork myUndoWork; 16: 17: SimpleTextApplication(){ 18: super(); 19: JTextArea text = new initialTextField(); 20: 21: setTitle("Simple Text Application"); 22: 23: getContentPane().add(text); 24: 25: } 26: 27: class initialTextField extends JTextArea{ 28: /** 29: * 30: */ 31: private static final long serialVersionUID = 1L; 32: 33: initialTextField(){ 34: super(); 35: 36: initialShortcutKey(this); 37: 38: /* 39: * Implement MyUndoWork class and initial it. 40: */ 41: myUndoWork = new MyUndoWork(this); 42: 43: setColumns(40); 44: setLineWrap(true); 45: setRows(5); 46: setEditable(true); 47: 48: 49: } 50: 51: void initialShortcutKey(JComponent component){ 52: 53: /* 54: * Never tried to use keyListener as it wouldn't work on component 55: * For more detail on the reason of keyListener, please find the answer on your own 56: * 57: * On swing, we have to specify which component is listen to key and which key 58: * We have to use InputMap and ActionMap instead of KeyListener 59: * 60: */ 61: 62: InputMap im = component.getInputMap(JComponent.WHEN_FOCUSED); 63: ActionMap am = component.getActionMap(); 64: 65: /* 66: * When the JTextArea is focused (Precisely JTextArea is focused all the times), 67: * Component JTextArea is listened to space key by getKeyStroke( KeyEvent.VK_SPACE ,0 ) 68: */ 69: im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0), "listenSpacebarKey"); 70: am.put("listenSpacebarKey", new AbstractAction(){ 71: 72: /** 73: * 74: */ 75: private static final long serialVersionUID = 1L; 76: 77: @Override 78: public void actionPerformed(ActionEvent arg0) { 79: 80: /* 81: * Undo memory is updated when user press space bar on JTextArea 82: * 83: */ 84: 85: myUndoWork.updateUndoMemory(getText()); 86: 87: } 88: }); 89: 90: im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z,InputEvent.CTRL_MASK), "listenCtrlzKey"); 91: am.put("listenCtrlzKey", new AbstractAction(){ 92: 93: /** 94: * 95: */ 96: private static final long serialVersionUID = 1L; 97: 98: @Override 99: public void actionPerformed(ActionEvent arg0) { 100: /* 101: * update the undo content when user pressed Ctrl + Z key * 102: */ 103: setText(myUndoWork.releaseDataForUndo()); 104: 105: 106: } 107: }); 108: } 109: } 110: 111: 112: public static void main(String[] args){ 113: JFrame frame = new SimpleTextApplication(); 114: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 115: frame.pack(); 116: frame.setLocation(250,250); 117: frame.setVisible(true); 118: } 119: 120: } 121:
Tried it out how undo is work.
How to make it work?
MyUndoWork
getText()
updateUndoMemory()
releaseDataForUndo()
That’s all! You can perform undo work on your application by declare just only 2 method if implemented MyUndoWork class.
Predict user input " B C D" into text area and "A" is exists on initial.
From the picture above, "A" letter is there when user is open the application After that, letter "B" is input and spacebar by user. Before content is changed, initial content "A" is store into memory. Again, "C" is input and spacebar. The content before "C" is input, "A B " is store into memory. Again, "D" is input and spacebar. The content before "D" is input, content "A B C" is retrieved and store into memory.
When user press shortcut key Ctrl + Z to perform undo for three times return to initial state "A". Pictures following shows how it works.
Ctrl+Z is the shortcut key of undo. When shortcut key is pressed, the top layer of the memory is released into content. For instances, current content "A B C D" is input and Ctrl+Z is pressed, the previous top layer memory "A B C" is released into content. When the top layer memory"A B C" is released into content, current content "A B C D" is replaced by top layer memory. So, what user will see just only the content of top layer memory.
Again, Ctrl + Z is pressed and "A B" is released into content and the current content "A B C" is replaced by it.
This is how my undo is work.
Thank you for reading my article.