blob: 0e71f37d640e99051b70f0c66196f4a4ee454ec5 [file] [log] [blame]
/*******************************************************************************
* 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
* Bundesinstitut für Risikobewertung
*******************************************************************************/
package org.eclipse.stem.ui.views.graphmap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.stem.jobs.simulation.ISimulation;
import org.eclipse.stem.jobs.simulation.ISimulationManagerListener;
import org.eclipse.stem.jobs.simulation.SimulationManager;
import org.eclipse.stem.jobs.simulation.SimulationManagerEvent;
import org.eclipse.stem.ui.views.IContextMenuUpdatesListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* This class presents "views" of the running simulations.
*/
public class GraphMapViewer extends Viewer implements
ISelectionChangedListener, ISimulationManagerListener {
/**
* This is the collection of
* {@link org.eclipse.stem.jobs.simulation.Simulation}s that should be
* displayed.
*/
private Set<ISimulation> simulationsToDisplay = new LinkedHashSet<ISimulation>();
/**
* This is the {@link SimulationManager} that is the input to the viewer. It
* maintains a collection of active
* {@link org.eclipse.stem.jobs.simulation.Simulation}s in the system. This
* viewer listens to it to discover when new
* {@link org.eclipse.stem.jobs.simulation.Simulation}s are created and old
* ones disappear.
*
* @see #simulationsChanged(SimulationManagerEvent)
*/
private SimulationManager simulationManager;
/**
* The <code>Identifiable</code> that was most recently selected by a user
* clicking on one of the
* {@link org.eclipse.stem.ui.views.geographic.map.MapControl}s, or
* <code>null</code> if none has been selected.
*/
private ISelection selection = null;
/**
* This is the top-level control of the viewer. It contains the
* {@link org.eclipse.stem.ui.views.geographic.map.MapControl}s that display
* the current state of the
* {@link org.eclipse.stem.jobs.simulation.Simulation}s.
*/
private Composite composite;
/**
* This is a list of listeners to get notifications about newly generated
* context menus.
*/
private List<IContextMenuUpdatesListener> contextMenuUpdateListeners = new ArrayList<IContextMenuUpdatesListener>();
/**
* @param parent
* the SWT parent of the control that makes up the viewer
* @param gcf
* the factory that creates instance of {@link GeographicControl}
*/
public GraphMapViewer(Composite parent) {
composite = new Composite(parent, SWT.NONE);
composite.setLayout(new FillLayout(SWT.HORIZONTAL));
refresh();
composite.pack();
}
@Override
public Control getControl() {
return composite;
}
@Override
public ISelection getSelection() {
return selection;
}
@Override
public void refresh() {
if (simulationManager != null) {
simulationsToDisplay.clear();
simulationsToDisplay.addAll(simulationManager
.getActiveSimulations());
}
populateView();
}
@Override
public Object getInput() {
return simulationManager;
}
@Override
public void setInput(Object input) {
Object oldInput = simulationManager;
simulationManager = (SimulationManager) input;
inputChanged(input, oldInput);
}
@Override
protected void inputChanged(Object input, Object oldInput) {
// Is there already a simulation manager?
if (oldInput != null) {
((SimulationManager) oldInput).removeListener(this);
}
// Register with the SimulationManager to listen for changes in the set
// of active Simulations.
// Got input?
if (input != null) {
((SimulationManager) input).addSimulationManagerListener(this);
}
// Update the viewer with the contents of the new input source
refresh();
}
@Override
public void setSelection(ISelection selection, boolean reveal) {
this.selection = selection;
}
@Override
public void selectionChanged(SelectionChangedEvent event) {
// Did the event come from a GeographicControl?
if (event.getSelectionProvider() instanceof GraphMapControl) {
// Just pass it along
selection = event.getSelection();
fireSelectionChanged(event);
}
}
@Override
public void simulationsChanged(SimulationManagerEvent event) {
simulationsToDisplay.addAll(Arrays.asList(event.getSimulationsAdded()));
simulationsToDisplay.removeAll(Arrays.asList(event
.getSimulationsRemoved()));
populateView();
}
/**
* The method adds the specified listener to the list of listeners
*
* @param newListener
* A listener to be added
*/
public void addContextMenuUpdateListener(
IContextMenuUpdatesListener newListener) {
if (!contextMenuUpdateListeners.contains(newListener)) {
contextMenuUpdateListeners.add(newListener);
}
}
/**
* The method removes the specified listener to the list of listeners
*
* @param newListener
* A listener to be added
*/
public void removeContextMenuUpdateListener(
IContextMenuUpdatesListener newListener) {
contextMenuUpdateListeners.remove(newListener);
}
/**
* Create and dispose of MapControls as necessary to display the selected
* Simulations.
*/
private void populateView() {
// Are we done?
if (composite.isDisposed()) {
return;
}
selection = null;
// Find the Simulations that are not currently being displayed and put
// them into the Set undisplayedSimulations.
Set<ISimulation> undisplayedSimulations = new HashSet<ISimulation>();
for (ISimulation simulation : simulationsToDisplay) {
// Is this one associated with a GeographicControl already?
if (!isDisplayed(simulation)) {
undisplayedSimulations.add(simulation);
}
}
// Go through the current set of Controls looking for ones that
// we can reassign
Control[] controls = composite.getChildren();
for (Control element : controls) {
// Does this GeographicControl have a simulation that is still valid
// to display?
GraphMapControl geoControl = (GraphMapControl) element;
if (!simulationsToDisplay.contains(geoControl.getSimulation())
&& !undisplayedSimulations.isEmpty()) {
// Reassign it to one that is valid
ISimulation simulation = (ISimulation) undisplayedSimulations
.toArray()[0];
geoControl.setSimulation(simulation);
// Notify ViewPart that a new context menu has been generated
notifyContextMenuUpdateListeners(geoControl);
undisplayedSimulations.remove(simulation);
}
}
// At this point we still could have map controls with invalid
// Simulations, let's get rid of them
for (Control element : controls) {
GraphMapControl geoControl = (GraphMapControl) element;
// Does this MapControl have a simulation that is still valid to
// display?
ISimulation simulation = geoControl.getSimulation();
if (simulation != null
&& !simulationsToDisplay.contains(simulation)) {
geoControl.removeSelectionChangedListener(this);
geoControl.dispose();
}
}
// If there're any Simulations not assigned to a GeographicControl,
// let's take care of that now.
for (ISimulation simulation2 : undisplayedSimulations) {
GraphMapControl geoControl = new GraphMapControl(composite,
SWT.NONE);
// Notify ViewPart that a new context menu has been generated
notifyContextMenuUpdateListeners(geoControl);
geoControl.addSelectionChangedListener(this);
geoControl.setSimulation(simulation2);
}
// If there are no simulations to display, we just put up a "blank"
// GeographicControl
if (composite.getChildren().length == 0) {
GraphMapControl geoControl = new GraphMapControl(composite,
SWT.NONE);
geoControl.addSelectionChangedListener(this);
}
composite.layout(true, true);
composite.redraw();
}
/**
* @param simulation
* @return
*/
private boolean isDisplayed(ISimulation simulation) {
boolean retValue = false;
Control[] foo = composite.getChildren();
for (Control element : foo) {
GraphMapControl geoControl = (GraphMapControl) element;
ISimulation testSimulation = geoControl.getSimulation();
if (testSimulation != null && testSimulation.equals(simulation)) {
retValue = true;
break;
}
}
return retValue;
}
/**
* The method will send notification to all listeners about new menu that
* has been created.
*
* @param geoControl
* The <code>GeographicControl</code> that has the new
* <code>MenuManager</code> as a field.
*/
private void notifyContextMenuUpdateListeners(GraphMapControl geoControl) {
GraphMapRenderer geoRenderer = geoControl.getGeographicRenderer();
for (IContextMenuUpdatesListener listener : contextMenuUpdateListeners) {
listener.onContextMenuUpdate(geoRenderer.getMenuManager(), geoRenderer);
}
}
}