View Javadoc
1   package org.opentrafficsim.swing.gui;
2   
3   import java.awt.Color;
4   import java.awt.Dimension;
5   import java.awt.event.ActionEvent;
6   import java.awt.event.ActionListener;
7   import java.awt.event.FocusEvent;
8   import java.awt.event.FocusListener;
9   import java.util.Optional;
10  
11  import javax.swing.Box;
12  import javax.swing.BoxLayout;
13  import javax.swing.JCheckBox;
14  import javax.swing.JComboBox;
15  import javax.swing.JLabel;
16  import javax.swing.JPanel;
17  import javax.swing.JTextField;
18  import javax.swing.event.DocumentEvent;
19  import javax.swing.event.DocumentListener;
20  
21  import org.djutils.base.Identifiable;
22  import org.opentrafficsim.animation.data.util.IconUtil;
23  import org.opentrafficsim.core.gtu.Gtu;
24  import org.opentrafficsim.core.network.Link;
25  import org.opentrafficsim.core.network.Network;
26  import org.opentrafficsim.core.network.Node;
27  
28  import nl.tudelft.simulation.dsol.animation.Locatable;
29  
30  /**
31   * The OTS search panel.
32   * <p>
33   * Copyright (c) 2020-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
34   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
35   * </p>
36   * @author Alexander Verbraeck
37   * @author Peter Knoppers
38   * @author Wouter Schakel
39   */
40  public class OtsSearchPanel extends JPanel implements ActionListener, FocusListener, DocumentListener
41  {
42  
43      /** ... */
44      private static final long serialVersionUID = 20200127L;
45  
46      /** The animation panel. */
47      private final OtsSimulationPanel otsAnimationPanel;
48  
49      /** The type-of-object-to-search-for selector. */
50      private final JComboBox<ObjectKind<?>> typeToSearch;
51  
52      /** Id of the object to search for. */
53      private final JTextField idTextField;
54  
55      /** Track object check box. */
56      private final JCheckBox trackObject;
57  
58      /**
59       * Construct a new OtsSearchPanel.
60       * @param otsAnimationPanel the animation panel
61       */
62      public OtsSearchPanel(final OtsSimulationPanel otsAnimationPanel)
63      {
64          this.otsAnimationPanel = otsAnimationPanel;
65          this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
66          this.add(new JLabel(IconUtil.of("Find24.png").imageSize(18, 18).get()));
67          this.add(Box.createHorizontalStrut(5));
68          ObjectKind<?>[] objectKinds = new ObjectKind[] {new ObjectKind<Gtu>("GTU")
69          {
70              @Override
71              Optional<Gtu> searchNetwork(final Network network, final String id)
72              {
73                  return network.getGTU(id);
74              }
75          }, new ObjectKind<Node>("Node")
76          {
77              @Override
78              Optional<Node> searchNetwork(final Network network, final String id)
79              {
80                  return network.getNode(id);
81              }
82          }, new ObjectKind<Link>("Link")
83          {
84              @Override
85              Optional<Link> searchNetwork(final Network network, final String id)
86              {
87                  return network.getLink(id);
88              }
89          }};
90          this.typeToSearch = new JComboBox<ObjectKind<?>>(objectKinds);
91          this.typeToSearch.setPreferredSize(new Dimension(55, 25));
92          this.typeToSearch.setMaximumSize(new Dimension(100, 25));
93          this.add(this.typeToSearch);
94  
95          this.idTextField = new AppearanceControlTextField();
96          this.idTextField.setMinimumSize(new Dimension(100, 25));
97          this.idTextField.setPreferredSize(new Dimension(100, 25));
98          this.idTextField.setMaximumSize(new Dimension(100, 25));
99          this.add(this.idTextField);
100         this.trackObject = new JCheckBox("Track");
101         this.add(this.trackObject);
102         this.trackObject.setActionCommand("Tracking status changed");
103         this.idTextField.setActionCommand("Id changed");
104         this.typeToSearch.setActionCommand("Type changed");
105         this.trackObject.addActionListener(this);
106         this.idTextField.addActionListener(this);
107         this.typeToSearch.addActionListener(this);
108         this.idTextField.addFocusListener(this);
109         this.idTextField.getDocument().addDocumentListener(this);
110         new GhostText(this.idTextField, "Id...").setGhostColor(Color.GRAY);
111     }
112 
113     /**
114      * Update all values at once.
115      * @param objectKey key of the object type to search
116      * @param id id of object to search
117      * @param track if true; track continuously; if false; center on it, but do not track
118      */
119     public void selectAndTrackObject(final String objectKey, final String id, final boolean track)
120     {
121         for (int index = this.typeToSearch.getItemCount(); --index >= 0;)
122         {
123             if (this.typeToSearch.getItemAt(index).getKey().equals(objectKey))
124             {
125                 this.typeToSearch.setSelectedIndex(index);
126             }
127         }
128         this.trackObject.setSelected(track);
129         this.idTextField.setText(id);
130         actionPerformed(null);
131     }
132 
133     @Override
134     public void actionPerformed(final ActionEvent e)
135     {
136         this.otsAnimationPanel.setAutoPan(this.idTextField.getText(), (ObjectKind<?>) this.typeToSearch.getSelectedItem(),
137                 this.trackObject.isSelected());
138     }
139 
140     @Override
141     public void focusGained(final FocusEvent e)
142     {
143         actionPerformed(null);
144     }
145 
146     @Override
147     public void focusLost(final FocusEvent e)
148     {
149         // Do nothing
150     }
151 
152     @Override
153     public void insertUpdate(final DocumentEvent e)
154     {
155         actionPerformed(null);
156     }
157 
158     @Override
159     public void removeUpdate(final DocumentEvent e)
160     {
161         actionPerformed(null);
162     }
163 
164     @Override
165     public void changedUpdate(final DocumentEvent e)
166     {
167         actionPerformed(null);
168     }
169 
170     /**
171      * Entries in the typeToSearch {@link JComboBox} of the OTS search panel.
172      * @param <T> Type of object identified by key
173      */
174     abstract static class ObjectKind<T extends Locatable & Identifiable>
175     {
176         /** The key of this ObjectKind. */
177         private final String key;
178 
179         /**
180          * Constructor.
181          * @param key key as shown to the user
182          */
183         ObjectKind(final String key)
184         {
185             this.key = key;
186         }
187 
188         /**
189          * Retrieve the key.
190          * @return the key
191          */
192         public Object getKey()
193         {
194             return this.key;
195         }
196 
197         /**
198          * Lookup an object of type T in an OTS network.
199          * @param network the OTS network
200          * @param id id of the object to return
201          * @return the object in the network of the correct type and matching id, empty if no matching object was found
202          */
203         abstract Optional<T> searchNetwork(Network network, String id);
204 
205         /**
206          * Produce the text that will appear in the combo box. This method should be overridden to implement localization.
207          */
208         @Override
209         public String toString()
210         {
211             return this.key;
212         }
213     }
214 }