blob: ff121a0212890b18981d58e5e49eb962aea50d44 [file] [log] [blame]
// GeoViewOptionsBar.java
package org.eclipse.stem.ui.widgets;
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.stem.core.graph.DynamicLabel;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProvider;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapter;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapterFactory;
import org.eclipse.stem.diseasemodels.standard.DiseaseModel;
import org.eclipse.stem.jobs.simulation.ISimulation;
import org.eclipse.stem.populationmodels.standard.PopulationModel;
import org.eclipse.stem.ui.adapters.color.ColorProviderAdapterFactory;
import org.eclipse.stem.ui.adapters.color.IColorProviderAdapterFactory;
import org.eclipse.stem.ui.adapters.color.IColorProviderChangedListener;
import org.eclipse.stem.ui.views.geographic.map.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
/**
* This class is a compound SWT {@link org.eclipse.swt.widgets.Widget} that allows for the selection of
* a {@link Decorator}s and {@link org.eclipse.stem.ui.adapters.color.ColorProvider}s.
*/
public class GeoViewOptionsBar extends Composite {
/**
* A list of {@link PropertySelectionListener}s to be notified about
* property selection events
*/
private final List<PropertySelectionListener> selectionListeners = new CopyOnWriteArrayList<PropertySelectionListener>();
/**
* The collection of {@link IColorProviderChangedListener} waiting to be told change of a color provider.
*/
protected final List<IColorProviderChangedListener> colorProviderChangedListeners = new CopyOnWriteArrayList<IColorProviderChangedListener>();
/**
* Combo for selecting decorators
*/
Combo decoratorsCombo;
/**
* Combo for selecting decorators
*/
Combo populationsCombo;
/**
* Combo for selecting the color provider
*/
Combo colorProvidersCombo;
/**
* A constant to set the width of the decorators combo
*/
static final int DECORATORS_WIDTH = 35;
/**
* A constant to set the width of the pop id combo
*/
static final int POPIDS_WIDTH=25;
/**
* A constant to set the width of the color providers combo
*/
static final int PROVIDERS_WIDTH = 45;
/**
* Combo for selecting edges
*/
Combo edgesCombo;
/**
* The composite that the selected color provider contributed
*/
Composite colorProviderComposite;
/**
* The composite with the colors legend (provided by the selected color
* provider)
*/
Composite colorsLegendComposite;
/**
* The group composite that gathers the widgets
*/
Group geoViewOptionsGroup;
/**
* The group composite that gathers the widgets
*/
Group edgesGroup;
/**
* List of available decorators
*/
List<Decorator> decorators;
/**
* List of available populations for the selected decorator
*/
List<String> populationIdentifiers;
/**
* List of available color providers
*/
List<Class> supportedColorProviders = null;
/**
* List of available color providers names
*/
List<String> supportedColorProvidersNames = null;
/**
* Mapping between edge type and its URI prefix
*/
Map<String, String> edgeTypeToUriPrefixMap = new HashMap<String, String>();
/**
* The selected color provider
*/
Class selectedColorProvider = null;
/**
* The selected decorator
*/
Decorator selectedDecorator;
/**
* The selected population identifier
*/
String selectedPopulationIdentifier;
/**
* Decorator filter to be used
*/
private DecoratorFilter decoratorFilter = new DecoratorFilter() {
/**
* Currently only accepts decorators that are able to provide a relative value
* TODO: Fix so we can view other types of decorators
*
* @see GeoViewOptionsBar.DecoratorFilter#accept(org.eclipse.stem.core.model.Decorator)
*/
public boolean accept(
final Decorator decorator) {
EList<DynamicLabel>labels = decorator.getLabelsToUpdate();
if(labels == null) return false;
for(DynamicLabel l:labels) {
RelativeValueProviderAdapter rvp = (RelativeValueProviderAdapter) RelativeValueProviderAdapterFactory.INSTANCE
.adapt(l, RelativeValueProvider.class);
if(rvp != null) return true;
}
return false;
}
};
/**
* Constructor
*
* @param parent
* the parent {@link Composite}
* @param style
* an SWT style
*/
public GeoViewOptionsBar(final Composite parent, final int style) {
super(parent, style);
final RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
rowLayout.fill = true;
this.setLayout(rowLayout);
geoViewOptionsGroup = new Group(this, SWT.NONE);
final FormLayout formLayout = new FormLayout();
geoViewOptionsGroup.setLayout(formLayout);
// //$NON-NLS-1$ //$NON-NLS-2$
geoViewOptionsGroup.setText(Messages.getString("IMView.MProp"));
geoViewOptionsGroup.setVisible(false);
// Combo Box of Decorators
decoratorsCombo = new Combo(geoViewOptionsGroup, SWT.DROP_DOWN
| SWT.READ_ONLY | SWT.CENTER);
// Combo Box of population identifiers
populationsCombo = new Combo(geoViewOptionsGroup, SWT.DROP_DOWN
| SWT.READ_ONLY | SWT.CENTER);
// Combo Box of the color providers
colorProvidersCombo = new Combo(geoViewOptionsGroup, SWT.DROP_DOWN
| SWT.READ_ONLY | SWT.CENTER);
final FormData decoratorsComboFormData = new FormData();
decoratorsComboFormData.left = new FormAttachment(0, 0);
decoratorsComboFormData.right = new FormAttachment(DECORATORS_WIDTH, 0);
decoratorsCombo.setLayoutData(decoratorsComboFormData);
final FormData populationComboFormData = new FormData();
populationComboFormData.top = new FormAttachment(decoratorsCombo, 5);
populationComboFormData.left = new FormAttachment(0, 0);
populationComboFormData.right = new FormAttachment(POPIDS_WIDTH, 0);
populationsCombo.setLayoutData(populationComboFormData);
final FormData colorProvidersComboFormData = new FormData();
colorProvidersComboFormData.top = new FormAttachment(populationsCombo, 5);
colorProvidersComboFormData.left = new FormAttachment(0, 0);
colorProvidersComboFormData.right = new FormAttachment(PROVIDERS_WIDTH, 0);
colorProvidersCombo.setLayoutData(colorProvidersComboFormData);
supportedColorProviders = ColorProviderAdapterFactory.INSTANCE.getSupportedColorProviders();
supportedColorProvidersNames = ColorProviderAdapterFactory.INSTANCE.getSupportedColorProvidersNames();
this.pack();
decoratorsCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(
@SuppressWarnings("unused") final SelectionEvent e) {
// Any decorators?
if (!decorators.isEmpty()) {
// Yes
final Decorator tempDecorator = decorators
.get(decoratorsCombo.getSelectionIndex());
// Was there a change in selected Decorators?
if (selectedDecorator != tempDecorator) {
// Yes
selectedDecorator = tempDecorator;
List<String> popIds = getPopulationIdentifiers(selectedDecorator);
populationIdentifiers = popIds;
if(populationIdentifiers != null) selectedPopulationIdentifier = populationIdentifiers.get(0);
initializeCombo(populationsCombo, getPopulationIdNames(popIds),
getPopulationIdIndex(selectedPopulationIdentifier, populationIdentifiers));
updateColorProviderComposites();
firePropertySelectionEvent(new PropertySelectionEvent(
selectedDecorator, selectedPopulationIdentifier, null, colorProvidersCombo));
} // if Decorators changed
} // if any decorators
}
} // SelectionAdapter
);
populationsCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(
@SuppressWarnings("unused") final SelectionEvent e) {
// Any decorators?
if (!populationIdentifiers.isEmpty()) {
// Yes
final String tempPopId = populationIdentifiers
.get(populationsCombo.getSelectionIndex());
// Was there a change in selected Decorators?
if (!selectedPopulationIdentifier.equals(tempPopId)) {
// Yes
selectedPopulationIdentifier = tempPopId;
updateColorProviderComposites();
firePropertySelectionEvent(new PropertySelectionEvent(
selectedDecorator, selectedPopulationIdentifier, null, colorProvidersCombo));
} // if Decorators changed
} // if any decorators
}
} // SelectionAdapter
);
colorProvidersCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(
@SuppressWarnings("unused") final SelectionEvent e) {
selectedColorProvider =
supportedColorProviders.get(colorProvidersCombo.getSelectionIndex());
updateColorProviderComposites();
}
} // SelectionAdapter
);
edgesGroup = new Group(this, SWT.NONE);
edgesCombo = new Combo(edgesGroup, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.CENTER);
edgesCombo.add("");
edgesGroup.setLayout(new FormLayout());
edgesGroup.setVisible(false);
edgesGroup.setText(Messages.getString("IMView.Edges"));
edgesCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(
@SuppressWarnings("unused") final SelectionEvent e) {
String selectedEdges = edgesCombo.getText();
if (selectedEdges == null || selectedEdges.equals("")) {
firePropertySelectionEvent(null);
}
else {
String edgePrefix = edgeTypeToUriPrefixMap.get(selectedEdges);
firePropertySelectionEvent(new PropertySelectionEvent(null, null,
null, edgePrefix));
}
}
} // SelectionAdapter
);
setSimulation(null);
} // PropertySelector
/**
* @return <code>true</code> if the control has been initialized.
*/
public boolean isInitialized() {
return !(decorators == null || decorators.isEmpty());
} // isInitialized
/**
* Sets the {@link Decorator}s
*
* @param decorators
* {@link Decorator}s to set
*/
public void setDecorators(final List<Decorator> decorators) {
this.decorators = decorators;
selectedDecorator = decorators.isEmpty() ? null : decorators.get(0);
// If we have BOTH a population decorator and a disease decorator
// try to initially select the disease by default
if (decorators.size()>=2) {
if(!(selectedDecorator instanceof DiseaseModel)) {
for(int i = 0; i < decorators.size(); i ++) {
if(decorators.get(i) instanceof DiseaseModel) {
selectedDecorator = decorators.get(i);
break;
}
}
}
}
List<String> popIds = getPopulationIdentifiers(selectedDecorator);
populationIdentifiers = popIds;
if(populationIdentifiers != null) selectedPopulationIdentifier = populationIdentifiers.get(0);
initializeCombo(decoratorsCombo, getDecoratorNames(decorators),
getDecoratorIndex(selectedDecorator, decorators));
initializeCombo(populationsCombo, getPopulationIdNames(popIds),
getPopulationIdIndex(selectedPopulationIdentifier, populationIdentifiers));
} // setDecorators
List<String> getPopulationIdentifiers(Decorator decorator) {
if(decorator instanceof DiseaseModel) {
return ((DiseaseModel) decorator).getAllLabelIdentifiers();
} else if(decorator instanceof PopulationModel) {
return ((PopulationModel) decorator).getAllLabelIdentifiers();
}
return null;
}
/**
* Sets the Population Identifiers
*
* @param popIds
*/
public void setPopulationIdentifiers(final List<String> popIds) {
this.populationIdentifiers = popIds;
selectedPopulationIdentifier = popIds.isEmpty() ? null : popIds.get(0);
initializeCombo(populationsCombo, getPopulationIdNames(popIds),
getPopulationIdIndex(selectedPopulationIdentifier, populationIdentifiers));
} // setDecorators
/**
* @param decorators
*/
public void setColorProviders(final List<Decorator> decorators) {
if (supportedColorProviders.isEmpty()) {
//No color providers available
return;
}
for (String providerName : supportedColorProvidersNames) {
colorProvidersCombo.add(providerName);
}
colorProvidersCombo.select(0);
selectedColorProvider = supportedColorProviders.get(0);
updateColorProviderComposites();
}
private void setEdges() {
if (selectedDecorator == null)
return;
Set<URI> edgesURIs = selectedDecorator.getGraph().getEdges().keySet();
Iterator<URI> iter = edgesURIs.iterator();
while(iter.hasNext()) {
URI nextUri = iter.next();
String edgePrefix = nextUri.trimSegments(1).toString();
String edgeType = org.eclipse.stem.ui.preferences.Messages.getString(edgePrefix);
if (edgeType.startsWith("!") && edgeType.endsWith("!")) {
edgePrefix = nextUri.trimSegments(2).toString();
edgeType = org.eclipse.stem.ui.preferences.Messages.getString(edgePrefix);
}
if (!edgeTypeToUriPrefixMap.containsKey(edgeType)) {
edgeTypeToUriPrefixMap.put(edgeType, edgePrefix);
edgesCombo.add(edgeType);
}
}
}
/**
* Initialize the control from a {@link org.eclipse.stem.jobs.simulation.Simulation} instance.
*
* @param simulation
* the {@link org.eclipse.stem.jobs.simulation.Simulation}
*/
public void setSimulation(final ISimulation simulation) {
if (simulation == null)
return;
setDecorators(getDecoratorsToDisplay(simulation));
if(decorators != null) {
setColorProviders(decorators);
geoViewOptionsGroup.setVisible(true);
setEdges();
edgesGroup.setVisible(true);
getInformation(simulation);
}
} // setSimulation
/**
* @param decoratorFilter
* the filter that determines which {@link Decorator}s will be
* displayed.
*/
public void setDecoratorFilter(final DecoratorFilter decoratorFilter) {
this.decoratorFilter = decoratorFilter;
} // setDecoratorFilter
/**
*
*/
protected void updateColorProviderComposites() {
if (colorProviderComposite != null) {
colorProviderComposite.dispose();
}
if (colorsLegendComposite != null) {
colorsLegendComposite.dispose();
}
AdapterFactory adapterFactory = ColorProviderAdapterFactory.INSTANCE.getFactoryForType(selectedColorProvider);
if (adapterFactory instanceof IColorProviderAdapterFactory) {
IColorProviderAdapterFactory selectedColorProviderAdapterFactory = (IColorProviderAdapterFactory)adapterFactory;
colorProviderComposite = selectedColorProviderAdapterFactory
.createPropertiesComposite(geoViewOptionsGroup, SWT.NONE, selectedDecorator, selectedPopulationIdentifier);
// if there is no composite contribution from the selected color
// provider then return
if (colorProviderComposite == null) {
return;
}
if (colorProviderComposite instanceof ColorProviderPropertiesComposite) {
((ColorProviderPropertiesComposite) colorProviderComposite)
.addPropertySelectionListener(new ColorProviderPropertiesComposite.PropertySelectionListener() {
public void propertySelected(
final ColorProviderPropertiesComposite.PropertySelectionEvent propertySelectionEvent) {
firePropertySelectionEvent(new PropertySelectionEvent(
null, null,null, propertySelectionEvent
.getSource()));
}
});
}
final FormData colorProviderCompositeFormData = new FormData();
colorProviderCompositeFormData.top = new FormAttachment(0,0);
colorProviderCompositeFormData.left = new FormAttachment(DECORATORS_WIDTH, 0);
colorProviderCompositeFormData.right = new FormAttachment(PROVIDERS_WIDTH, 0);
colorProviderComposite.setLayoutData(colorProviderCompositeFormData);
geoViewOptionsGroup.layout();
colorsLegendComposite = selectedColorProviderAdapterFactory
.createColorsLegendComposite(this, SWT.NONE);
if (colorsLegendComposite != null) {
colorsLegendComposite.pack();
colorsLegendComposite.layout();
}
this.layout();
}
fireColorProviderChangedEvent();
}
/**
* @param simulation
* the simulation that contains {@link Decorator}s
* @return a {@link List} of the {@link Decorator}s whose properties
*/
private List<Decorator> getDecoratorsToDisplay(final ISimulation simulation) {
final List<Decorator> retValue = new ArrayList<Decorator>();
// Got Simulation?
if (simulation != null) {
// Yes
final Graph canonicalGraph = simulation.getScenario()
.getCanonicalGraph();
// Is the canonicalGraph initialized yet?
if (canonicalGraph != null) {
// Yes
// Go through the Decorators keeping the ones that the filter
// says are ok.
for (final Object element : canonicalGraph.getDecorators()) {
final Decorator decorator = (Decorator) element;
// Acceptable?
if (decoratorFilter.accept(decorator)) {
retValue.add(decorator);
} // if has a title
} // for each decorator
} // if got graph
} // if got simulation
return retValue;
} // getDecoratorsToDisplay
/**
* @param simulation
* the simulation that contains {@link Decorator}s
*/
private void getInformation(final ISimulation simulation) {
// Got Simulation?
if (simulation != null) {
// Yes
final Graph canonicalGraph = simulation.getScenario()
.getCanonicalGraph();
// Is the canonicalGraph initialized yet?
if (canonicalGraph != null) {
canonicalGraph.getGraphLabels();
canonicalGraph
.getNodeLabelsByTypeURI(URI
.createURI("stemtype://org.eclipse.stem/label/population"));
} // if got graph
} // if got simulation
} // getDecoratorsToDisplay
/**
* @param combo
* @param names
* @param selectionIndex
*/
private void initializeCombo(final Combo combo, final String[] names,
final int selectionIndex) {
combo.setItems(names);
combo.select(selectionIndex);
} // initializeCombo
/**
* @param decorators
* a list of {@link Decorator}s
* @return an array of the names of the {@link Decorators}.
*/
private String[] getDecoratorNames(final List<Decorator> decorators) {
final List<String> retValue = new ArrayList<String>();
if (decorators != null) {
// Yes
for (final Decorator decorator : decorators) {
final ComposedAdapterFactory itemProviderFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
final IItemLabelProvider lp = (IItemLabelProvider) itemProviderFactory.adapt(
decorator, IItemLabelProvider.class);
String title = lp.getText(decorator);
title = title == null ? "null" : title;
retValue.add(title);
} // for each decorator
} // if
return retValue.toArray(new String[] {});
} // getDecoratorNames
/**
* @param popIds
* a list of population ids
* @return an array of the names
*/
private String[] getPopulationIdNames(final List<String> popIds) {
final List<String> retValue = new ArrayList<String>();
if (popIds != null) {
// Yes
for (final String decid : popIds) {
String title = decid;
title = title == null ? "null" : title;
retValue.add(title);
} // for each decorator
} // if
return retValue.toArray(new String[] {});
} // getDecoratorNames
/**
* @param selectedDecorator
* @param decorators
* a list of {@link Decorator}s.
* @return the position (0 origin) of the selectedDecorator in decorators,
* or 0, if the decorators list is empty.
*/
private int getDecoratorIndex(final Decorator selectedDecorator,
final List<Decorator> decorators) {
if (selectedDecorator != null && decorators != null
&& !decorators.isEmpty()) {
// Yes
return decorators.indexOf(selectedDecorator);
} // if
return 0;
} // getDecoratorIndex
/**
*/
private int getPopulationIdIndex(final String selectedPopId,
final List<String> popIds) {
if (selectedPopId != null && popIds != null
&& !popIds.isEmpty()) {
// Yes
return popIds.indexOf(selectedPopId);
} // if
return 0;
} // getDecoratorIndex
/**
* @param listener
*/
public void addPropertySelectionListener(
final PropertySelectionListener listener) {
selectionListeners.add(listener);
}
/**
* @param listener
*/
public void removePropertySelectionListener(
final PropertySelectionListener listener) {
selectionListeners.remove(listener);
}
protected void firePropertySelectionEvent(final PropertySelectionEvent pse) {
for (final PropertySelectionListener listener : selectionListeners) {
listener.propertySelected(pse);
} // for each PropertySelectionListener
} // firePropertySelectionEvent
/**
* @param listener
*/
public void addColorProviderChangedListener(
final IColorProviderChangedListener listener) {
colorProviderChangedListeners.add(listener);
}
/**
* @param listener
*/
public void removeColorProviderChangedListener(
final IColorProviderChangedListener listener) {
colorProviderChangedListeners.remove(listener);
}
protected void fireColorProviderChangedEvent() {
for (final IColorProviderChangedListener listener : colorProviderChangedListeners) {
listener.colorProviderChanged(selectedColorProvider);
} // for each PropertySelectionListener
} // firePropertySelectionEvent
/**
* This interface is implemented by classes that determine if a
* {@link Decorator} meets some specified criteria.
*/
public interface DecoratorFilter {
/**
* @param decorator
* @return <code>true</code> if the {@link Decorator} is acceptable.
*/
boolean accept(final Decorator decorator);
} // DecoratorFilter
/**
* This interface is implemented by classes that wish to be notified
* whenever a property is selected in this widget.
*/
public interface PropertySelectionListener {
/**
* @param propertySelectionEvent
*/
void propertySelected(PropertySelectionEvent propertySelectionEvent);
} // PropertySelectionListener
/**
* This class represents the event of a property being selected in the
* widget.
*/
public static class PropertySelectionEvent extends EventObject {
private static final long serialVersionUID = 1L;
private transient final ItemPropertyDescriptor property;
private transient final Decorator decorator;
private transient final String populationIdentifier;
/**
* @param decorator
* the {@link Decorator}
* @param property
* the property that was selected.
* @param source
*/
public PropertySelectionEvent(final Decorator decorator, String popId,
final ItemPropertyDescriptor property, final Object source) {
super(source);
this.decorator = decorator;
this.property = property;
this.populationIdentifier = popId;
}
/**
* @return the decorator
*/
public final Decorator getDecorator() {
return decorator;
}
/**
* @return the population identifier
*/
public final String getPopulationIdentifier() {
return populationIdentifier;
}
/**
* @return the property
*/
public final ItemPropertyDescriptor getProperty() {
return property;
}
/**
* @see java.util.EventObject#toString()
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(
decorator == null ? "null," : decorator.getDublinCore()
.getTitle());
sb.append(property == null ? "null" : property
.getDisplayName(property));
return sb.toString();
}
} // PropertySelectionEvent
/**
* @return the selectedDecorator
*/
public Decorator getSelectedDecorator() {
return selectedDecorator;
}
/**
* @return the selected population identifier
*/
public String getSelectedPopulationIdentifier() {
return selectedPopulationIdentifier;
}
} // PropertySelector