1

I have a view where I have two tree viewers. In the createPartControl() how I can set the selectionProviders for both the views. It takes either one of them.

Here is my snippet. The View code:

IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPartSite activePartSite = workbenchWindow.getActivePage().getActivePart().getSite();
activePartSite.setSelectionProvider(inputTreeViewer);
activePartSite.setSelectionProvider(compositeTreeViewer);

// Here the last line the selection provider code for the top one. 
// Hence I only get selections from the second tree. 

How can we solve the problem? I tried with inheriting the view class from ISelectionProvider and overriding getSelection() method. But that was not of any help.

Can someone suggest something?

Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79
Srikant Barik
  • 133
  • 2
  • 12
  • I see you're new to SO. If you feel an answer solved the problem, please mark it as 'accepted' by clicking the green check mark. This helps keep the focus on older posts which still don't have answers. – Rüdiger Herrmann Dec 05 '16 at 21:39

2 Answers2

1

I suggest to add a focus listener to each of the trees and call partSite.setSelectionProvider() with the currently focused tree viewer. For example:

treeViewer1.getTree().addListener( SWT.FocusIn, event -> site.setSelectionProvider( treeViewer1 ) );
treeViewer2.getTree().addListener( SWT.FocusIn, event -> site.setSelectionProvider( treeViewer2 ) );

I'll leave it as an exercise to the reader to remove the listener-duplication.

Alternatively, you can create a proxy selection provider that listens for selection changes in both tree viewers and propagates the most recent selection. Something along these lines:

public class ProxySelectionProvider implements ISelectionProvider {

  private ISelection selection;
  private final Collection<ISelectionChangedListener> listeners;

  public ProxySelectionProvider( StructuredViewer...  viewers ) {
    listeners = new ArrayList<>();
    selection = StructuredSelection.EMPTY;
    for( StructuredViewer viewer : viewers ) {
      ISelectionChangedListener selectionListener = this::selectionChanged;
      viewer.addSelectionChangedListener( selectionListener );
      viewer.getControl().addDisposeListener( event -> viewer.removeSelectionChangedListener( selectionListener ) );
    }
  }

  @Override
  public void addSelectionChangedListener( ISelectionChangedListener listener ) {
    listeners.add( listener );
  }

  @Override
  public void removeSelectionChangedListener( ISelectionChangedListener listener ) {
    listeners.remove( listener );
  }

  @Override
  public ISelection getSelection() {
    return selection;
  }

  @Override
  public void setSelection( ISelection selection ) {
    this.selection = selection;
  }

  private void selectionChanged( SelectionChangedEvent event ) {
    selection = event.getSelection();
    notifyListeners();
  }

  private void notifyListeners() {
    SelectionChangedEvent event = new SelectionChangedEvent( this, selection );
    new ArrayList<>( listeners ).forEach( listener -> listener.selectionChanged( event ) );
  }
}

Use the selection provider like this:

ISelectionProvider selectionProvider = new ProxySelectionProvider( treeViewer1, treeViewer2 );
IWorkbenchPartSite partSite = workbenchWindow.getActivePage().getActivePart().getSite();
partSite.setSelectionProvider( selectionProvider );
Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79
  • addListener() method accepts only int,Listener as the parameters.How do I set the selectionProviders as the second parameter.I had tried with treeviewer.getControl.addFocusLisnter() earlier but it did not yield any result. – Srikant Barik Dec 05 '16 at 13:29
  • Also I read somewhere setSelectionProvider() has to be called on the activesite inside createPartControl() method.So by calling it inside the focus listener it is not registering it as a selection provider. – Srikant Barik Dec 05 '16 at 13:34
  • The example code uses a lambda expression that is equivalent to `Listener::handleEvent()`. If `setSelectionProvider()` has to be called inside `createPartControl()`, then you need to take the alternative approach and use a proxy selection service. – Rüdiger Herrmann Dec 05 '16 at 13:51
  • Can you explain a bit more about the approach?I have never worked with proxy selection service. – Srikant Barik Dec 05 '16 at 14:31
-1

I solved this problem using this approach.

public class SelectionProviderAdapater implements IPostSelectionProvider {
    public class InternalListener implements ISelectionChangedListener, FocusListener {
        @Override
        public void focusGained(FocusEvent e) {
            doFocusChanged(e.widget);
        }

