Undo/Redo actions don't call AbstractDocument.insertString or remove?
Hi,
I just started working with the UNDO support in the JTextComponents. Primarily, the JTextPane. I am working on a small syntax highlighter component that uses my own extension of DefaultStyledDocument and use the "insertString(int offset, String str, AttributeSet attr, boolean replace)" method and it uses the setCharacterAttributes() method to highlight my keywords. (Pretty standard, like everyone else)
When i run my app, i can paste code into the JTextPane and see the code highlight in the call to insertString(). When I do an UNDO action through my JMenu, I see the text dissappear from the component. But I don't see the remove() method called.
Also, when I do a REDO action on the UndoManager. The insertString() method is never called. I have a DocumentListener attached to my JTextPane and I see that fire the insertUpdate method fire...and my text that was highlighted through the insertString method on the document..is loses it's highlighting.
My question is, is that the correct behaviour? Am I correct in assume that the insertString()/removeString() methods should be called when a REDO/UNDO action is called on the undomanager? I looked at the source code for AbstractDocument and the UndoManager and it looks like the UndoManager simply calls the redo() and undo() methods on the classes that support undo capabilities.
And, what is happening to my CharacterAttributes on the redo? it's like they are lost.
Am I misunderstanding how this works? Do I need to call insertString() from inside my insertUpdate document listener?
I've tried this on both 1.4.2_09 and 1.5.0_06
Thanks,
- Tim
Ok, I'm having a mental lapse..
I'm trying to override the fireInsert/fireRemove methods and am running into arrayindex out of bounds issues..I'm sure I'm doing something dumb..
I've tried both calling super.xxx before and after my highlighting..
* (non-Javadoc)
* @see javax.swing.text.AbstractDocument#fireInsertUpdate(javax.swing.event.DocumentEvent)
protected void fireInsertUpdate(DocumentEvent e) {
super.fireInsertUpdate(e);
try {
int offset = e.getOffset();
int length = e.getLength();
String text = e.getDocument().getText(offset, length);
processChangedLines(offset, text.length());
} catch (BadLocationException ex) {
ex.printStackTrace();
* (non-Javadoc)
* @see javax.swing.text.AbstractDocument#fireRemoveUpdate(javax.swing.event.DocumentEvent)
protected void fireRemoveUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
super.fireRemoveUpdate(e);
try {
int offset = e.getOffset();
int length = e.getLength();
processChangedLines(offset, length);
} catch (BadLocationException ex) {
ex.printStackTrace();
}Exception when trying to do an undo of text that I paste into the editor:
java.lang.ArrayIndexOutOfBoundsException: -1
at javax.swing.text.AbstractDocument$BranchElement.getEndOffset(AbstractDocument.java:2333)
at javax.swing.text.View.getEndOffset(View.java:832)
at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:391)
at javax.swing.text.FlowView.layout(FlowView.java:182)
at javax.swing.text.BoxView.setSize(BoxView.java:379)
at javax.swing.text.BoxView.updateChildSizes(BoxView.java:348)
at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:316)
at javax.swing.text.BoxView.layout(BoxView.java:683)
at javax.swing.text.BoxView.setSize(BoxView.java:379)
at javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1599)
at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:801)
at javax.swing.JComponent.getPreferredSize(JComponent.java:1275)
at javax.swing.JEditorPane.getPreferredSize(JEditorPane.java:1212)
at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
at java.awt.Container.layout(Container.java:1020)
at java.awt.Container.doLayout(Container.java:1010)
at java.awt.Container.validateTree(Container.java:1092)
at java.awt.Container.validate(Container.java:1067)
at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:353)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:116)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:189)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:478)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)
Similar Messages
-
Problem with undo/redo actions in a StyledDocument
Hello,
In my app i have a text area where each user can keep some notes.The document is serialized and saved in the database for later access as StyledDocument, in order to be saved with the formating the user has chosen(for example with certain fonts,text color and size).
What i want to do now is to give to the user the ability to undo/redo his actions. I have these methods implemented and everything worked fine when i was saving and loading simple text in my JTextPane (previously i was saving in the database what user typed as a simple string which meant that the formatting was lost). Now, after loading styled document (using the textPane.setStyledDocument(doc) code line) these actions do not work.
Are there any suggestions on how i can make this work? Is it possible?
I hope i made my problem clear enough
Thanks in advanceSeem like I found the answer to my issue: http://helpx.adobe.com/dreamweaver/using/whats-new-2014.html#Undo/Redo enhancements
Undo/Redo enhancements
All undo/redo actions are recorded at the HTML file-level. This means, any manual changes to a CSS file can be undone from ANY related file.
Someone called it Undo/Redo enhancements!? Damn this is the most stupid thing one can imagine about undo/redo! How the heck editing one source file affects the other!? Do whatever you want in Designer mode, but I'm editing SOURCE CODE and need to be able to undo/redo my actions on a file level.
With this change TextEdit or Notepad becomes a more suitable tool for editing HTML/CSS than Dreamweaver. -
Undo/Redo Actions for Your Music on Desktop
Right now you can only use the undo/redo actions for playlists.
Add the ability to undo/redo actions you make to "Your Music" in the desktop app.
Menu bar:
Edit --> Undo
Edit --> Redo
Maybe you accidentally removed a song from Your Music and you want to undo it.oh cool, this is over six months old and it still hasn't been addressed.
-
New to undo/redo on component
hello all,
i'm new to swing programming & i have to develop a web enabled application. in that i'm having an internalframe which contains a panel with some labels in it. i'm able to move the labels around the panel by using mouse listener. but my problem is i have to implement undo/redo functionality on this movement. but i don't know how to proceed since i don't have a single idea abt this api. i got some materials related to undo/redo of textual components. but nothing related to this labels or components like that. can someone help me on this topic or guide me to some links which has details. if u can provide me some code samples i'll be really greateful.
Thanks in advanceThe Java Tutorial provides a section on how to implement the java.swing.undo package.
http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html#undo
The TextComponentDemo example code it references uses a text Document to generate the UndoableEditListener events, but any component document or data model can be coded to do the same thing, such as the data model for your label placement panel. The listeners are usually added by a controlling parent class, such as a JFrame.
* Create an addUndoableEditListener(UndoableEditListener listener) method in your model class.
* Whenever an undoable edit is done in your model class, create an UndoableEditEvent object with the undoable edit data and call the undoableEditHappened(UndoableEditEvent e) method for all of your registered listeners.
* Create an UndoManager object in your controlling parent class.
* Create UndoAction and RedoAction subclassed objects in your controlling parent class.
* Create an UndoableEditListener object in your controlling parent class and add it to your model class.
The listeners will handle adding the UndoableEditEvent object to the UndoManager and updating any menu or toolbar Undo/Redo actions. The Undo/Redo actions will handle performing the commands via the UndoManager and updating the state of the Undo/Redo actions.
I hope you find this of some help. -
Only Undo/Redo Editing but No Syntax Highlighting
I have a JTextPane with styled content, when I apply undo/redo I don't want the different Color Highlighting to be added to Undo/Redo queue of UndoManager. How can I? My Undo Listener and Actions looks like below:
protected class RulesUndoableEditListener implements UndoableEditListener {
RuleExpressionUndo undoAction;
RedoRuleExpression redoAction;
UndoManager undoMgr;
public RulesUndoableEditListener(RuleExpressionUndo undoAction,
RedoRuleExpression redoAction, UndoManager undoMgr)
this.undoAction = undoAction;
this.redoAction = redoAction;
this.undoMgr = undoMgr;
public void undoableEditHappened(UndoableEditEvent e) {
undoMgr.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
class RuleExpressionUndo extends AbstractAction {
RedoRuleExpression redoAction;
UndoManager undo;
public RuleExpressionUndo(UndoManager undo) {
super("Undo");
this.undo = undo;
setEnabled(false);
public void actionPerformed(ActionEvent e) {
try {
undo.undo();
} catch (CannotUndoException ex) {
System.out.println("Unable to undo: " + ex);
ex.printStackTrace();
updateUndoState();
redoAction.updateRedoState();
protected void updateUndoState() {
if (undo.canUndo()) {
setEnabled(true);
putValue(Action.NAME, undo.getUndoPresentationName());
} else {
setEnabled(false);
putValue(Action.NAME, "Undo");
* @param redoAction the redoAction to set
public void setRedoAction(RedoRuleExpression redoAction)
this.redoAction = redoAction;
class RedoRuleExpression extends AbstractAction {
RuleExpressionUndo undoAction;
UndoManager undo;
public RedoRuleExpression(UndoManager undo) {
super("Redo");
this.undo = undo;
setEnabled(false);
public void actionPerformed(ActionEvent e) {
try {
undo.redo();
} catch (CannotRedoException ex) {
System.out.println("Unable to redo: " + ex);
ex.printStackTrace();
updateRedoState();
undoAction.updateUndoState();
protected void updateRedoState() {
if (undo.canRedo()) {
setEnabled(true);
putValue(Action.NAME, undo.getRedoPresentationName());
} else {
setEnabled(false);
putValue(Action.NAME, "Redo");
* @param undoAction the undoAction to set
public void setUndoAction(RuleExpressionUndo undoAction)
this.undoAction = undoAction;
}I believe that in the undoableEditHappened() method you can add code like thefollowing:
AbstractDocument.DefaultDocumentEvent event =
(AbstractDocument.DefaultDocumentEvent)e.getEdit();
if (event.getType().equals(DocumentEvent.EventType.CHANGE))
// attribute change - do nothing
else
undoMgr.addEdit(e.getEdit());
undoAction.updateUndoState();
redoAction.updateRedoState();
} -
Move OSD of Undo/Redo to bottom of workspace
A lot of the time when I am trying to compare one particular edit that I've made, say, increase Vibrance +30, I switch back and forth using Undo/Redo to view the Before/After (using the '\' key to see 'Before' vs 'After' doesn't work if you've already made multiple edits, obviously).
Now, I like how LR shows 'Undo Vibrance + 30' in big bold letters across the screen, BUT, could you please move it *away* from smack dab right in the center on top of my image?
If you moved the On-Screen-Display of 'Undo/Redo' actions to near the bottom of the LR workspace, it wouldn't interfere with my viewing of what's happening to the image.
Seems simple + logical enough.
Thanks,
RishiI approach it differently :
When (or if) I get an image to a point where I want to compare small changes I make a virtual copy and then adjust the VC, then using the '\' key to see 'Before' vs 'After' does work.
Not a work around - a different way of working.
Sid
The LightroomExtra home page is right here. -
How can I include in my VI actions like "Undo last action/redo last action"?
I built a Vi and I want to include functions like Undo (last action) and Redo (last action).
Any suggestion wellcome.
Thank youHi
If you have the Menu Bar visible when your VI runs - this Forms your Default VI run-time Menu. You will discover a built in Undo and Redo Functions under "Edit" Menu. This fuction can be added to your custom Menus or .rtm files.
However, this undo fuctionality is limited to data change only, which means it will erase the last control change. This Undo will not reverse any data propagated as a result of your last control change. Here is an example.
Say you are taking a continuously polled value of a String control and building a Path using this, and you have a Button that says "Process Path" which ends the polling and brings you out of the While Loop. In this example if you change the value of String Control and Say Undo you will be reverted to Previo
us Value. However If after changing the Value you Clicked the "Process Path" Button, you will be Out of your While Loop with the Path being built with the Last value of String Control before "ProcessPath" was clicked. Now Clicking Undo tries to Reverse the Last Control Which was "Process Path" This has no effect on Path Value. The Undo Function will not reverse the Data which has Propagated and take you backwards in the diagram. It will simply reverse the Data Changed on the last Control.
Therefore if you want a robust "Undo" and "Redo" you will have to program this functionality, Basically you will have to trap values of all controls and on data change remember these values. On Undo you can then Change the values of Controls back to Previous Value and Also take your Diagram back to Where the Last action had impacted any data propagation.
All this - mind you - is for a single level undo. It will get complex to do Multiple Level Undo.
Good Luck! Dont you wish, you could Just
Undo the Computer Age?!!
Mache
Good Luck!
Mache -
Problem of cut,copy,past ,undo and redo actions
hi
iam a student of computer science
iam working on my project notpad
in this i have to apply the command of doing cut ,copy ,past ,undo,redo
how can i use thes actions in my project
please help me for making my project
i will wait your response at [email protected]what u can do is
just component.cut();
or
compoennt.copy();
component.paste();
for undo and redo
u need to take help of undo manager
which will tell u whether u can undo or not
same with redo case
hope it will work -
Undo / Redo Feature in Swing
Hi all,
Iam working on swing project which uses Undo/Redo feature for drag and drop figure and delete,cut,copy,paste and all the feature which ever want to use, and iam using multiple internal frames so the feature Undo/Redo should be specific to perticular internal frame.
Is any buddy already done such a kind of thing then pls help me, or if it's possible then pls send the code also.
Regards
LaxmikantHi,
you would have to create an UndoableEditListener for each object, undo/redo shall be perfomed. The listener then is connected to an instance of UndoManager to do the actual handling: /** Listener for edits on a document. */
private UndoableEditListener undoHandler = new UndoHandler();
/** UndoManager that we add edits to. */
private UndoManager undo = new UndoManager();
/** inner class for handling undoable edit events */
public class UndoHandler implements UndoableEditListener {
* Messaged when the Document has created an edit, the edit is
* added to <code>undo</code>, an instance of UndoManager.
public void undoableEditHappened(UndoableEditEvent e) {
undo.addEdit(e.getEdit());
} This now can be registered with let's say a Document like thiseditor.getDocument().addUndoableEditListener(undoHandler); (editor is an instance of JEditorPane containing the document).
Once you have this, you only need actions to perform undo or redo by calling the respective method of your instance of UndoManager undo() and redo().
Hope that helps
Ulrich -
Undo/Redo for Cut, Copy, Paste
I am trying to implement Undo/Redo for Cut,Copy,Paste in a Treetable.
I have to support undo/redo for multiple nodes being cut/copied. I am not sure how I should be going about implementing this. Any help will be greatly appreciated.
ThanksIf the class you are using doesn't support cut, copy, and paste already, usually what you do is store a list of actions in two lists. One for actions done, the other for redos (when there is an undo). Capture the data before and after each operation (you can create a KeyListener to listen for the events) and store that in a list. When undo is called, the last element on the list should be undone, either by taking it out of the list and reiterating through the elements still there, or implementing an undo method in the object you are trying to change. Then put that element on the redo list in case that is called. This works well with graphics and stuff, but I never tried to implement it in a tree with nodes and stuff, so that's about the most I can help with right now. I hope it helps some!
-JBoeing -
Hi to everyone!!!
I need your advice for my problem!!
when I cliked new in the file to create a new JTextPane the undo redo button will multiply and if I have so many JTextPane then I have many undo redo in my toolbar
here is my code.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.util.*;
import javax.swing.undo.*;
public class URTest extends JFrame {
JToolBar toolBar = new JToolBar();
JButton undo;
JButton redo = new JButton("Redo");
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
JMenuItem item = new JMenuItem("New");
JMenuItem item2 = new JMenuItem("Close");
JTabbedPane tabbedPane = new JTabbedPane();
JTextPane pane;
public URTest() {
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
create();
item2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeCreate();
menu.add(item);
menu.add(item2);
menuBar.add(menu);
this.add(toolBar,BorderLayout.NORTH);
this.add(tabbedPane);
this.setJMenuBar(menuBar);
void create() {
undo = new JButton("Undo");
redo = new JButton("Redo");
pane = new JTextPane();
EditorKit editorKit = new StyledEditorKit() {
public Document createDefaultDocument() {
return new SyntaxDocument();
pane.setEditorKit(editorKit);
final CompoundUndoManager undoManager = new CompoundUndoManager( pane );
undo.addActionListener( new ActionListener()
public void actionPerformed(ActionEvent e)
try
undoManager.undo();
pane.requestFocus();
catch (CannotUndoException ex)
System.out.println("Unable to undo: " + ex);
redo.addActionListener( new ActionListener()
public void actionPerformed(ActionEvent e)
try
undoManager.redo();
pane.requestFocus();
catch (CannotRedoException ex)
System.out.println("Unable to redo: " + ex);
toolBar.add(undo);
toolBar.add(redo);
tabbedPane.addTab("Tab",pane);
void removeCreate() {
tabbedPane.remove(tabbedPane.getSelectedIndex());
public static void main(String[] args) {
URTest frame = new URTest();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(400,400);
frame.setVisible(true);
class CompoundUndoManager extends UndoManager
implements UndoableEditListener, DocumentListener
public CompoundEdit compoundEdit;
private JTextComponent editor;
// These fields are used to help determine whether the edit is an
// incremental edit. For each character added the offset and length
// should increase by 1 or decrease by 1 for each character removed.
private int lastOffset;
private int lastLength;
public CompoundUndoManager(JTextComponent editor)
this.editor = editor;
editor.getDocument().addUndoableEditListener( this );
** Add a DocumentLister before the undo is done so we can position
** the Caret correctly as each edit is undone.
public void undo()
editor.getDocument().addDocumentListener( this );
super.undo();
editor.getDocument().removeDocumentListener( this );
** Add a DocumentLister before the redo is done so we can position
** the Caret correctly as each edit is redone.
public void redo()
editor.getDocument().addDocumentListener( this );
super.redo();
editor.getDocument().removeDocumentListener( this );
** Whenever an UndoableEdit happens the edit will either be absorbed
** by the current compound edit or a new compound edit will be started
public void undoableEditHappened(UndoableEditEvent e)
// Start a new compound edit
if (compoundEdit == null)
compoundEdit = startCompoundEdit( e.getEdit() );
lastLength = editor.getDocument().getLength();
return;
// Check for an attribute change
AbstractDocument.DefaultDocumentEvent event =
(AbstractDocument.DefaultDocumentEvent)e.getEdit();
if (event.getType().equals(DocumentEvent.EventType.CHANGE))
compoundEdit.addEdit( e.getEdit() );
return;
// Check for an incremental edit or backspace.
// The change in Caret position and Document length should be either
// 1 or -1 .
int offsetChange = editor.getCaretPosition() - lastOffset;
int lengthChange = editor.getDocument().getLength() - lastLength;
if (Math.abs(offsetChange) == 1
&& Math.abs(lengthChange) == 1)
compoundEdit.addEdit( e.getEdit() );
lastOffset = editor.getCaretPosition();
lastLength = editor.getDocument().getLength();
return;
// Not incremental edit, end previous edit and start a new one
compoundEdit.end();
compoundEdit = startCompoundEdit( e.getEdit() );
** Each CompoundEdit will store a group of related incremental edits
** (ie. each character typed or backspaced is an incremental edit)
private CompoundEdit startCompoundEdit(UndoableEdit anEdit)
// Track Caret and Document information of this compound edit
lastOffset = editor.getCaretPosition();
lastLength = editor.getDocument().getLength();
// The compound edit is used to store incremental edits
compoundEdit = new MyCompoundEdit();
compoundEdit.addEdit( anEdit );
// The compound edit is added to the UndoManager. All incremental
// edits stored in the compound edit will be undone/redone at once
addEdit( compoundEdit );
return compoundEdit;
// Implement DocumentListener
// Updates to the Document as a result of Undo/Redo will cause the
// Caret to be repositioned
public void insertUpdate(final DocumentEvent e)
SwingUtilities.invokeLater(new Runnable()
public void run()
int offset = e.getOffset() + e.getLength();
offset = Math.min(offset, editor.getDocument().getLength());
editor.setCaretPosition( offset );
public void removeUpdate(DocumentEvent e)
editor.setCaretPosition(e.getOffset());
public void changedUpdate(DocumentEvent e) {}
class MyCompoundEdit extends CompoundEdit
public boolean isInProgress()
// in order for the canUndo() and canRedo() methods to work
// assume that the compound edit is never in progress
return false;
public void undo() throws CannotUndoException
// End the edit so future edits don't get absorbed by this edit
if (compoundEdit != null)
compoundEdit.end();
super.undo();
// Always start a new compound edit after an undo
compoundEdit = null;I was not actually sure what you wanted so I made the wild guess that you actually wanted only one pair of Undo/Redo buttons. Here you go :import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
public class URTest extends JPanel {
private JMenuBar theMenuBar;
private JTabbedPane theTabbedPane;
private List<Pane> thePanes;
private static class Pane {
private JTextPane theTextPane;
private CompoundUndoManager theUndoManager;
private class CompoundUndoManager extends UndoManager implements UndoableEditListener, DocumentListener {
public CompoundEdit compoundEdit;
private int lastOffset;
private int lastLength;
public CompoundUndoManager() {
compoundEdit = null;
public void undo() {
theTextPane.getDocument().addDocumentListener(this);
super.undo();
theTextPane.getDocument().removeDocumentListener(this);
public void redo() {
theTextPane.getDocument().addDocumentListener(this);
super.redo();
theTextPane.getDocument().removeDocumentListener(this);
public void undoableEditHappened(UndoableEditEvent e) {
if (compoundEdit == null) {
compoundEdit = startCompoundEdit(e.getEdit());
lastLength = theTextPane.getDocument().getLength();
return;
AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent)e.getEdit();
if (event.getType().equals(DocumentEvent.EventType.CHANGE)) {
compoundEdit.addEdit(e.getEdit());
return;
int offsetChange = theTextPane.getCaretPosition() - lastOffset;
int lengthChange = theTextPane.getDocument().getLength() - lastLength;
if (Math.abs(offsetChange) == 1
&& Math.abs(lengthChange) == 1) {
compoundEdit.addEdit(e.getEdit());
lastOffset = theTextPane.getCaretPosition();
lastLength = theTextPane.getDocument().getLength();
return;
compoundEdit.end();
compoundEdit = startCompoundEdit(e.getEdit());
private CompoundEdit startCompoundEdit(UndoableEdit anEdit) {
lastOffset = theTextPane.getCaretPosition();
lastLength = theTextPane.getDocument().getLength();
compoundEdit = new MyCompoundEdit();
compoundEdit.addEdit(anEdit);
addEdit(compoundEdit);
return compoundEdit;
public void insertUpdate(final DocumentEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int offset = e.getOffset() + e.getLength();
offset = Math.min(offset, theTextPane.getDocument().getLength());
theTextPane.setCaretPosition(offset);
public void removeUpdate(DocumentEvent e) {
theTextPane.setCaretPosition(e.getOffset());
public void changedUpdate(DocumentEvent e) {}
class MyCompoundEdit extends CompoundEdit {
public boolean isInProgress() {
return false;
public void undo() throws CannotUndoException {
if (compoundEdit != null) compoundEdit.end();
super.undo();
compoundEdit = null;
public Pane() {
theTextPane = new JTextPane();
theTextPane.setEditorKit(new StyledEditorKit() {
public Document createDefaultDocument() {
return new SyntaxDocument();
theUndoManager = new CompoundUndoManager();
theTextPane.getDocument().addUndoableEditListener(theUndoManager);
public JTextPane getTextPane() {
return theTextPane;
public UndoManager getUndoManager() {
return theUndoManager;
public URTest() {
super(new BorderLayout(5, 5));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.add(new AbstractAction("Undo") {
public void actionPerformed(ActionEvent e) {
undo();
toolBar.add(new AbstractAction("Redo") {
public void actionPerformed(ActionEvent e) {
redo();
add(toolBar, BorderLayout.NORTH);
thePanes = new LinkedList<Pane>();
theTabbedPane = new JTabbedPane();
add(theTabbedPane, BorderLayout.CENTER);
theMenuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.add(new AbstractAction("New") {
public void actionPerformed(ActionEvent e) {
create();
menu.add(new AbstractAction("Close") {
public void actionPerformed(ActionEvent e) {
remove();
theMenuBar.add(menu);
public JMenuBar getMenuBar() {
return theMenuBar;
private void create() {
Pane pane = new Pane();
thePanes.add(pane);
theTabbedPane.addTab("Tab", pane.getTextPane());
private void remove() {
Pane selectedPane = getSelectedPane();
if (selectedPane == null) return;
thePanes.remove(selectedPane);
theTabbedPane.remove(selectedPane.getTextPane());
private void undo() {
Pane selectedPane = getSelectedPane();
if (selectedPane == null) return;
try {
selectedPane.getUndoManager().undo();
selectedPane.getTextPane().requestFocus();
} catch (CannotUndoException ex) {
System.out.println("Unable to undo: " + ex);
private void redo() {
Pane selectedPane = getSelectedPane();
if (selectedPane == null) return;
try {
selectedPane.getUndoManager().redo();
selectedPane.getTextPane().requestFocus();
} catch (CannotRedoException ex) {
System.out.println("Unable to redo: " + ex);
private Pane getSelectedPane() {
Component selectedComponent = theTabbedPane.getSelectedComponent();
if (selectedComponent == null) return null;
for (Pane pane : thePanes) {
if (pane.getTextPane() == selectedComponent) return pane;
return null;
private static void test() {
JFrame f = new JFrame("URTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
URTest urTest = new URTest();
f.setContentPane(urTest);
f.setJMenuBar(urTest.getMenuBar());
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
test();
}Hope it helps. -
Undo/Redo button are not performing more than one operation at a time
Hi,
I have created undo/redo button on my paint application. But it performing only last action to undo.I have just the code which store offscreen image into undo buffer image like this :
if (OSC == null || widthOfOSC != getSize().width || heightOfOSC != getSize().height) {
// Create the OSC, or make a new one if canvas size has changed.
OSC = null; // (If OSC & undoBuffer already exist, this frees up the memory.)
undoBuffer = null;
OSC = createImage(getSize().width, getSize().height);
widthOfOSC = getSize().width;
heightOfOSC = getSize().height;
OSG = OSC.getGraphics(); // Graphics context for drawing to OSC.
OSG.setColor(getBackground());
OSG.dispose();
undoBuffer = createImage(widthOfOSC, heightOfOSC);
OSG = undoBuffer.getGraphics(); // Graphics context for drawing to the undoBuffer.
OSG.setColor(getBackground());
OSG.fillRect(0, 0,widthOfOSC, heightOfOSC);
and the button performed it's action :
else if (command.equals("Undo")) {
// Swap the off-screen canvas with the undoBuffer and repaint.
Image temp = OSC;
OSC = undoBuffer;
undoBuffer = temp;
repaint();I want to create undo button that performed end operation on canvas.
please help me
Thanks in advance....Don't post the same question repeatedly. I've removed the thread you started 4 days after this one with the identical same question.
db -
Undo,redo not working properly with JPopupMenu
if i use JButton for undo ,redo it is working fine. but the same code is not
working properly if i add it in JPopupMenu.
what could be the problem.
thankswhat could be the problem.Your code is different or written incorrectly and since you didn't post any we can't help.
[url http://java.sun.com/docs/books/tutorial/uiswing/misc/action.html]How to Use Actions
If you need further help then you need to create a [url http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.
And don't forget to use the [url http://forum.java.sun.com/help.jspa?sec=formatting]Code Formatting Tags so the code retains its original formatting. -
Lazy Notification and Command Undo/Redo
I have a two-part CS3 plug-in (model and UI).<br /><br />When I click on one of the checkboxes in the UI, it causes a command to be executed that highlights certain fields in the document and sets a persistent boolean indicating the state of the higlighting.<br /><br />I want to be able to uncheck the checkbox when an Edit > Undo is done using lazy notification, but I've been working on this for a few days now and I can't get it to work.<br /><br />I've made the following changes to the model plug-in code:<br /><br />1. In the .fr file, I added this:<br />AddIn<br />{<br /> kDocWorkspaceBoss,<br /> kInvalidClass,<br /> {<br /> // Interface to the persistent prefs implementation<br /> IID_IVIPREFERENCES, kVIPrefsImpl,<br /> <br /> // Interface to the Toggle Highlighting command<br /> IID_IVIHIGHLIGHTCHANGE, kVISetHighlightDisplayedCmdImpl,<br /> }<br />},<br /><br />2. In the command's DoNotify method, I do a ModelChange call with an 'interestedIn' parameter of IID_IVIHIGHLIGHTCHANGE. I've tried invoking this method on various subjects, e.g., document subject, document workspace subject, document preferences subject (i.e., getting my persistent interface on the workspace and then getting an ISubject interface on it), all to no apparent avail.<br /><br />I've made the following changes to the UI plug-in code:<br /><br />1. In the .fr file, I added this:<br /><br />AddIn<br />{<br /> kDocWorkspaceBoss,<br /> kInvalidClass,<br /> {<br /> // Interface to the preference change observer<br /> IID_IPREFSOBSERVER, kVIPUIPrefsObserverImpl,<br /> }<br />},<br /><br />2. In the preference change observer's AutoAttach method, I do the following (with error checking removed here for clarity). I've tried various subjects besides the document workspace subject here as well...<br /><br />InterfacePtr<IActiveContext><br /> ac(gSession->GetActiveContext(), UseDefaultIID());<br />IDocument *doc = ac->GetContextDocument();<br />InterfacePtr<ISubject> subject(doc->GetDocWorkSpace(), UseDefaultIID());<br /><br />if (!subject->IsAttached(ISubject::kLazyAttachment, this,<br /> IID_IVIHIGHLIGHTCHANGE, IID_IPREFSOBSERVER)<br />) {<br /> subject->AttachObserver(ISubject::kLazyAttachment, this,<br /> IID_IVIHIGHLIGHTCHANGE, IID_IPREFSOBSERVER);<br />}<br /><br />I've implemented a LazyUpdate method in the preference change observer, but it never gets called -- not when the checkbox is checked, and not when an Undo or Redo is done. I've verified that the observer's AutoAttach method is getting called, and that the ModelChange method inside the command's DoNotify method is being called.<br /><br />Has anyone gotten lazy notification on command undo/redo to work? If so, can you tell me what I might be doing wrong?
Don't post the same question repeatedly. I've removed the thread you started 4 days after this one with the identical same question.
db -
Keybindings for undo/redo buttons.
I thought I knew how to do this, and I do seem to have this working fine for cut/copy/paste/select all keybindings CTRL X/C/V/A respectively.
However I tried to do this for CTRL X and Y undo/redo and it's not working as I intended. Can anyone see what I'm doing wrong?
I created a SSCCE based off the original example I was following from: [http://www.java2s.com/Code/Java/Swing-JFC/Undoredotextarea.htm]
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
public class UndoRedoTextArea extends JFrame implements KeyListener{
private static final long serialVersionUID = 1L;
protected JTextArea textArea = new JTextArea();
protected UndoManager undoManager = new UndoManager();
protected JButton undoButton = new JButton("Undo");
protected JButton redoButton = new JButton("Redo");
public UndoRedoTextArea() {
super("Undo/Redo Demo");
undoButton.setEnabled(false);
redoButton.setEnabled(false);
JPanel buttonPanel = new JPanel(new GridLayout());
buttonPanel.add(undoButton);
buttonPanel.add(redoButton);
JScrollPane scroller = new JScrollPane(textArea);
getContentPane().add(buttonPanel, BorderLayout.NORTH);
getContentPane().add(scroller, BorderLayout.CENTER);
textArea.getDocument().addUndoableEditListener(
new UndoableEditListener() {
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
updateButtons();
undoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
updateButtons();
undoButton.addKeyListener(this);
redoButton.addKeyListener(this);
redoButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
updateButtons();
setSize(400, 300);
setVisible(true);
public void updateButtons() {
undoButton.setText(undoManager.getUndoPresentationName());
redoButton.setText(undoManager.getRedoPresentationName());
undoButton.setEnabled(undoManager.canUndo());
redoButton.setEnabled(undoManager.canRedo());
public static void main(String argv[]) {
new UndoRedoTextArea();
public void keyPressed(KeyEvent e){
if (e.equals(KeyStroke.getKeyStroke
(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK))){
// undo
try {
undoManager.undo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
updateButtons();
else if (e.equals(KeyStroke.getKeyStroke
(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK))){
// redo
try {
undoManager.redo();
} catch (CannotRedoException cre) {
cre.printStackTrace();
updateButtons();
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}Edited by: G-Unit on Oct 24, 2010 5:30 AMcamickr wrote:
So the way I posted in the second lump of code OK (3rd post) or did you mean something different? Why did you set the key bindings? Did I not state they would be created automatically? I think you need to reread my suggestion (and the tutorial).Because I don't get it, it says only Menu items can contain accelerators and buttons only get mnemonics. I'm not using menu items here, I only have a text pane and 2 buttons. So I set the actions for the InputMap in TextPane. For the buttons, I pretty much used the small bit of code using undoManager.
I tried to set KEYSTROKE constructor for the action and simply add them to the buttons that way, but this didn't seem to have any response.
Also I don't get how this could happen anyway if the TextPane has the focus.
Not like the example using MNEMONICS.
Action leftAction = new LeftAction(); //LeftAction code is shown later
button = new JButton(leftAction)
menuItem = new JMenuItem(leftAction);
To create an Action object, you generally create a subclass of AbstractAction and then instantiate it. In your subclass, you must implement the actionPerformed method to react appropriately when the action event occurs. Here's an example of creating and instantiating an AbstractAction subclass:
leftAction = new LeftAction("Go left", anIcon,
"This is the left button.",
new Integer(KeyEvent.VK_L));
class LeftAction extends AbstractAction {
public LeftAction(String text, ImageIcon icon,
String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
public void actionPerformed(ActionEvent e) {
displayResult("Action for first button/menu item", e);
}This is what I attempted. No errors... It just doesn't work.
public JPanel p()
undoButton.addActionListener(new UndoAction(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK)));
panel.add(undoButton);
return panel;
private class UndoAction extends AbstractAction
public UndoAction(KeyStroke keyStroke)
putValue(ACCELERATOR_KEY, keyStroke);
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e)
try
if (undoManager.canUndo())
undoManager.undo();
catch (CannotRedoException cre)
cre.printStackTrace();
updateButtons();
}Edited by: G-Unit on Oct 25, 2010 8:32 AM
Maybe you are looking for
-
I am having a major problem with iMessage-
Since upgrading to 7.02 about half my texts don't go out even with a robust wireless or LTE signal. I have checked the 'send as SMS' but in some cases the messages will simply lock up and not go no matter what. Happens almost all the time now- and en
-
This happened for example when clicking on "printable view" on my Roadrunner webmail.
-
Mac mini fusion drive startup slow
Unfortunately my fusion drive was damaged and replaced by Apple service center. When I got it back it startup very slow, even slower than my white mac book. Initially, I though it was not start up from SSD so I tried to select SSD as the start up dis
-
Server 2012 not visable in AD after IP change
Running a single server 2012 in this environment so it hosts everything such as AD, DHCP, DNS etc. I changed the network IP scope due to VPN issues for users who connect from home networks using the same IP range. During the IP range change I change
-
Sort by Path and Filename - What does a guy have to do?
Hello all, First post here and such, but as the title reads. I have been using iTunes since early versions of 7 when I aquired my used 2gen Mini. In a past incident where people were attaching viruses to the ID3 Tags (see: http://en.wikipedia.org/wik