Saturday, October 10, 2009

Eclipse RCP - Saving Editor State and Layout

Introduction:

In the previous article, we saw how to save view layout and state. In this article, we will see how to save editor layout and state.

Saving Editor State and Layout:

Saving editor state is slightly more complicated than saving the view state. Below are the steps which needs to be done to save the editor state.

1) First of all, make sure that initialize method in ApplicationWorkbenchAdvisor has save and restore enabled. Add the following line to the initialize method for this: configurer.setSaveAndRestore(true);

2) The editor input needs to implement getPersistable() method and should return an IPersistableElement. Mostly, my editor input itself implements IPersistableElement and so getPersistable() would return this. IPersistableElement is responsible for saving the current state of the element and also tells the id of the factory which is responsible for reconstructing the editor from current state of the application. The methods (listed in points 4 and 5 below) need to be implemented in IPersistableElement.

3) The editor input needs to implement exists() method and make sure that it returns true.

public boolean exists() {
return true;
}

4) Implement saveState method in IPersistableElement - public void saveState(final IMemento memento) {}

This method is responsible to save the current editor state into the memento. See the previous article on how saveState method works for views and it behaves exactly the same for editors too. Make sure to save all the information in memento, which are needed to reconstruct the editor later.

5) Implement getFactoryId method in IPersistableElement - public String getFactoryId() {}

This method should return the id of your IElementFactory which is responsible for re-creating the editor from the saved memento. We will see more about IElementFactory below in 6 and 7.

6) Open plugin.xml and go to extensions tab. Add a new extension point org.eclipse.ui.elementFactories and add a new factory for your editor. Give it an Id (this is the ID which needs to be returned in getFactoryId method in IPersistable element - see point 5 above) and class (the class name which implements IElementFactory).

7) Implement your IElementFactory class. It needs to implement public IAdaptable createElement(final IMemento memento) {} method. This method is passed the IMemento which is saved when application was closed last time. createElement method need to re-create the editor and need to return IAdaptable. IEditorInput is an instanceof IAdaptable. So, for editors, you would typically get info from IMemento, create your IEditorInput (using info from IMemento) and return that.

This is all you need to do to save your editor state and layout. Eclipse takes care of remembering the layout of the editors. Main thing here is, we need to make sure that we persist all state information (in saveState method - point 4) and be able to recreate the editor in exactly the same state (in createElement method - point 7).

How this works?

Behind the scene, whenever the application is closed, getPersistable method for all the open editors is called. If it is not null, then the IPersistableElement's saveState method is called and all the state information is saved into the memento. Also, getFactoryId is called so that eclipse can know which class is responsible for recreating this editor later. This information is saved in <youreclipseworkspacedir>\.metadata\.plugins\org.eclipse.ui.workbench\workbench.xml file. Take a look at this file and you will see that the information saved in memento and also factory information is persisted there.

Note that if getPersistable() returns null, then the state of the editor will not be saved. You can use this in cases where you don't want to save the editor state. For example, if user switches to a different workspace or to a completely different environment, you don't want to save the editor state because they are no longer applicable in the new workspace/environment. In these cases, you could just return null in getPeristable() method.

When application is re-openened, platform reads the workbench.xml file, creates IElementFactory instance and passes it the proper memento. Then, the IElementFactory knows how to recreate the editor from the saved information.

Conclusion:

In this article, we saw how to save editor state and layout so that the application can re-open in exactly the same state as it was closed last time.

3 comments:

Jay said...

Thanks, I found this helpful.

Erik Edlund said...

This was very useful. Thank you!

Timothy Vogel said...

How would you handle the case where the editor to restore is reading a record from the database that has been deleted?