/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.utils.selection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.forms.widgets.Section;
/**
* A selection provider for view parts with more that one viewer. Tracks the
* focus of the viewers to provide the correct selection.
*/
public class ControlSelectionProvider implements IPostSelectionProvider {
/**
* Whether debug is enabled for this provider.
*/
public static boolean DEBUG = false;
/**
* All round listener.
*/
private class MyListener
implements
ISelectionChangedListener,
FocusListener,
Listener {
private final Control myControl;
public MyListener(Control control) {
myControl = control;
}
/*
* @see ISelectionChangedListener#selectionChanged
*/
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (myControl == controlInFocus) {
fireSelectionChanged();
}
}
@Override
public void focusGained(FocusEvent e) {
setFocusControl(myControl);
}
@Override
public void focusLost(FocusEvent e) {
// do not reset due to focus behavior on GTK
// fViewerInFocus= null;
}
@Override
public void handleEvent(Event event) {
if (event.type == SWT.Activate) {
setFocusControl(myControl);
}
}
}
private class PostSelectionListener implements ISelectionChangedListener {
private final Control myControl;
public PostSelectionListener(Control control) {
myControl = control;
}
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (myControl == controlInFocus) {
firePostSelectionChanged();
}
}
}
private final Map<Control, ISelectionProvider> selectionProviders = new HashMap<Control, ISelectionProvider>();
private Control controlInFocus;
private final ListenerList selectionChangedListeners = new ListenerList();;
private final ListenerList postSelectionChangedListeners = new ListenerList();;
public ControlSelectionProvider() {
debug("created"); //$NON-NLS-1$
}
protected void debug(String message) {
if (DEBUG) {
System.out.println(this + ": " + message); //$NON-NLS-1$
}
}
@Override
public String toString() {
return getClass().getSimpleName() + ":" + hashCode(); //$NON-NLS-1$
}
/**
* @param viewers
* All viewers that can provide a selection
* @param viewerInFocus
* the viewer currently in focus or <code>null</code>
*/
public ControlSelectionProvider(StructuredViewer[] viewers,
StructuredViewer viewerInFocus) {
for (final StructuredViewer viewer : viewers) {
addViewer(viewer);
}
if (viewerInFocus != null) {
setFocusControl(viewerInFocus.getControl());
}
}
/**
* @param controls
* @param providers
*/
public ControlSelectionProvider(Control[] controls,
ISelectionProvider[] providers) {
this();
Assert.isNotNull(controls);
Assert.isNotNull(providers);
Assert.isTrue(controls.length == providers.length);
for (int i = 0; i < controls.length; i++) {
addControl(controls[i], providers[i]);
}
}
/**
* Returns the control that currently has focus.
*
* @return the control or <code>null</code>
*/
public Control getFocusControl() {
return controlInFocus;
}
/**
* Returns the selection provider of the current control.
*
* @return the provider or <code>null</code>
*/
public ISelectionProvider getCurrentSelectionProvider() {
if (controlInFocus == null)
return null;
return selectionProviders.get(controlInFocus);
}
/**
* Adds a new control with a specific provider.
*
* @param control
* the control
* @param provider
* the provider
*/
public void addControl(Control control, ISelectionProvider provider) {
debug("added(" + control + ", " + provider + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
final MyListener listener = new MyListener(control);
provider.addSelectionChangedListener(listener);
selectionProviders.put(control, provider);
control.addFocusListener(listener);
control.addListener(SWT.Activate, listener);
if (control instanceof Section) {
final Section s = (Section) control;
for (final Control c : s.getChildren()) {
c.addListener(SWT.Activate, listener);
}
}
if (provider instanceof IPostSelectionProvider) {
final IPostSelectionProvider post = (IPostSelectionProvider) provider;
post.addPostSelectionChangedListener(new PostSelectionListener(
control));
}
}
public void addViewer(StructuredViewer viewer) {
addControl(viewer.getControl(), viewer);
}
/**
* @param control
*/
public void setFocusControl(Control control) {
Assert.isNotNull(control);
if (control == controlInFocus)
return;
debug("focus: " + control); //$NON-NLS-1$
controlInFocus = control;
if (!control.isFocusControl()) {
control.setFocus();
}
final ISelectionProvider provider = selectionProviders.get(control);
if (provider == null)
return;
fireSelectionChanged();
firePostSelectionChanged();
}
private void fireSelectionChanged() {
debug("selectionChanged(" + getCurrentSelectionProvider() + ": " + getSelection() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (selectionChangedListeners != null) {
final SelectionChangedEvent event = new SelectionChangedEvent(this,
getSelection());
final Object[] listeners = selectionChangedListeners.getListeners();
for (final Object listener2 : listeners) {
final ISelectionChangedListener listener = (ISelectionChangedListener) listener2;
listener.selectionChanged(event);
}
}
}
private void firePostSelectionChanged() {
if (postSelectionChangedListeners != null) {
final SelectionChangedEvent event = new SelectionChangedEvent(this,
getSelection());
final Object[] listeners = postSelectionChangedListeners
.getListeners();
for (final Object listener2 : listeners) {
final ISelectionChangedListener listener = (ISelectionChangedListener) listener2;
listener.selectionChanged(event);
}
}
}
@Override
public void addSelectionChangedListener(ISelectionChangedListener listener) {
selectionChangedListeners.add(listener);
}
@Override
public void removeSelectionChangedListener(
ISelectionChangedListener listener) {
selectionChangedListeners.remove(listener);
}
@Override
public void addPostSelectionChangedListener(
ISelectionChangedListener listener) {
postSelectionChangedListeners.add(listener);
}
@Override
public void removePostSelectionChangedListener(
ISelectionChangedListener listener) {
postSelectionChangedListeners.remove(listener);
}
@Override
public ISelection getSelection() {
final ISelectionProvider provider = getCurrentSelectionProvider();
if (provider == null)
return StructuredSelection.EMPTY;
final ISelection selection = provider.getSelection();
debug("getSelection()=" + selection); //$NON-NLS-1$
return selection;
}
/*
* @see ISelectionProvider#setSelection
*/
@Override
public void setSelection(ISelection selection) {
final ISelectionProvider provider = getCurrentSelectionProvider();
if (provider == null)
return;
provider.setSelection(selection);
}
}