Community
Participate
Working Groups
'org.eclipse.text.undo.DocumentUndoManager.UndoableTextChange.canUndo()' returns true when last undo operation runed, and 'undoTextChange()' method is also called. expect: return false
Do you have a concrete test case that exhibits the problem?
Please reopen when the requested info has been provided.
please run the testUndoable() method: -------------------------------------------------------------------- public void testUndoable(){ IUndoableOperation operation = new AbstractOperation("test undoable"){ public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } }; final DocumentUndoManager undoManager = new DocumentUndoManager(new Document()); undoManager.addDocumentUndoListener(new IDocumentUndoListener(){ public void documentUndoNotification(DocumentUndoEvent event){ if(event.getEventType() == DocumentUndoEvent.ABOUT_TO_UNDO){ System.out.println("before undo:" + undoManager.undoable()); }else if(event.getEventType() == DocumentUndoEvent.UNDONE){ System.out.println("after undo:" + undoManager.undoable()); } } }); undoManager.connect(new Object()); operation.addContext(undoManager.getUndoContext()); OperationHistoryFactory.getOperationHistory().add(operation); undoManager.transferUndoHistory(undoManager); try{ undoManager.undo(); }catch(ExecutionException e){ e.printStackTrace(); } } ------------------------------------------------------------------- I guess 'DocumentUndoManager.undoable()' should returns false when getting a 'DocumentUndoEvent.UNDONE' notification in a DocumentUndoListener. But true is returned now.
Your example code is badly broken: you create your own operation which always returns 'true' on canUndo(). Also, it is wrong to transfer an operation history from the same manager to itself.
I modified this method: -------------------------------------------------------------------- public void testUndoable(){ IUndoableOperation operation = new AbstractOperation("test undoable"){ public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return null; } }; DocumentUndoManager tempUndoManager = new DocumentUndoManager(new Document()); tempUndoManager.connect(new Object()); operation.addContext(tempUndoManager.getUndoContext()); OperationHistoryFactory.getOperationHistory().add(operation); final DocumentUndoManager undoManager = new DocumentUndoManager(new Document()); undoManager.addDocumentUndoListener(new IDocumentUndoListener(){ public void documentUndoNotification(DocumentUndoEvent event){ if(event.getEventType() == DocumentUndoEvent.ABOUT_TO_UNDO){ System.out.println("When get DocumentUndoEvent.ABOUT_TO_UNDO in DocumentUndoListener, undoable() is: " + undoManager.undoable()); }else if(event.getEventType() == DocumentUndoEvent.UNDONE){ System.out.println("When get DocumentUndoEvent.UNDONE in DocumentUndoListener, undoable() is: " + undoManager.undoable()); } } }); undoManager.connect(new Object()); undoManager.transferUndoHistory(tempUndoManager); try{ System.out.println("Before undo, undoable() is: " + undoManager.undoable()); undoManager.undo(); System.out.println("After undo, undoable() is: " + undoManager.undoable()); }catch(ExecutionException e){ e.printStackTrace(); } } ---------------------------------------------------------- The results: ********************************************************* Before undo, undoable() is: true When get DocumentUndoEvent.ABOUT_TO_UNDO in DocumentUndoListener, undoable() is: true When get DocumentUndoEvent.UNDONE in DocumentUndoListener, undoable() is true After undo, undoable() is: false ********************************************************** 1. My own operation is not always returns 'true' on canUndo(), because undoable() returns false after undo() is called. (see step 4) 2. I create a temp undo manager to transfer an operation history. I think undoable() should return false when the DocumentUndoEvent.UNDONE is reveived in DocumentUndoListener. But it returns true.
>I think undoable() should return false when the DocumentUndoEvent.UNDONE is >reveived in DocumentUndoListener. No. As said before, org.eclipse.core.commands.operations.AbstractOperation.canUndo() and only this used by the undo manager to tell whether undo is possible. Your example operation does not override this and hence what we see is expected. Telling me that your operation would not always return 'true' and then providing a test case that does otherwise is of no help at all. Just FYI: I quickly replaced your bogus operation class with a correct implementation (org.eclipse.text.undo.DocumentUndoManager.UndoableTextChange) and that's what you get: Before undo, undoable() is: true When get DocumentUndoEvent.ABOUT_TO_UNDO in DocumentUndoListener, undoable() is: true When get DocumentUndoEvent.UNDONE in DocumentUndoListener, undoable() is: true After undo, undoable() is: false So, please do not reopen this again.
Argh! OK, I see now what you meant.
Sorry, At last time, I missed the code: -------------------------------------------------- public boolean canUndo() { return false; } -------------------------------------------------- Thanks & best regards, ~leigh
Exactly ;-) That's how I modified the test case already. One problem happens when transfering the contexts: for internal purpose this is itself registered as (text) operation and seems to have a little problem, especially when the current operation is not a text operation (UndoableTextChange). In your test case the correct output would be: Before undo, undoable() is: 'false' After undo, undoable() is: 'false' As the canUndo() returns false and the operation isn't a text operation. If we change the test case so that canUndo() returns 'true' and the ops return an OK status instead of illeagal 'null' we should expect: Before undo, undoable() is: 'true' After undo, undoable() is: 'false' NOTE: no events will be sent out as the operation wasn't a document change. Now, we have to look at the case where a document op is on the stack: there we have indeed a bug.
Fixed in HEAD. Available in builds > I20071122-0010.
Now, UndoableTextChange.canUndo() is right. Closed the thread.