        @Override
        public void focusLost(FocusEvent e) {
        }

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            doSelectionChanged(event);
        }
    }

    /**
     * The array of viewers.
     */
    private StructuredViewer[] viewers;

    /**
     * The current viewer in focus.
     */
    private StructuredViewer viewerInFocus;

    /**
     * The list of selection changed listeners.
     */
    private final ListenerList selectionChangedListeners = new ListenerList();

    /**
     * The list of post selection changed listeners.
     */
    private final ListenerList postSelectionChangedListeners = new ListenerList();

    /**
     * The internal listener instance.
     */
    private final InternalListener internalListener = new InternalListener();

    /**
     * The internal post selection listener instance.
     */
    private final ISelectionChangedListener internalPostSelectionListener = new ISelectionChangedListener() {
        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            doPostSelectionChanged(event);
        }
    };

    @Override
    public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
        postSelectionChangedListeners.add(listener);
    }

    @Override
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        selectionChangedListeners.add(listener);
    }

    /**
     * Sets the viewer in focus and fires selection change events.
     *
     * @param control
     *            The {@link Widget} that has gained focus.
     */
    private void doFocusChanged(Widget control) {
        for (StructuredViewer viewer : viewers) {
            if (viewer.getControl() == control) {
                propagateFocusChanged(viewer);
                return;
            }
        }
    }

    /**
     * Fires post selection changed events if the {@link SelectionChangedEvent}
     * 's selection provider is the current viewer in focus.
     *
     * @param event
     *            The selection changed event.
     */
    private void doPostSelectionChanged(SelectionChangedEvent event) {
        ISelectionProvider provider = event.getSelectionProvider();
        if (provider == viewerInFocus) {
            firePostSelectionChanged();
        }
    }

    /**
     * Fires selection changed events if the {@link SelectionChangedEvent}'s
     * selection provider is the current viewer in focus.
     *
     * @param event
     *            The selection changed event.
     */
    private void doSelectionChanged(SelectionChangedEvent event) {
        ISelectionProvider provider = event.getSelectionProvider();
        if (provider == viewerInFocus) {
            fireSelectionChanged();
        }
    }

    /**
     * Notifies post selection changed listeners of a selection changed event.
     */
    private void firePostSelectionChanged() {
        if (postSelectionChangedListeners != null) {
            SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());

            Object[] listeners = postSelectionChangedListeners.getListeners();
            for (Object listener : listeners) {
                ISelectionChangedListener selectionChangedListener = (ISelectionChangedListener) listener;
                selectionChangedListener.selectionChanged(event);
            }
        }
    }

    /**
     * Notifies selection changed listeners of a selection changed event.
     */
    private void fireSelectionChanged() {
        if (selectionChangedListeners != null) {
            SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());

            Object[] listeners = selectionChangedListeners.getListeners();
            for (Object listener : listeners) {
                ISelectionChangedListener selectionChangedListener = (ISelectionChangedListener) listener;
                selectionChangedListener.selectionChanged(event);
            }
        }
    }

    @Override
    public ISelection getSelection() {
        if (viewerInFocus != null) {
            return viewerInFocus.getSelection();
        }
        return StructuredSelection.EMPTY;
    }

    public StructuredViewer getViewerInFocus() {
        return viewerInFocus;
    }

    /**
     * Sets the viewer as the viewer in focus and fires selection changed
     * events.
     *
     * @param viewer
     *            The new viewer in focus.
     */
    private void propagateFocusChanged(StructuredViewer viewer) {
        if (viewer != viewerInFocus) {
            viewerInFocus = viewer;
            fireSelectionChanged();
            firePostSelectionChanged();
        }
    }

    @Override
    public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
        postSelectionChangedListeners.remove(listener);
    }

    @Override
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        selectionChangedListeners.remove(listener);
    }

    @Override
    public void setSelection(ISelection selection) {
        if (viewerInFocus != null) {
            viewerInFocus.setSelection(selection);
        }
    }

    /**
     * Sets the selection on the current viewer in focus.
     *
     * @param selection
     *            The selection to set.
     * @param reveal
     *            true if the selection is to be made visible, and false
     *            otherwise
     */
    public void setSelection(ISelection selection, boolean reveal) {
        if (viewerInFocus != null) {
            viewerInFocus.setSelection(selection, reveal);
        }
    }

    /**
     * Sets the collection of viewers to be monitored by this mediator.
     *
     * @param newViewers
     *            The collection of viewers.
     */
    public void setViewers(Collection<? extends StructuredViewer> newViewers) {
        // Remove listeners from any previous viewers.
        if (viewers != null) {
            for (StructuredViewer viewer : viewers) {
                viewer.removeSelectionChangedListener(internalListener);
                viewer.removePostSelectionChangedListener(internalPostSelectionListener);
                Control control = viewer.getControl();
                if (!control.isDisposed()) {
                    control.removeFocusListener(internalListener);
                }
            }
        }
        viewers = null;
        viewerInFocus = null;

        if (newViewers != null) {
            viewers = newViewers.toArray(new StructuredViewer[newViewers.size()]);
            for (StructuredViewer viewer : viewers) {
                viewer.addSelectionChangedListener(internalListener);
                viewer.addPostSelectionChangedListener(internalPostSelectionListener);
                Control control = viewer.getControl();
                control.addFocusListener(internalListener);
                if (control.isFocusControl()) {
                    propagateFocusChanged(viewer);
                }
            }
        }
    }
}

Create an instance of this class in your view.Set the viewers using setViewers() method which are needed to be listened for selection.Then set it as the selection provider.It should start working.

Srikant Barik
  • 133
  • 2
  • 12