/* * 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.views.data.internal.filter; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; 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.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; 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.Widget; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PlatformUI; import eu.esdihumboldt.hale.common.instance.model.DataSet; import eu.esdihumboldt.hale.common.instance.model.Filter; import eu.esdihumboldt.hale.common.instance.model.Instance; import eu.esdihumboldt.hale.common.instance.model.InstanceReference; import eu.esdihumboldt.hale.common.schema.SchemaSpaceID; import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.hale.ui.common.definition.viewer.DefinitionComparator; import eu.esdihumboldt.hale.ui.common.definition.viewer.DefinitionLabelProvider; import eu.esdihumboldt.hale.ui.filter.TypeFilterField; import eu.esdihumboldt.hale.ui.filter.cql.CQLFilterField; import eu.esdihumboldt.hale.ui.selection.InstanceSelection; import eu.esdihumboldt.hale.ui.service.instance.InstanceService; import eu.esdihumboldt.hale.ui.util.selection.SelectionTrackerUtil; import eu.esdihumboldt.hale.ui.views.data.AbstractDataView; /** * Instance selector retrieving values from the selection service. * * @author Simon Templer * @partner 01 / Fraunhofer Institute for Computer Graphics Research */ public class WindowSelectionSelector implements AdvancedInstanceSelector { /** * Instance selector control */ private class InstanceSelectorControl extends Composite implements ISelectionListener { private final ComboViewer instanceTypes; private final Map<TypeDefinition, List<Instance>> instanceMap = new HashMap<TypeDefinition, List<Instance>>(); private TypeDefinition selectedType; private final CQLFilterField filterField; private final ComboViewer count; /** * @see Composite#Composite(Composite, int) */ public InstanceSelectorControl(Composite parent, int style) { super(parent, style); GridLayout layout = new GridLayout(3, false); layout.marginHeight = 2; layout.marginWidth = 3; setLayout(layout); // instance type selector instanceTypes = new ComboViewer(this, SWT.READ_ONLY); instanceTypes.setContentProvider(ArrayContentProvider.getInstance()); instanceTypes.setComparator(new DefinitionComparator()); instanceTypes.setLabelProvider(new DefinitionLabelProvider(null)); instanceTypes.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateSelection(); } }); instanceTypes.getControl() .setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); // filter field filterField = new CQLFilterField((selectedType == null) ? (null) : (selectedType), this, SWT.NONE, SchemaSpaceID.TARGET); filterField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); filterField.addListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(TypeFilterField.PROPERTY_FILTER)) { updateSelection(); } } }); // max count selector count = new ComboViewer(this, SWT.READ_ONLY); count.setContentProvider(ArrayContentProvider.getInstance()); count.setInput(new Integer[] { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5) }); count.setSelection(new StructuredSelection(Integer.valueOf(2))); count.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateSelection(); } }); // service listeners ISelectionService ss = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getSelectionService(); ss.addPostSelectionListener(this); ISelection selection = ss.getSelection(); if (!(selection instanceof InstanceSelection)) selection = SelectionTrackerUtil.getTracker().getSelection(InstanceSelection.class); if (selection != null) lastSelection = (InstanceSelection) selection; updateTypeSelection(); } /** * Update the feature types selection */ protected void updateTypeSelection() { instanceMap.clear(); // get selected instance Collection<Instance> instances = getSelectedInstances(null); if (instances != null && !instances.isEmpty()) { // determine types Iterator<Instance> it = instances.iterator(); while (it.hasNext()) { Instance instance = it.next(); TypeDefinition type = instance.getDefinition(); List<Instance> instanceList = instanceMap.get(type); if (instanceList == null) { instanceList = new ArrayList<Instance>(); instanceMap.put(type, instanceList); } instanceList.add(instance); } } Set<TypeDefinition> selectableTypes = instanceMap.keySet(); instanceTypes.setInput(selectableTypes); boolean enabled = !selectableTypes.isEmpty(); if (enabled) instanceTypes .setSelection(new StructuredSelection(selectableTypes.iterator().next())); instanceTypes.getControl().setEnabled(enabled); count.getControl().setEnabled(enabled); filterField.setEnabled(enabled); layout(true, true); updateSelection(); } /** * Get the selected instances form the current {@link InstanceSelection} * * @param typeFilter the type for the instances to match, * <code>null</code> for any type * @return the selected features or <code>null</code> */ private Collection<Instance> getSelectedInstances(TypeDefinition typeFilter) { if (lastSelection == null || lastSelection.isEmpty()) { return null; } else { List<?> elements = lastSelection.toList(); Collection<Instance> result = new ArrayList<Instance>(elements.size()); final InstanceService instanceService = PlatformUI.getWorkbench() .getService(InstanceService.class); // collect instances from selection that match the data set for (Object element : elements) { Instance instance = null; if (element instanceof Instance && ((Instance) element).getDataSet() == dataSet) { instance = (Instance) element; } else if (element instanceof InstanceReference && ((InstanceReference) element).getDataSet() == dataSet) { instance = instanceService.getInstance((InstanceReference) element); } if (instance != null && (typeFilter == null || typeFilter.equals(instance.getDefinition()))) { // add instance if type filter matches result.add(instance); } } return result; } } /** * Update the selection. */ protected void updateSelection() { if (!instanceTypes.getSelection().isEmpty()) { TypeDefinition type = (TypeDefinition) ((IStructuredSelection) instanceTypes .getSelection()).getFirstElement(); filterField.setType(type); selectedType = type; } else { filterField.setType(null); selectedType = null; } for (InstanceSelectionListener listener : listeners) { listener.selectionChanged(selectedType, getSelection()); } } /** * Get the currently selected instances. * * @return the currently selected instances */ public Iterable<Instance> getSelection() { if (selectedType == null) return null; else { List<Instance> selection = instanceMap.get(selectedType); Integer max = (Integer) ((IStructuredSelection) count.getSelection()) .getFirstElement(); Filter filter = filterField.getFilter(); List<Instance> result = new ArrayList<Instance>(max); int count = 0; Iterator<Instance> iter = selection.iterator(); while (iter.hasNext() && count < max) { Instance instance = iter.next(); if (filter == null || filter.match(instance)) { result.add(instance); count++; } } return result; } } /** * @see Widget#dispose() */ @Override public void dispose() { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService() .removePostSelectionListener(this); listeners.clear(); super.dispose(); } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (!(part instanceof AbstractDataView) // don't react on data view // changes (to prevent // loops) && selection instanceof InstanceSelection) { lastSelection = (InstanceSelection) selection; if (part != null) { selectionImage = part.getTitleImage(); } else { selectionImage = null; } updateButton(); updateTypeSelection(); } } } private final Set<InstanceSelectionListener> listeners = new HashSet<InstanceSelectionListener>(); private InstanceSelectorControl current; private final DataSet dataSet; private InstanceSelection lastSelection; private Button activator; private Image defaultImage; private Image selectionImage; /** * Constructor * * @param dataSet the data set */ public WindowSelectionSelector(DataSet dataSet) { this.dataSet = dataSet; } /** * @see InstanceSelector#addSelectionListener(InstanceSelectionListener) */ @Override public void addSelectionListener(InstanceSelectionListener listener) { listeners.add(listener); if (current != null && !current.isDisposed()) { listener.selectionChanged(current.selectedType, current.getSelection()); } } /** * @see InstanceSelector#createControl(Composite) */ @Override public Control createControl(Composite parent) { current = new InstanceSelectorControl(parent, SWT.NONE); return current; } /** * @see InstanceSelector#removeSelectionListener(InstanceSelectionListener) */ @Override public void removeSelectionListener(InstanceSelectionListener listener) { listeners.remove(listener); } /** * Show the given selection. * * @param is the selection to show * @param image an image to show for the selection, may be <code>null</code> */ public void showSelection(InstanceSelection is, final Image image) { if (current != null && !current.isDisposed()) { current.selectionChanged(new IWorkbenchPart() { // dummy part @SuppressWarnings("unchecked") @Override public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { // dummy return null; } @Override public void setFocus() { // dummy } @Override public void removePropertyListener(IPropertyListener listener) { // dummy } @Override public String getTitleToolTip() { // dummy return null; } @Override public Image getTitleImage() { return image; } @Override public String getTitle() { // dummy return null; } @Override public IWorkbenchPartSite getSite() { // dummy return null; } @Override public void dispose() { // dummy } @Override public void createPartControl(Composite parent) { // dummy } @Override public void addPropertyListener(IPropertyListener listener) { // dummy } }, is); } } /** * @see AdvancedInstanceSelector#setActivator(Button) */ @Override public void setActivator(Button activator) { defaultImage = activator.getImage(); this.activator = activator; updateButton(); } /** * Update the activator button image. */ private void updateButton() { if (activator != null) { if (selectionImage != null) { activator.setImage(selectionImage); } else { activator.setImage(defaultImage); } // activator.redraw(); } } }