package nl.tudelft.simulation.dsol.swing.gui.animation;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.rmi.RemoteException;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import org.djutils.draw.bounds.Bounds2d;
import org.djutils.logger.CategoryLogger;
import nl.tudelft.simulation.dsol.animation.gis.GisMapInterface;
import nl.tudelft.simulation.dsol.animation.gis.GisRenderable2D;
import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
import nl.tudelft.simulation.dsol.swing.animation.D2.AnimationPanel;
import nl.tudelft.simulation.dsol.swing.animation.D2.AutoPanAnimationPanel;
import nl.tudelft.simulation.dsol.swing.gui.animation.panel.SearchPanel;
import nl.tudelft.simulation.language.DSOLException;
/**
* Animation panel with GIS layers and various controls.
*
* Copyright (c) 2020-2022 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information DSOL Manual. The DSOL
* project is distributed under a three-clause BSD-style license, which can be found at
* DSOL License.
*
* @author Alexander Verbraeck
* @author Peter Knoppers
*/
public class DSOLAnimationGisTab extends DSOLAnimationTab
{
/** */
private static final long serialVersionUID = 20150617L;
/** Set of GIS layer names to toggle GIS layers . */
private Map toggleGISMap = new LinkedHashMap<>();
/** Set of GIS layer names to toggle buttons. */
private Map toggleGISButtons = new LinkedHashMap<>();
/**
* Construct a tab with an AnimationPane for the animation of a DSOLModel, including GIS layers.
* @param homeExtent Bounds2d; initial extent of the animation
* @param simulator SimulatorInterface; the simulator
* @throws RemoteException when notification of the animation panel fails
* @throws DSOLException when simulator does not implement the AnimatorInterface
*/
public DSOLAnimationGisTab(final Bounds2d homeExtent, final SimulatorInterface, ?, ?> simulator)
throws RemoteException, DSOLException
{
super(homeExtent, simulator);
}
/**
* Construct a tab with an AnimationPane for the animation of a DSOLModel, including GIS layers.
* @param simulator SimulatorInterface; the simulator
* @param animationPanel AnimationPanel; the animation panel to use, e.g. the AutoPanAnimationPanel
* @throws RemoteException when notification of the animation panel fails
* @throws DSOLException when simulator does not implement the AnimatorInterface
*/
public DSOLAnimationGisTab(final SimulatorInterface, ?, ?> simulator, final AnimationPanel animationPanel)
throws RemoteException, DSOLException
{
super(simulator, animationPanel);
}
/**
* Construct a tab with an AutoPanAnimationPanel and a linked SearchPanel for the animation of a DSOLModel, including GIS
* layers.
* @param homeExtent Bounds2d; initial extent of the animation
* @param simulator SimulatorInterface; the simulator
* @return DSOLAnimationTab; a tab with an AutoPanAnimationPanel and a linked SearchPanel
* @throws RemoteException when notification of the animation panel fails
* @throws DSOLException when simulator does not implement the AnimatorInterface
*/
public static DSOLAnimationTab createAutoPanTab(final Bounds2d homeExtent, final SimulatorInterface, ?, ?> simulator)
throws RemoteException, DSOLException
{
DSOLAnimationTab tab = new DSOLAnimationTab(simulator, new AutoPanAnimationPanel(homeExtent, simulator));
tab.setSearchPanel(new SearchPanel());
return tab;
}
/**
* Add buttons for toggling all GIS layers on or off.
* @param header String; the name of the group of layers
* @param gisMap GisRenderable2D; the GIS map for which the toggles have to be added
* @param toolTipText String; the tool tip text to show when hovering over the button
*/
public void addAllToggleGISButtonText(final String header, final GisRenderable2D gisMap, final String toolTipText)
{
addToggleText(" ");
addToggleText(header);
try
{
for (String layerName : gisMap.getMap().getLayerMap().keySet())
{
addToggleGISButtonText(layerName, layerName, gisMap, toolTipText);
}
}
catch (RemoteException exception)
{
exception.printStackTrace();
}
}
/**
* Add a button to toggle a GIS Layer on or off.
* @param layerName String; the name of the layer
* @param displayName String; the name to display next to the tick box
* @param gisMap GisRenderable2D; the map
* @param toolTipText String; the tool tip text
*/
public void addToggleGISButtonText(final String layerName, final String displayName, final GisRenderable2D gisMap,
final String toolTipText)
{
JToggleButton button;
button = new JCheckBox(displayName);
button.setName(layerName);
button.setEnabled(true);
button.setSelected(true);
button.setActionCommand(layerName);
button.setToolTipText(toolTipText);
button.addActionListener(this);
JPanel toggleBox = new JPanel();
toggleBox.setLayout(new BoxLayout(toggleBox, BoxLayout.X_AXIS));
toggleBox.add(button);
getTogglePanel().add(toggleBox);
toggleBox.setAlignmentX(Component.LEFT_ALIGNMENT);
this.toggleGISMap.put(layerName, gisMap.getMap());
this.toggleGISButtons.put(layerName, button);
}
/**
* Set a GIS layer to be shown in the animation to true.
* @param layerName String; the name of the GIS-layer that has to be shown.
*/
public void showGISLayer(final String layerName)
{
GisMapInterface gisMap = this.toggleGISMap.get(layerName);
if (gisMap != null)
{
try
{
gisMap.showLayer(layerName);
this.toggleGISButtons.get(layerName).setSelected(true);
getAnimationPanel().repaint();
}
catch (RemoteException exception)
{
exception.printStackTrace();
}
}
}
/**
* Set a GIS layer to be hidden in the animation to true.
* @param layerName String; the name of the GIS-layer that has to be hidden.
*/
public void hideGISLayer(final String layerName)
{
GisMapInterface gisMap = this.toggleGISMap.get(layerName);
if (gisMap != null)
{
try
{
gisMap.hideLayer(layerName);
this.toggleGISButtons.get(layerName).setSelected(false);
getAnimationPanel().repaint();
}
catch (RemoteException exception)
{
exception.printStackTrace();
}
}
}
/**
* Toggle a GIS layer to be displayed in the animation to its reverse value.
* @param layerName String; the name of the GIS-layer that has to be turned off or vice versa.
*/
public void toggleGISLayer(final String layerName)
{
GisMapInterface gisMap = this.toggleGISMap.get(layerName);
if (gisMap != null)
{
try
{
if (gisMap.getVisibleLayers().contains(gisMap.getLayerMap().get(layerName)))
{
gisMap.hideLayer(layerName);
this.toggleGISButtons.get(layerName).setSelected(false);
}
else
{
gisMap.showLayer(layerName);
this.toggleGISButtons.get(layerName).setSelected(true);
}
getAnimationPanel().repaint();
}
catch (RemoteException exception)
{
exception.printStackTrace();
}
}
}
/** {@inheritDoc} */
@Override
public void actionPerformed(final ActionEvent actionEvent)
{
String actionCommand = actionEvent.getActionCommand();
try
{
if (this.toggleGISMap.containsKey(actionCommand))
{
this.toggleGISLayer(actionCommand);
getTogglePanel().repaint();
}
super.actionPerformed(actionEvent); // handle other commands
}
catch (Exception exception)
{
CategoryLogger.always().warn(exception);
}
}
}