/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.papyrus.infra.core.ui.IRevealSemanticElement;
import org.eclipse.papyrus.infra.widgets.Activator;
import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IGraphicalContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IHierarchicContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.dialogs.SelectionDialog;
/**
* A Dialog for selecting values. The values are displayed as a Tree. If only
* some of the values of this Tree should be selectable, you should pass a {@link IHierarchicContentProvider} to this dialog.
*
* @author Camille Letavernier
*
*/
public class TreeSelectorDialog extends SelectionDialog implements ITreeSelectorDialog {
private ILabelProvider labelProvider;
private ITreeContentProvider contentProvider;
private TreeViewer treeViewer;
private Label descriptionLabel;
private Object input = null;
private final Set<ICommitListener> commitListeners = new HashSet<ICommitListener>();
/**
*
* Constructor.
*
* @param parentShell
* The parent shell in which this dialog will be opened
*/
public TreeSelectorDialog(Shell parentShell) {
super(parentShell);
}
/**
* Sets the label provider for this dialog
*
* @param provider
*/
public void setLabelProvider(ILabelProvider provider) {
labelProvider = provider;
if(treeViewer != null) {
treeViewer.setLabelProvider(labelProvider);
}
}
/**
* Sets the ContentProvider for this dialog
* The ContentProvider may be a {@link IHierarchicContentProvider}
*
* @param provider
* The content provider for this dialog. May be a {@link IHierarchicContentProvider}
*/
public void setContentProvider(ITreeContentProvider provider) {
contentProvider = provider;
if(treeViewer != null) {
initViewerAndProvider();
}
if(contentProvider instanceof ICommitListener) {
commitListeners.add((ICommitListener)contentProvider);
}
}
protected void initViewerAndProvider() {
treeViewer.setContentProvider(contentProvider);
if(treeViewer.getInput() == null) {
doSetInput();
}
List<?> initialSelection = getInitialElementSelections();
if(contentProvider instanceof IRevealSemanticElement) {
((IRevealSemanticElement)contentProvider).revealSemanticElement(initialSelection);
} else if(!initialSelection.isEmpty()) {
//FIXME : When we use an EncapsulatedContentProvider, we'll not get into this case,
//even if the encapsulated provider is not a IRevealSemanticElement
treeViewer.setSelection(new StructuredSelection(initialSelection.get(0)), true);
}
}
@Override
protected Composite getDialogArea() {
return (Composite)super.getDialogArea();
}
@Override
public void create() {
super.create();
descriptionLabel = new Label(getDialogArea(), SWT.WRAP);
descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
treeViewer = new TreeViewer(getDialogArea(), SWT.BORDER);
treeViewer.setFilters(new ViewerFilter[]{ new PatternFilter() });
if(labelProvider != null) {
treeViewer.setLabelProvider(labelProvider);
}
if(contentProvider != null) {
initViewerAndProvider();
}
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
Object selectedElement = null;
if(selection instanceof IStructuredSelection && !selection.isEmpty()) {
IStructuredSelection sSelection = (IStructuredSelection)selection;
selectedElement = sSelection.getFirstElement();
}
if(contentProvider instanceof IHierarchicContentProvider) {
boolean isValidValue = ((IHierarchicContentProvider)contentProvider).isValidValue(selectedElement);
if(contentProvider instanceof IAdaptableContentProvider) {
selectedElement = ((IAdaptableContentProvider)contentProvider).getAdaptedValue(selectedElement);
}
if(isValidValue) {
setResult(Collections.singletonList(selectedElement));
} else {
setResult(Collections.EMPTY_LIST);
}
getOkButton().setEnabled(isValidValue);
}
}
});
treeViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
if(getOkButton().isEnabled()) {
okPressed();
}
}
});
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.minimumHeight = 300;
data.minimumWidth = 300;
treeViewer.getTree().setLayoutData(data);
if(contentProvider instanceof IGraphicalContentProvider) {
IGraphicalContentProvider graphicalContentProvider = (IGraphicalContentProvider)contentProvider;
Composite beforeTreeComposite = new Composite(getDialogArea(), SWT.NONE);
beforeTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
beforeTreeComposite.setLayout(new FillLayout());
graphicalContentProvider.createBefore(beforeTreeComposite);
beforeTreeComposite.moveAbove(treeViewer.getTree());
Composite afterTreeComposite = new Composite(getDialogArea(), SWT.NONE);
afterTreeComposite.setLayout(new FillLayout());
afterTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
graphicalContentProvider.createAfter(afterTreeComposite);
}
getShell().setDefaultButton(null);
getButton(OK).setFocus();
getShell().setImage(Activator.getDefault().getImage("/icons/papyrus.png")); //$NON-NLS-1$
getShell().pack();
}
/**
* Sets the description for this Dialog. The description is displayed on
* top of the dialog
*
* @param description
* The description for this dialog
*/
public void setDescription(String description) {
descriptionLabel.setText(description);
}
/**
* Get the TreeViewer used by this dialog
*
* @return
* The TreeViewer associated to this dialog
*/
protected TreeViewer getViewer() {
return treeViewer;
}
/**
* Sets the input object for this dialog's TreeViewer
*
* @param input
*/
public void setInput(Object input) {
this.input = input;
}
// @Deprecated
// //Unused
// public List<Object> getAdaptedInitialSelection() {
// if(contentProvider instanceof IAdaptableContentProvider) {
// List<Object> result = new LinkedList<Object>();
// for(Object object : getInitialElementSelections()) {
// result.add(((IAdaptableContentProvider)contentProvider).getContainerValue(object));
// }
// return result;
// } else {
// return super.getInitialElementSelections();
// }
// }
private void doSetInput() {
if(input == null) {
//Default non-null input for IStaticContentProvider (input-independent)
treeViewer.setInput(""); //$NON-NLS-1$
} else {
treeViewer.setInput(input);
}
}
@Override
public void okPressed() {
for(ICommitListener listener : commitListeners) {
listener.commit(null);
}
super.okPressed();
}
}