View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.awt.Color;
4   import java.awt.Dimension;
5   import java.awt.Font;
6   import java.awt.HeadlessException;
7   import java.awt.event.ActionEvent;
8   import java.awt.event.ActionListener;
9   import java.lang.reflect.InvocationTargetException;
10  import java.lang.reflect.Method;
11  import java.util.ArrayList;
12  import java.util.List;
13  
14  import javax.swing.Box;
15  import javax.swing.JButton;
16  import javax.swing.JComponent;
17  import javax.swing.JFrame;
18  import javax.swing.JLabel;
19  import javax.swing.JOptionPane;
20  import javax.swing.JScrollPane;
21  import javax.swing.JSeparator;
22  import javax.swing.JTextArea;
23  import javax.swing.ScrollPaneConstants;
24  import javax.swing.WindowConstants;
25  
26  import org.djutils.reflection.ClassUtil;
27  import org.opentrafficsim.core.dsol.OtsModelInterface;
28  import org.opentrafficsim.demo.conflict.TJunctionDemo;
29  import org.opentrafficsim.demo.conflict.TurboRoundaboutDemo;
30  import org.opentrafficsim.demo.trafficcontrol.TrafCodDemo2;
31  import org.opentrafficsim.swing.gui.OtsSwingApplication;
32  
33  /**
34   * SuperDemo.java.
35   * <p>
36   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
37   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
38   * </p>
39   * @author <a href="https://github.com/averbraeck" target="_blank">Alexander Verbraeck</a>
40   */
41  public class SuperDemo extends JFrame
42  {
43      /** */
44      private static final long serialVersionUID = 1L;
45  
46      /** demos to show. */
47      private List<Demo> demos = new ArrayList<>();
48  
49      /**
50       * Construct a mode chooser that can start different models.
51       * @throws HeadlessException when not run in graphics environment
52       */
53      public SuperDemo() throws HeadlessException
54      {
55          super("OTS demo models");
56          setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
57          setMinimumSize(new Dimension(1024, 20));
58          addDemos();
59          setContentPane(makeGUI());
60          pack();
61          setVisible(true);
62      }
63  
64      /**
65       * Add the demos to the list.
66       */
67      private void addDemos()
68      {
69          this.demos.add(new Demo("Straight", StraightSwing.class, "Single lane road with a blockage for a while.\n"
70                  + "The model shows the dissolving of the congestion that occurs as a result."));
71          this.demos.add(new Demo("CircularRoad", CircularRoadSwing.class, "Model of a two-lane circular road with overtaking.\n"
72                  + "Users can specify the fraction of cars and trucks, as well as some driving parameters."));
73          this.demos.add(new Demo("ShortMerge", ShortMerge.class, "Short merge on a highway, followed by a destination split,\n"
74                  + "forcing cars to change lanes in a relative short distance."));
75          this.demos.add(new Demo("TJunction", TJunctionDemo.class,
76                  "Complex crossing traffic on a T-junction with\n" + "automated conflict resolution."));
77          this.demos.add(new Demo("TurboRoundabout", TurboRoundaboutDemo.class,
78                  "Turbo Roundabout without traffic lights,\n" + "conflict resolution is fully automated."));
79          this.demos.add(new Demo("Networks", NetworksSwing.class,
80                  "A number of different networks with merging and splitting,\n" + "forcing cars to change lanes and to merge."));
81          this.demos.add(new Demo("TrafCODDemoComplex", TrafCodDemo2.class,
82                  "Model of a complex crossing with traffic lights.\n" + "using a TrafCOD controller"));
83      }
84  
85      /**
86       * @return a grid with model start buttons and short model descriptions.
87       */
88      private JComponent makeGUI()
89      {
90          Box table = Box.createVerticalBox();
91          table.setBackground(Color.WHITE);
92          table.setOpaque(true);
93          JScrollPane scrollPane = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
94                  ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
95          int maxButtonWidth = 0;
96          table.add(Box.createRigidArea(new Dimension(0, 3)));
97          Box headerBox = Box.createHorizontalBox();
98          JLabel header = new JLabel(" OpenTrafficSim demo's ");
99          header.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 36));
100         headerBox.add(header);
101         headerBox.add(Box.createHorizontalGlue());
102         table.add(headerBox);
103         table.add(Box.createRigidArea(new Dimension(0, 3)));
104         table.add(new JSeparator());
105         for (Demo demo : this.demos)
106         {
107             table.add(Box.createRigidArea(new Dimension(0, 3)));
108             Box row = Box.createHorizontalBox();
109             row.add(new JLabel("  "));
110             row.add(demo.getButton());
111             row.add(new JLabel("  "));
112             JTextArea description = new JTextArea();
113             description.setText(demo.getDescription());
114             description.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 16));
115             description.setEditable(false);
116             description.setWrapStyleWord(true);
117             description.setLineWrap(true);
118             row.add(description);
119             row.add(Box.createHorizontalGlue());
120             row.add(new JLabel("  "));
121             table.add(row);
122             table.add(Box.createRigidArea(new Dimension(0, 3)));
123             table.add(new JSeparator());
124             maxButtonWidth = Math.max(maxButtonWidth, demo.getButton().getPreferredSize().width);
125         }
126 
127         for (Demo demo : this.demos)
128         {
129             demo.getButton().setPreferredSize(new Dimension(maxButtonWidth, demo.getButton().getPreferredSize().height));
130         }
131 
132         table.add(Box.createVerticalGlue());
133 
134         return scrollPane;
135     }
136 
137     /**
138      * Main method.
139      * @param args should be empty
140      */
141     public static void main(final String[] args)
142     {
143         new SuperDemo();
144     }
145 
146     /** the information about the demos. */
147     private static class Demo implements ActionListener
148     {
149         /** the demo name. */
150         @SuppressWarnings("checkstyle:visibilitymodifier")
151         protected final String name;
152 
153         /** the start button for the demo. */
154         private final JButton button;
155 
156         /** the demo class. */
157         @SuppressWarnings("checkstyle:visibilitymodifier")
158         protected final Class<? extends OtsSwingApplication<? extends OtsModelInterface>> clazz;
159 
160         /** the demo description. */
161         private final String description;
162 
163         /**
164          * @param name the demo name
165          * @param clazz the demo class
166          * @param description the demo description
167          */
168         Demo(final String name, final Class<? extends OtsSwingApplication<? extends OtsModelInterface>> clazz,
169                 final String description)
170         {
171             this.name = name;
172             this.button = new JButton(name);
173             this.button.addActionListener(this);
174             this.clazz = clazz;
175             this.description = description;
176         }
177 
178         /**
179          * @return the button to tart the demo
180          */
181         public final JButton getButton()
182         {
183             return this.button;
184         }
185 
186         /**
187          * @return the demo description
188          */
189         public final String getDescription()
190         {
191             return this.description;
192         }
193 
194         @Override
195         public void actionPerformed(final ActionEvent e)
196         {
197             try
198             {
199                 final Method demoMethod = ClassUtil.resolveMethod(this.clazz, "demo", new Class[] {boolean.class});
200                 Thread demo = new Thread(new Runnable()
201                 {
202                     @Override
203                     public void run()
204                     {
205                         try
206                         {
207                             Class.forName(Demo.this.clazz.getName());
208                             demoMethod.invoke(null, new Object[] {false});
209                         }
210                         catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
211                                 | ClassNotFoundException exception)
212                         {
213                             exception.printStackTrace();
214                             JOptionPane
215                                     .showMessageDialog(null,
216                                             "Method 'demo' for demo " + Demo.this.name + " cound not be started\n"
217                                                     + exception.getMessage(),
218                                             "Could not start demo", JOptionPane.ERROR_MESSAGE);
219                         }
220                     }
221                 });
222                 demo.start();
223             }
224             catch (NoSuchMethodException exception)
225             {
226                 JOptionPane.showMessageDialog(null, "Method 'demo' not found for demo " + this.name, "Could not start demo",
227                         JOptionPane.ERROR_MESSAGE);
228             }
229         }
230     }
231 }