Search code examples
eclipseeclipse-rcpe4

Toolbar undo redo Eclipse RCP


I basically have the following:

<menuContribution locationURI="menu:com.myprog.menus.edit?after=undo">
<command commandId="org.eclipse.ui.edit.undo" label="Undo" style="push">
</command>
<command commandId="org.eclipse.ui.edit.redo" label="Redo" style="push">
</command>
</menuContribution>

================================

<menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar">     
     <toolbar id="com.myprog.ui.undo">
        <command commandId="org.eclipse.ui.edit.undo" label="Undo" style="push">
        </command>
        <command commandId="org.eclipse.ui.edit.redo" label="Redo" style="push">
        </command>
     </toolbar>
</menuContribution>

This is a Eclipse 3.X RCP running using the compatibility layer on Eclipse 4.

The problem is that when I open any of my text editors the undo/redo toolbar buttons doesn't become enabled or disabled correctly unless I use the mouse to select mutliple lines or when I click on any other tab (project explorer for example) and then click back into the editor.

Knowing that this happens I expected the Edit menu undo/redo to be messed up as well, but I found that they are enabled and disabled correctly according to what I do in the editor.

Also it should be noted that no matter what is the state of the toolbar undo/redo buttons, keyboard shortcuts Ctrl+Z and Ctrl+Y work as expected.

What can be possibly causing this? To have the toolbar buttons only not working is so weird. I would have felt better if all the undo/redo mechanism didn't work.


Solution

  • Using greg-449's answer:

    IEventBroker eventBroker = (IEventBroker)PlatformUI.getWorkbench().getService(IEventBroker.class);

    eventBroker.send(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, UIEvents.ALL_ELEMENT_ID);

    I have used it in a documentChanged listener by doing the following:

        try {
           TextEditor editor = (TextEditor)((IEditorReference) editorReference).getEditor(false);
           if(editor != null) {
              editor.getDocumentProvider().getDocument(editor.getEditorInput()).addDocumentListener(new IDocumentListener() {
                 @Override
                 public void documentChanged(DocumentEvent event) {
                    IEventBroker eventBroker = (IEventBroker)PlatformUI.getWorkbench().getService(IEventBroker.class);
                    eventBroker.post(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, UIEvents.ALL_ELEMENT_ID);
                 }
    
                 @Override
                 public void documentAboutToBeChanged(DocumentEvent event) {
                 }
              });
           }  
        }
        catch (ClassCastException e) {
        }
    

    I, however, was facing a problem. The problem was that if the edit is exactly one character the undo button doesn't get enabled. It however worked flawlessly if the edit goes beyond one character.

    Debugging further, I noticed that another editor, which I didn't implement and had undo/redo working correctly, had the call-stack starting from the selectionChanged event and not the documentChanged.

    I have mentioned in my question that if I select multiple lines using the mouse the undo/redo becomes enabled and this is obviously the selectionChanged.

    So basically, I have come to this solution:

           try {
               final TextEditor editor = (TextEditor)((IEditorReference) partRef).getEditor(false);
               editor.getDocumentProvider().getDocument(editor.getEditorInput()).addDocumentListener(new IDocumentListener() {
                  
                  @Override
                  public void documentChanged(DocumentEvent event) {
                     editor.getSelectionProvider().setSelection(editor.getSelectionProvider().getSelection());
                  }
                  
                  @Override
                  public void documentAboutToBeChanged(DocumentEvent event) {
                  }
               });
            }
            catch (ClassCastException e) {
            }
    

    What I am doing now is basically triggering the selectionChanged event which updates the undo/redo correctly from the start.