package org.opentrafficsim.demo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
import org.djutils.reflection.ClassUtil;
import org.opentrafficsim.core.dsol.OTSModelInterface;
import org.opentrafficsim.demo.conflict.BusStreetDemo;
import org.opentrafficsim.demo.conflict.TJunctionDemo;
import org.opentrafficsim.demo.conflict.TurboRoundaboutDemo;
import org.opentrafficsim.demo.trafficcontrol.TrafCODDemo1;
import org.opentrafficsim.demo.trafficcontrol.TrafCODDemo2;
import org.opentrafficsim.swing.gui.OTSSwingApplication;
/**
* SuperDemo.java.
*
* Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information www.simulation.tudelft.nl. The
* source code and binary code of this software is proprietary information of Delft University of Technology.
* @author Alexander Verbraeck
*/
public class SuperDemo extends JFrame
{
/** */
private static final long serialVersionUID = 1L;
/** demos to show. */
private List demos = new ArrayList<>();
/**
* Construct a mode chooser that can start different models.
* @throws HeadlessException when not run in graphics environment
*/
public SuperDemo() throws HeadlessException
{
super("OTS demo models");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setMinimumSize(new Dimension(1024, 20));
addDemos();
setContentPane(makeGUI());
pack();
setVisible(true);
}
/**
* Add the demos to the list.
*/
private void addDemos()
{
this.demos.add(new Demo("Straight", StraightSwing.class, "Single lane road with a blockage for a while.\n"
+ "The model shows the dissolving of the congestion that occurs as a result."));
this.demos.add(new Demo("SequentialLanes", SequentialLanes.class,
"Cars and trucks driving on several sequential lanes, each around 1 km long.\n"));
this.demos.add(new Demo("CircularRoad", CircularRoadSwing.class, "Model of a two-lane circular road with overtaking.\n"
+ "Users can specify the fraction of cars and trucks, as well as some driving parameters."));
this.demos.add(new Demo("CircularLane", CircularLaneSwing.class, "Model of a one-lane circular road with overtaking.\n"
+ "Users can specify the fraction of cars and trucks, as well as some driving parameters."));
this.demos.add(new Demo("FundamentalDiagrams", FundamentalDiagrams.class,
"Creating fundamental diagrams for a straight road.\n"));
this.demos.add(new Demo("ShortMerge", ShortMerge.class, "Short merge on a highway, followed by a destination split,\n"
+ "forcing cars to change lanes in a relative short distance."));
this.demos.add(new Demo("TJunction", TJunctionDemo.class, "Complex crossing traffic on a T-junction with\n"
+ "automated conflict resolution."));
this.demos.add(new Demo("TurboRoundabout", TurboRoundaboutDemo.class, "Turbo Roundabout without traffic lights,\n"
+ "conflict resolution is fully automated."));
this.demos.add(new Demo("BusStreet", BusStreetDemo.class, "Interaction between bus traffic and normal road traffic,\n"
+ "several types of bus stops and busses."));
this.demos.add(new Demo("Networks", NetworksSwing.class,
"A number of different networks with merging and splitting,\n" + "forcing cars to change lanes and to merge."));
this.demos.add(new Demo("CrossingTrafficLights", CrossingTrafficLightsSwing.class,
"Model of a crossing with traffic lights.\n"));
this.demos.add(new Demo("TrafCODDemoSimple", TrafCODDemo1.class,
"Model of a simple crossing with traffic lights.\n" + "using a TrafCOD controller"));
this.demos.add(new Demo("TrafCODDemoComplex", TrafCODDemo2.class,
"Model of a complex crossing with traffic lights.\n" + "using a TrafCOD controller"));
}
/**
* @return a grid with model start buttons and short model descriptions.
*/
private JComponent makeGUI()
{
Box table = Box.createVerticalBox();
table.setBackground(Color.WHITE);
table.setOpaque(true);
JScrollPane scrollPane = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
int maxButtonWidth = 0;
table.add(Box.createRigidArea(new Dimension(0, 3)));
Box headerBox = Box.createHorizontalBox();
JLabel header = new JLabel(" OpenTrafficSim demo's ");
header.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 36));
headerBox.add(header);
headerBox.add(Box.createHorizontalGlue());
table.add(headerBox);
table.add(Box.createRigidArea(new Dimension(0, 3)));
table.add(new JSeparator());
for (Demo demo : this.demos)
{
table.add(Box.createRigidArea(new Dimension(0, 3)));
Box row = Box.createHorizontalBox();
row.add(new JLabel(" "));
row.add(demo.getButton());
row.add(new JLabel(" "));
JTextArea description = new JTextArea();
description.setText(demo.getDescription());
description.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 16));
description.setEditable(false);
description.setWrapStyleWord(true);
description.setLineWrap(true);
row.add(description);
row.add(Box.createHorizontalGlue());
row.add(new JLabel(" "));
table.add(row);
table.add(Box.createRigidArea(new Dimension(0, 3)));
table.add(new JSeparator());
maxButtonWidth = Math.max(maxButtonWidth, demo.getButton().getPreferredSize().width);
}
for (Demo demo : this.demos)
{
demo.getButton().setPreferredSize(new Dimension(maxButtonWidth, demo.getButton().getPreferredSize().height));
}
table.add(Box.createVerticalGlue());
return scrollPane;
}
/**
* @param args String[]; should be empty
*/
public static void main(final String[] args)
{
new SuperDemo();
}
/** the class to prevent the models from exiting the whole SuperDemo application. */
static class NoExitSecurityManager extends SecurityManager
{
@Override
public void checkExit(final int status)
{
throw new SecurityException();
}
}
/** the information about the demos. */
private static class Demo implements ActionListener
{
/** the demo name. */
@SuppressWarnings("checkstyle:visibilitymodifier")
protected final String name;
/** the start button for the demo. */
private final JButton button;
/** the demo class. */
@SuppressWarnings("checkstyle:visibilitymodifier")
protected final Class extends OTSSwingApplication extends OTSModelInterface>> clazz;
/** the demo description. */
private final String description;
/**
* @param name String; the demo name
* @param clazz Class<? extends OTSSwingApplication>; the demo class
* @param description String; the demo description
*/
Demo(final String name, final Class extends OTSSwingApplication extends OTSModelInterface>> clazz,
final String description)
{
this.name = name;
this.button = new JButton(name);
this.button.addActionListener(this);
this.clazz = clazz;
this.description = description;
}
/**
* @return the button to tart the demo
*/
public final JButton getButton()
{
return this.button;
}
/**
* @return the demo description
*/
public final String getDescription()
{
return this.description;
}
/** {@inheritDoc} */
@Override
public void actionPerformed(final ActionEvent e)
{
try
{
final Method demoMethod = ClassUtil.resolveMethod(this.clazz, "demo", new Class[] {boolean.class});
Thread demo = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
Class.forName(Demo.this.clazz.getName());
demoMethod.invoke(null, new Object[] {false});
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| ClassNotFoundException exception)
{
exception.printStackTrace();
JOptionPane
.showMessageDialog(null,
"Method 'demo' for demo " + Demo.this.name + " cound not be started\n"
+ exception.getMessage(),
"Could not start demo", JOptionPane.ERROR_MESSAGE);
}
}
});
demo.start();
}
catch (NoSuchMethodException exception)
{
JOptionPane.showMessageDialog(null, "Method 'demo' not found for demo " + this.name, "Could not start demo",
JOptionPane.ERROR_MESSAGE);
}
}
}
}