/* * 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.selector; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TrayDialog; 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.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; /** * Abstract selection dialog based on a structured viewer. * * @author Simon Templer * @param <T> the type of object that can be selected in the dialog * @param <V> the type of the viewer * @partner 01 / Fraunhofer Institute for Computer Graphics Research */ public abstract class AbstractViewerSelectionDialog<T, V extends StructuredViewer> extends TrayDialog { private static final int NONE_ID = IDialogConstants.CLIENT_ID + 1; private T selected; private V viewer; private final String title; private ViewerFilter[] filters; private final T initialSelection; private final boolean allowNone; private int widthHint; private int heightHint; /** * Constructor. * * @param parentShell the parent shell * @param title the dialog title * @param initialSelection the entity definition to select initially (if * possible), may be <code>null</code> */ public AbstractViewerSelectionDialog(Shell parentShell, String title, T initialSelection) { this(parentShell, title, initialSelection, true, 400, 400); } /** * Constructor. * * @param parentShell the parent shell * @param title the dialog title * @param initialSelection the entity definition to select initially (if * possible), may be <code>null</code> * @param allowNone if selecting the None button is allowed * @param widthHint the width hint for the dialog * @param heightHint the height hint for the dialog */ public AbstractViewerSelectionDialog(Shell parentShell, String title, T initialSelection, boolean allowNone, int widthHint, int heightHint) { super(parentShell); this.title = title; this.initialSelection = initialSelection; this.allowNone = allowNone; this.widthHint = widthHint; this.heightHint = heightHint; } /** * @see Dialog#createContents(Composite) */ @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); updateState(); return control; } /** * @see Window#configureShell(Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(title); } /** * @see Dialog#createDialogArea(Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite page = new Composite(parent, SWT.NONE); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.widthHint = widthHint; // data.minimumHeight = 200; data.heightHint = heightHint; page.setLayoutData(data); GridLayout pageLayout = new GridLayout(1, false); pageLayout.marginLeft = 0; pageLayout.marginTop = 0; pageLayout.marginLeft = 0; pageLayout.marginBottom = 0; page.setLayout(pageLayout); // create tool bar first so that it is on top ToolBarManager manager = new ToolBarManager(SWT.FLAT | SWT.WRAP); ToolBar toolbar = manager.createControl(page); toolbar.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, false, false)); viewer = createViewer(page); setupViewer(viewer, initialSelection); // fill it after viewer creation, so that the viewer can be referenced // in there addToolBarActions(manager); manager.update(false); // dispose the tool bar again, if it is empty if (manager.getSize() == 0) toolbar.dispose(); if (!(viewer.getControl().getLayoutData() instanceof GridData)) { viewer.getControl().setLayoutData( GridDataFactory.fillDefaults().grab(true, true).create()); } viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateState(); } }); viewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (getButton(IDialogConstants.OK_ID).isEnabled()) okPressed(); } }); updateState(); return page; } /** * Create the tree viewer. * * @param parent the parent composite * @return the tree viewer */ protected abstract V createViewer(Composite parent); /** * Add tool bar actions to the entity dialog tool bar. * * @param manager the tool bar manager */ protected void addToolBarActions(ToolBarManager manager) { // add nothing } /** * @see Dialog#createButtonsForButtonBar(Composite) */ @Override protected void createButtonsForButtonBar(Composite parent) { super.createButtonsForButtonBar(parent); if (allowNone) { createButton(parent, NONE_ID, "None", false); } } /** * @see Dialog#buttonPressed(int) */ @Override protected void buttonPressed(int buttonId) { switch (buttonId) { case NONE_ID: this.selected = null; setReturnCode(OK); close(); break; default: super.buttonPressed(buttonId); } } /** * Determines if the given object matches the given filters. * * @param viewer the viewer * @param filters the viewer filters * @param candidate the object to test * @return if the object is accepted by all filters */ public static boolean acceptObject(Viewer viewer, ViewerFilter[] filters, Object candidate) { if (filters == null) return true; for (ViewerFilter filter : filters) if (!filter.select(viewer, null, candidate)) return false; return true; } private void updateState() { Button ok = getButton(IDialogConstants.OK_ID); if (ok != null) { ISelection selection = viewer.getSelection(); if (selection.isEmpty()) ok.setEnabled(false); else { boolean valid = true; if (selection instanceof IStructuredSelection) { if (!acceptObject(viewer, filters, ((IStructuredSelection) selection).getFirstElement())) valid = false; } ok.setEnabled(valid); } } } /** * Setup the tree viewer with label provider, content provider and input. * Don't set any viewer filters as they will be overridden by those provided * through {@link #setFilters(ViewerFilter[])}. * * @param viewer the tree viewer * @param initialSelection the object to select (if possible), may be * <code>null</code> */ protected abstract void setupViewer(V viewer, T initialSelection); /** * @see Dialog#okPressed() */ @Override protected void okPressed() { selected = getObjectFromSelection(viewer.getSelection()); super.okPressed(); } /** * Retrieve the selected entity from the given selection * * @param selection the selection * @return the selected entity or <code>null</code> */ protected abstract T getObjectFromSelection(ISelection selection); /** * @see Dialog#cancelPressed() */ @Override protected void cancelPressed() { selected = null; super.cancelPressed(); } /** * Get the selected object. * * @return the object or <code>null</code> */ public T getObject() { return selected; } /** * Set the viewer filters * * @param filters the filters */ public void setFilters(ViewerFilter[] filters) { this.filters = filters; } /** * @return the filters */ public ViewerFilter[] getFilters() { return filters; } /** * @return the viewer */ protected V getViewer() { return viewer; } }