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