Thursday, April 26, 2007

Synchronizing Views with a GEF Editor

View synchronizing is one of the fundamental features for most Eclipse workbench apps. When using a GEF editor, you can use additional views to provide more targeted information about the selection, or even allow editing. There is a lot of good information about this topic - both in the eclipse docs and in the newsgroups. However, I think I can augment that with a concise set of steps for getting this task done quickly.

In this post, I'll talk about how to easily allow views to respond to selection events in an editor.

  1. First, you will need to make sure events are being properly fired from your editor. Since a default selection provider is provided by the GEF Graphical Editor, this is handled for you if you are extending it.

  2. Next, you need to watch for these selection events in your views. This is done by simply adding a postSelectionListener to the page during createPartControl in the view:

  3. getSite().getPage().addPostSelectionListener(yourPageSelectionListener);

    It is important to note here that you can't use the other add method that allows filtering by workbench part. This does not work for editors. I have filed an enhancement request to get this added, but it wouldn't be until 3.4 at the earliest since 3.3 is at API freeze.

  4. If all you wanted was to get selection events of your edit parts, you're done. However, in my designs, I usually like to hide the edit parts from view outside the editor. For this, you will need to use the Eclipse adapter mechanism. In your edit part getAdapter method, you have the opportunity to do any pre-processing.

    Lets say that your edit parts are shapes and you want to find out the color, and size of them without exposing the edit parts to the view:
    1. First, put an interface in a shared plugin called: IShapeInfo with getters for color and size
    2. In Shape.getAdapter, when IShapeInfo is passed in, return an implementation that provides size and color. (You can implement IShapeInfo in Shape, create an anonymous inner class, etc.)
    3. In your view's pageSelectionListener:


//Get the selection as a list
StructuredSelection ss = (StructuredSelection) selection;
List sList = ss.toList();
/**
* Create a list of objects to show
*/
for (Iterator iterator = sList.iterator(); iterator.hasNext();) {
Object name = iterator.next();
//See if it implements IAdaptable
if (name instanceof IAdaptable) {
//See if the IShapeInfo is available as an adapter
Object o = ((IAdaptable)name).getAdapter(IShapeInfo.class);
if(o != null) {
IShapeInfo info = (IShapeInfo)o;
/** Now you can get size and color from the selected Object
}
}
}

Thats it. All you have to do is customize the interface and you can get custom information back from your edit parts - or any other selection - without exposing class details.

2 comments:

Unknown said...

Adam,

Thank you for your post. It ‘s been very useful. I would like to ask you an aditional question:

In my case I have a gef editor (extended shapes example) and an outline view (outline extending org.eclipse.ui.views.contentoutline.ContentOutlinePage, not gef outline. (It could be any other additional view).

How to interact programmatically with the view which is out of focus (editor is in focus)? Both the editor and the view are in the same page and are visible. My listener has detected the editor’s selection, and it has a reference to the view. I send collapseAll from the listener class but the view remains intact . Any idea what could be missing? (I’m eclipse beginner)

Thanks, vladimir

Saint Saul said...

Very useful post, probably saved me a few hours of digging through the GEF API. Thanks.