Multiplexing an interface

Many composite parts will have the notion of an active child. Such parts may want to dynamically attach a dependency to the child that is currently active.

For example, we may want to create a view that arranges its children in a tab folder. The parent may want to set its own name and icon to match that of its active child. We could accomplish this using the following pattern:

We will refer to this as multiplexing the INameable interface.

In general, the multiplexer pattern works like this: Since this pattern is quite common, we supply a Multiplexer class to support it. Clients that supply new types of interfaces using the org.eclipse.core.component.types extension point can also supply a multiplexed version of their interface. The multiplexed version will: Clients using the Multiplexer don't need to know the details of multiplexing each interface. They can simply attach an INameable to the multiplexer as though it was a part, and attach the multiplexer to each child part as though it were an INameable. This is shown in the following example, use of the multiplexer has been highlighted in red. Multiplexers need to be explicitly disposed.

public class MultiplexNameView implements IDisposable {
    private Multiplexer mplex;
   
    private ISite view1;
    private ISite view2;
   
    private Listener focusListener = new Listener() {
        /* (non-Javadoc)
         * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
         */
        public void handleEvent(Event e) {
            if (e.widget == view1.getControl()) {
                mplex.setActivePart(view1);
            } else if (e.widget == view2.getControl()) {
                mplex.setActivePart(view2);
            }        
        }
       
    };
   
    /**
     * Component constructor. Do not invoke directly.
     */
    public MultiplexNameView(Composite parent, IPartFactory factory, INameable name) throws CoreException {
       
        // Create a multiplexer. Redirect our INameable to the multiplexer
        mplex = new Multiplexer(new ContainerContext().addInstance(INameable.class, name));
       
        // Create a resource navigator. Give the navigator a multiplexed INameable, but use
        // defaults for all of the other interfaces.
        ContainerContext viewContext1 = new ContainerContext()
            .delegateTo(INameable.class, mplex);
        view1 = factory.createView(
                IPageLayout.ID_RES_NAV, parent, viewContext1, null);
        view1.getControl().addListener(SWT.Activate, focusListener);
       
        // Create property view. Give the properties view a multiplexed INameable, but use
        // defaults for everything else.
        ContainerContext viewContext2 = new ContainerContext()
            .delegateTo(INameable.class, mplex);
        view2 = factory.createView(IPageLayout.ID_PROP_SHEET, parent, viewContext2, null);
        view2.getControl().addListener(SWT.Activate, focusListener);
       
        // Make the navigator active initially
        mplex.setActivePart(view1);
       
        parent.setLayout(new FillLayout());       
    }
   
    /* (non-Javadoc)
     * @see org.eclipse.core.component.IDisposable#dispose()
     */
    public void dispose() {
        mplex.dispose();
    }
}