View Javadoc
1   package nl.tudelft.simulation.dsol.swing.gui.animation;
2   
3   import java.awt.Component;
4   import java.awt.event.ActionEvent;
5   import java.util.LinkedHashMap;
6   import java.util.Map;
7   
8   import javax.swing.BoxLayout;
9   import javax.swing.JCheckBox;
10  import javax.swing.JPanel;
11  import javax.swing.JToggleButton;
12  
13  import org.djutils.draw.bounds.Bounds2d;
14  import org.djutils.logger.CategoryLogger;
15  
16  import nl.tudelft.simulation.dsol.animation.gis.GisMapInterface;
17  import nl.tudelft.simulation.dsol.animation.gis.GisRenderable2d;
18  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
19  import nl.tudelft.simulation.dsol.swing.animation.d2.AnimationPanel;
20  import nl.tudelft.simulation.dsol.swing.animation.d2.AutoPanAnimationPanel;
21  import nl.tudelft.simulation.dsol.swing.gui.animation.panel.SearchPanel;
22  import nl.tudelft.simulation.language.DsolException;
23  
24  /**
25   * Animation panel with GIS layers and various controls.
26   * <p>
27   * Copyright (c) 2020-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
28   * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
29   * project is distributed under a three-clause BSD-style license, which can be found at
30   * <a href="https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
31   * </p>
32   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
33   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
34   */
35  public class DsolAnimationGisTab extends DsolAnimationTab
36  {
37      /** */
38      private static final long serialVersionUID = 20150617L;
39  
40      /** Set of GIS layer names to toggle GIS layers . */
41      private Map<String, GisMapInterface> toggleGISMap = new LinkedHashMap<>();
42  
43      /** Set of GIS layer names to toggle buttons. */
44      private Map<String, JToggleButton> toggleGISButtons = new LinkedHashMap<>();
45  
46      /**
47       * Construct a tab with an AnimationPane for the animation of a DsolModel, including GIS layers.
48       * @param homeExtent initial extent of the animation
49       * @param simulator the simulator
50       * @throws DsolException when simulator does not implement the AnimatorInterface
51       */
52      public DsolAnimationGisTab(final Bounds2d homeExtent, final SimulatorInterface<?> simulator) throws DsolException
53      {
54          super(homeExtent, simulator);
55      }
56  
57      /**
58       * Construct a tab with an AnimationPane for the animation of a DsolModel, including GIS layers.
59       * @param simulator the simulator
60       * @param animationPanel the animation panel to use, e.g. the AutoPanAnimationPanel
61       * @throws DsolException when simulator does not implement the AnimatorInterface
62       */
63      public DsolAnimationGisTab(final SimulatorInterface<?> simulator, final AnimationPanel animationPanel) throws DsolException
64      {
65          super(simulator, animationPanel);
66      }
67  
68      /**
69       * Construct a tab with an AutoPanAnimationPanel and a linked SearchPanel for the animation of a DsolModel, including GIS
70       * layers.
71       * @param homeExtent initial extent of the animation
72       * @param simulator the simulator
73       * @return a tab with an AutoPanAnimationPanel and a linked SearchPanel
74       * @throws DsolException when simulator does not implement the AnimatorInterface
75       */
76      public static DsolAnimationTab createAutoPanTab(final Bounds2d homeExtent, final SimulatorInterface<?> simulator)
77              throws DsolException
78      {
79          DsolAnimationTab tab = new DsolAnimationTab(simulator, new AutoPanAnimationPanel(homeExtent, simulator));
80          tab.setSearchPanel(new SearchPanel());
81          return tab;
82      }
83  
84      /**
85       * Add buttons for toggling all GIS layers on or off.
86       * @param header the name of the group of layers
87       * @param gisMap the GIS map for which the toggles have to be added
88       * @param toolTipText the tool tip text to show when hovering over the button
89       */
90      public void addAllToggleGISButtonText(final String header, final GisRenderable2d gisMap, final String toolTipText)
91      {
92          addToggleText(" ");
93          addToggleText(header);
94          for (String layerName : gisMap.getMap().getLayerMap().keySet())
95          {
96              addToggleGISButtonText(layerName, layerName, gisMap, toolTipText);
97          }
98      }
99  
100     /**
101      * Add a button to toggle a GIS Layer on or off.
102      * @param layerName the name of the layer
103      * @param displayName the name to display next to the tick box
104      * @param gisMap the map
105      * @param toolTipText the tool tip text
106      */
107     public void addToggleGISButtonText(final String layerName, final String displayName, final GisRenderable2d gisMap,
108             final String toolTipText)
109     {
110         JToggleButton button;
111         button = new JCheckBox(displayName);
112         button.setName(layerName);
113         button.setEnabled(true);
114         button.setSelected(true);
115         button.setActionCommand(layerName);
116         button.setToolTipText(toolTipText);
117         button.addActionListener(this);
118 
119         JPanel toggleBox = new JPanel();
120         toggleBox.setLayout(new BoxLayout(toggleBox, BoxLayout.X_AXIS));
121         toggleBox.add(button);
122         getTogglePanel().add(toggleBox);
123         toggleBox.setAlignmentX(Component.LEFT_ALIGNMENT);
124 
125         this.toggleGISMap.put(layerName, gisMap.getMap());
126         this.toggleGISButtons.put(layerName, button);
127     }
128 
129     /**
130      * Set a GIS layer to be shown in the animation to true.
131      * @param layerName the name of the GIS-layer that has to be shown.
132      */
133     public void showGISLayer(final String layerName)
134     {
135         GisMapInterface gisMap = this.toggleGISMap.get(layerName);
136         if (gisMap != null)
137         {
138             gisMap.showLayer(layerName);
139             this.toggleGISButtons.get(layerName).setSelected(true);
140             getAnimationPanel().repaint();
141         }
142     }
143 
144     /**
145      * Set a GIS layer to be hidden in the animation to true.
146      * @param layerName the name of the GIS-layer that has to be hidden.
147      */
148     public void hideGISLayer(final String layerName)
149     {
150         GisMapInterface gisMap = this.toggleGISMap.get(layerName);
151         if (gisMap != null)
152         {
153             gisMap.hideLayer(layerName);
154             this.toggleGISButtons.get(layerName).setSelected(false);
155             getAnimationPanel().repaint();
156         }
157     }
158 
159     /**
160      * Toggle a GIS layer to be displayed in the animation to its reverse value.
161      * @param layerName the name of the GIS-layer that has to be turned off or vice versa.
162      */
163     public void toggleGISLayer(final String layerName)
164     {
165         GisMapInterface gisMap = this.toggleGISMap.get(layerName);
166         if (gisMap != null)
167         {
168             if (gisMap.getVisibleLayers().contains(gisMap.getLayerMap().get(layerName)))
169             {
170                 gisMap.hideLayer(layerName);
171                 this.toggleGISButtons.get(layerName).setSelected(false);
172             }
173             else
174             {
175                 gisMap.showLayer(layerName);
176                 this.toggleGISButtons.get(layerName).setSelected(true);
177             }
178             getAnimationPanel().repaint();
179         }
180     }
181 
182     @Override
183     public void actionPerformed(final ActionEvent actionEvent)
184     {
185         String actionCommand = actionEvent.getActionCommand();
186         try
187         {
188             if (this.toggleGISMap.containsKey(actionCommand))
189             {
190                 this.toggleGISLayer(actionCommand);
191                 getTogglePanel().repaint();
192             }
193             super.actionPerformed(actionEvent); // handle other commands
194         }
195         catch (Exception exception)
196         {
197             CategoryLogger.always().warn(exception);
198         }
199     }
200 
201 }