/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.util.wizard;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.IWizardNode;
import org.eclipse.jface.wizard.WizardSelectionPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import eu.esdihumboldt.util.Pair;
/**
* Wizard selection page based on a structured viewer.
*
* @author Simon Templer
*/
public abstract class ViewerWizardSelectionPage extends WizardSelectionPage {
private StructuredViewer viewer;
/**
* @see WizardSelectionPage#WizardSelectionPage(String)
*/
protected ViewerWizardSelectionPage(String pageName) {
super(pageName);
}
/**
* Get the size hint for the viewer height.
*
* @return the size hint
*/
protected int getViewerHeightHint() {
return SWT.DEFAULT;
}
/**
* @see IDialogPage#createControl(Composite)
*/
@Override
public void createControl(Composite parent) {
Font font = parent.getFont();
// create composite for page.
Composite outerContainer = new Composite(parent, SWT.NONE);
outerContainer.setLayout(new GridLayout());
outerContainer.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
outerContainer.setFont(font);
Pair<StructuredViewer, Control> viewerControl = createViewer(outerContainer);
viewer = viewerControl.getFirst();
viewerControl.getSecond().setLayoutData(
GridDataFactory.fillDefaults().grab(true, true)
.hint(SWT.DEFAULT, getViewerHeightHint()).create());
// wire viewer
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
viewerSelectionChanged(event.getSelection());
}
});
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
doubleClicked(event);
}
});
Dialog.applyDialogFont(outerContainer);
// apply the initial selection
viewerSelectionChanged(viewer.getSelection());
setControl(outerContainer);
}
/**
* Called when the viewer selection has changed.
*
* @param selection the current selection
*/
protected void viewerSelectionChanged(ISelection selection) {
setErrorMessage(null);
IStructuredSelection ss = (IStructuredSelection) selection;
Object sel = ss.getFirstElement();
if (sel instanceof IWizardNode) {
IWizardNode currentWizardSelection = (IWizardNode) sel;
updateSelectedNode(currentWizardSelection);
}
else {
updateSelectedNode(null);
}
}
/**
* Update the selected node
*
* @param wizardNode the selected wizard node
*/
private void updateSelectedNode(IWizardNode wizardNode) {
setErrorMessage(null);
if (wizardNode == null) {
updateMessage();
setSelectedNode(null);
return;
}
// set the message based on the wizard description
if (wizardNode instanceof ExtendedWizardNode) {
setMessage(((ExtendedWizardNode) wizardNode).getDescription(), INFORMATION);
}
else {
setMessage(null);
}
// set the selected node
setSelectedNode(wizardNode);
}
/**
* @see WizardSelectionPage#setSelectedNode(IWizardNode)
*/
@Override
protected void setSelectedNode(IWizardNode node) {
if (node != null) {
String message = acceptWizard(node);
if (message != null) {
// display warning message
setMessage(message, WARNING);
// disable next
super.setSelectedNode(null);
return;
}
}
super.setSelectedNode(node);
}
/**
* Accepts or doesn't accept a wizard node as a valid selection.
*
* @param wizardNode the wizard node
* @return <code>null</code> if the node is accepted or a reason why it is
* not accepted.
*/
protected String acceptWizard(IWizardNode wizardNode) {
return null;
}
/**
* Update the selected node based on the viewer selection.
*/
protected void updateMessage() {
if (viewer != null) {
ISelection selection = viewer.getSelection();
IStructuredSelection ss = (IStructuredSelection) selection;
Object sel = ss.getFirstElement();
if (sel instanceof IWizardNode) {
updateSelectedNode((IWizardNode) sel);
}
else {
setSelectedNode(null);
}
}
else {
setMessage(null);
}
}
/**
* Called when a double click in the viewer occurs.
*
* @param event the double click event
*/
protected void doubleClicked(DoubleClickEvent event) {
ISelection selection = event.getViewer().getSelection();
IStructuredSelection ss = (IStructuredSelection) selection;
viewerSelectionChanged(ss);
Object element = ss.getFirstElement();
if (element instanceof IWizardNode) {
if (canFlipToNextPage()) {
getContainer().showPage(getNextPage());
return;
}
}
else if (event.getViewer() instanceof TreeViewer) {
TreeViewer viewer = (TreeViewer) event.getViewer();
viewer.setExpandedState(element, !viewer.getExpandedState(element));
}
getContainer().showPage(getNextPage());
}
/**
* Create the structured viewer and set it up with label and content
* providers as well as the input. The viewer must provide
* {@link IStructuredSelection}s with {@link IWizardNode}s.
*
* @param parent the parent composite
* @return the viewer paired with the main control that should fill the
* parent composite
*/
protected abstract Pair<StructuredViewer, Control> createViewer(Composite parent);
}