Monday, July 28, 2008

ResourceSelectionDialog: adding filter capabilities

When working on plugins once in a while we hit a wall. We need to implement some functionality, it already exists in eclipse in some form - but it is not exactly what we want. For example, when you want a user to select some resources from the workspace - ResourceSelectionDialog provides the functionality needed. Unfortunately, RSD does not provide a way for filtering the resources that can be chosen. RSD displays *all* the resources from a given root (some IContainer - workspace root, project or a folder) - there is no way to tell RSD that we want it to filter some resources.

When we are stuck with this situation, we have the following solutions:

  1. Copy the code (in this case RSD) and modify it to our purposes. A major issue with this approach is that not only, but you need to also copy all other classes that are used by RSD that are not made public by the plugin. Depending on the case these might be few or a lot.
  2. Another approach is to derive a class from RSD (though the documentation says that we should not) and implement the required functionality. In the case of RSD, we need to override the createDialogArea because the getResourceProvider is private and we need to add functionality into the getResourceProvider.
  3. Create a patch to RSD and submit to eclipse and hope that it will get included. Seeing that this request is made almost 3 years back (see bug 91227 and bug 124338)  and still there is not much of movement, you must be very lucky for this to get included and be ready for your plugin release.
  4. The one option I want to discuss in this post is to bend the RSD to work your way. GoF has a nice little pattern for this - they call it adapter.
From the 'Design Patterns' book:

An adpater 
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
We use a variant of adapter pattern to make RSD to accept resources that also implement filtering.

What we need is a parallel hierarchy of classes for IResource - folder, project and file that wraps a real IFolder, IFile, IProject and also provides filtering. We create classes FileDelegate, FolderDelegate and ProjectDelegate and use eclipse's source -> create delegate methods to delegate all the functions wrapped object, except for those methods that return a IResource(s). Each of the methods that return a IResource(s) uses the delegate to get the returned IResource(s)  and creates the appropriate delegate object(s) and returns it. We wrap RSD also into another class and allow the user to set a validator onto this class. Each of the resource delegates gets a reference to this class and uses the validation from this class. We also need a little cleanup so that when searching for the resources we do not go higher than the root object that is passed to the RSD.

You can access the related code from Google code eclipse-snippets project.

No comments: