| /******************************************************************************* |
| * 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); |
| } |
| } |
| |
| } |