• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Help with UndoManager

 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for reading!
I have made a small app to illustrate the problem I am having. I have a JTextArea which I have an UndoManager managing any edits made. But, I get an ArrayIndexOutOfBoundsException - sometimes, but then not other times.
At the end of this post:-
UndoManager.java - compiles to illustrate problem
Stack Trace - for ArrayIndexOutOfBoundsException
Compile and press the 'Test Me' button first, then 'Undo' and this causes the exception. If you change the code in the actionPerformed method, you will see that there is not always an exception.
I have traced the error, and it seems to occur if the first edit to the JTextArea ends in a newline char, and also, if the first edit consists of more than one line and the first line is shorter than any of the others eg.

String s = "a\nab\n"; // this CAUSES an exception
If the first line length >= the second, it is fine eg.
String s = "ab\nab\n"; // this does NOT cause an exception
My question is: what am I doing wrong? Must be something simple?
PS. I have tried with various different methods, eg dsd.insertString(...) etc and regardless, I get the same error every time.
Can you tell me what I'm doing wrong???
Much appreciated!
**************************************************************************
Here is the Code:
**************************************************************************
/* Small app to test UndoManager
*
* Works fine for straight editing in the JTextArea,
* but if you apply a few methods on the Text Area, using
* the class API, it starts to throw ArrayIndexOutOfBoundsExceptions.
*
* My question is this: What do I need to do to make it possible to undo
* textArea.setText(...) or textArea.append(...) methods from code. I have
* tried different methods, eg dsd.insertText(...) etc, but always the same
* result.
*
* I have set this example up with some data. If you execute the code, hit
* the test button FIRST before typing in anything, then undo, and you get the
* exception. This exception only occurs if the first line of the append is
* shorter than the others, and the whole append all ends in a newline char!
* Other strange things happen too!
*
* Have a look at the actionPerformed method. Play around too. Strange things.
*
* I know I must be doing something simple wrong!!!
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.undo.*;
import javax.swing.text.*;

public class UndoManagerTest extends JFrame implements ActionListener
{
private JPanel contentPane;
private JTextArea textArea;
private JButton undoButton, redoButton, testButton;
private UndoManager undo;
private UndoAction undoAction;
private RedoAction redoAction;
private DefaultStyledDocument dsd;
//--------------------------------------------------------------------------
public UndoManagerTest()
{
contentPane = new JPanel();
dsd = new DefaultStyledDocument();
textArea = new JTextArea( dsd, "", 20, 30 );
JScrollPane scrollPane = new JScrollPane( textArea );
dsd.addUndoableEditListener( new MyUndoableEditListener() );

undoAction = new UndoAction ( "Undo" );
redoAction = new RedoAction ( "Redo" );
undoButton = new JButton( undoAction );
redoButton = new JButton( redoAction );
testButton = new JButton( "Test Me" );
testButton.addActionListener( this );

contentPane.add( scrollPane );
contentPane.add( undoButton );
contentPane.add( redoButton );
contentPane.add( testButton );
setContentPane( contentPane );
// create a new UndoManager
undo = new UndoManager();
}
//--------------------------------------------------------------------------
public void actionPerformed( ActionEvent e )
{
if( e.getSource() == testButton )
{
String s = "a\nab\n"; // this CAUSES an exception
//String s = "ab\nab\n"; // this does NOT cause an exception
//String s = "a\na"; // this does NOT cause an exception
textArea.append( s );
}
}
//--------------------------------------------------------------------------
private class UndoAction extends AbstractAction
{
public UndoAction( String text )
{
super( text );
setEnabled( false );
}
public void actionPerformed( ActionEvent e )
{
try {
undo.undo();
}
catch( CannotUndoException ex )
{
System.out.println( "Unable to undo: " + ex);
ex.printStackTrace();
}
catch( Exception ec )
{
System.err.println( "UndoAction General Exception: Why this error???" );
ec.printStackTrace();
}
updateUndoState();
redoAction.updateRedoState();
}
protected void updateUndoState()
{
if( undo.canUndo() )
{
setEnabled( true );
}
else
{
setEnabled( false );
}
}
}
//--------------------------------------------------------------------------
private class RedoAction extends AbstractAction
{
public RedoAction( String text )
{
super( text );
setEnabled( false );
}
public void actionPerformed( ActionEvent e )
{
try {
undo.redo();
}
catch ( CannotRedoException ex )
{
System.out.println("Unable to redo: " + ex);
ex.printStackTrace();
}
catch( Exception ec )
{
System.err.println( Action.NAME + " Why this error???" );
ec.printStackTrace();
}
updateRedoState();
undoAction.updateUndoState();
}
protected void updateRedoState()
{
if ( undo.canRedo() )
{
setEnabled( true );
}
else
{
setEnabled( false );
}
}
}
//--------------------------------------------------------------------------
// Listener for undo manager
protected class MyUndoableEditListener implements UndoableEditListener
{
public void undoableEditHappened( UndoableEditEvent e )
{
//Remember the edit and update the menus
undo.addEdit( e.getEdit() );
undoAction.updateUndoState();
redoAction.updateRedoState();
}
}
//--------------------------------------------------------------------------
public static void main( String[] args )
{
UndoManagerTest mainFrame = new UndoManagerTest();
mainFrame.setSize( 400, 400 );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setTitle( "UndoManager Test" );
mainFrame.setVisible( true );
}
//--------------------------------------------------------------------------
}
***************************************************************************
Here is the Stack Trace:
***************************************************************************
java.lang.ArrayIndexOutOfBoundsException: -1
at javax.swing.text.AbstractDocument$BranchElement.getEndOffset(AbstractDocument.java:2333)
at javax.swing.text.PlainView.getLineWidth(PlainView.java:631)
at javax.swing.text.PlainView.updateDamage(PlainView.java:507)
at javax.swing.text.PlainView.removeUpdate(PlainView.java:434)
at javax.swing.plaf.basic.BasicTextUI$RootView.removeUpdate(BasicTextUI.java:1501)
at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.removeUpdate(BasicTextUI.java:1741)
at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:242)
at javax.swing.text.AbstractDocument$DefaultDocumentEvent.undo(AbstractDocument.java:2799)
at javax.swing.undo.UndoManager.undoTo(UndoManager.java:210)
at javax.swing.undo.UndoManager.undo(UndoManager.java:275)
at UndoManagerTest$UndoAction.actionPerformed(UndoManagerTest.java:107)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1839)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)
at java.awt.Component.processMouseEvent(Component.java:5100)
at java.awt.Component.processEvent(Component.java:4897)
at java.awt.Container.processEvent(Container.java:1569)
at java.awt.Component.dispatchEventImpl(Component.java:3615)
at java.awt.Container.dispatchEventImpl(Container.java:1627)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)
at java.awt.Container.dispatchEventImpl(Container.java:1613)
at java.awt.Window.dispatchEventImpl(Window.java:1606)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
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)
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic