Monday, July 9, 2012

Eclipse RCP - How to save view layouts and state?


Introduction:

Saving the state of the application and reopening the application in the same state as previously opened vastly improves user experience. This article explains how to save the layout and state of the views in your application.

Saving Views and Layout:

First of all, you need to enable saving and restoring application state at workbench level. Make sure you override initialize method in your ApplicationWorkbenchAdvisor and add configurer.setSaveAndRestore(true);

@Override
public void initialize(final IWorkbenchConfigurer configurer) {
super.initialize(configurer);
configurer.setSaveAndRestore(true);
}

Adding this automatically saves opens views along with their layouts and makes sure they are reopened appropriately in the same layout. Isn't that amazing? Almost half of our work is done just by adding the above code block to ApplicationWorkbenchAdvisor. The remaining thing is saving the internal view state (i.e saving details of inside the view) .

Saving View State:

Let's say you have a navigator view in your perspective which displays a tree. By adding the above code block, the navigator view would be reopened in the same spot when application reopens again. But, the internals of navigator view would be lost. For example, if the tree had few selections and few nodes opened, they would be lost. Below, I'll explain how to preserve tree selections in your view.

1) Override saveState method (from ViewPart) in your view.

@Override
public void saveState(final IMemento memento) {
IStructuredSelection sel = (IStructuredSelection)this.treeViewer.getSelection();
if (sel.isEmpty()) {
return;
}
memento = memento.createChild("tree-selections");
Iterator iter = sel.iterator();
while (iter.hasNext()) {
String nodeName = iter.next();
memento.createChild("selected-nodes", nodeName);
}
}

IMemento provides way for user to store the application state in XML. User does not have to deal with XML directly and IMemento API takes care of it. When application is closed, if a view is open, it's saveState method is called before it is closed. This way, internal state of the view can be persisted before it is closed.

Restoring View State:

If you want to restore your view state (from the saved memento), you need to override the init method with memento i.e override this method

public void init(IViewSite site, IMemento memento) throws PartInitException {}

instead of

public void init(IViewSite site) throws PartInitException {}

Then, you can read the contents of the memento and restore view's internal state.

// Stores the memento so that it can be used after view is created

@Override
public void init(final IViewSite site, final IMemento memento) throws PartInitException {
init(site);
this.memento = memento;
}

@Override
public void createPartControl(Composite parent) {
// Create view here - For example, create tree viewer here

restoreState();
}

// Method which reads memento and sets selections on the tree
private void restoreState() {
IMemento selectionsMomento = this.memento.getChild("tree-selections");
if (selectionsMomento != null) {
IMemento selectedNodes[] = selectionsMomento.getChildren("selected-nodes");
if (selectedNodes.length > 0) {
ArrayList selections = new ArrayList(selectedNodes.length);
for (int i = 0; i<selectedNodes.length; i++) {
String id = selectedNodes[i].getID();
if (id != null) {
selections.add(id);
}
}

this.treeViewer.setSelection(new StructuredSelection(selections));
}
}
}

The contents of the view is created in createPartControl. Once the contents are created, it's state is set by using the restoreState method, which uses memento to get the internal state of the view last time. Above, we get selected node names from the memento and set tree selection appropriately.

Conclusion:

In this article, we saw how to preserve view layout and it's internal state so that views are reopened in exactly the same way as it was closed last time. In the next one, we'll see how to preserve editor layout and it's state.

No comments:

Post a Comment