495 lines
15 KiB
Java
495 lines
15 KiB
Java
|
package simulator.view;
|
|||
|
|
|||
|
import java.awt.BorderLayout;
|
|||
|
import java.awt.Dimension;
|
|||
|
import java.awt.Frame;
|
|||
|
import java.awt.event.ActionEvent;
|
|||
|
import java.awt.event.ActionListener;
|
|||
|
import java.io.File;
|
|||
|
import java.io.FileInputStream;
|
|||
|
import java.io.FileNotFoundException;
|
|||
|
import java.io.FileOutputStream;
|
|||
|
import java.io.IOException;
|
|||
|
import java.io.InputStream;
|
|||
|
import java.io.OutputStream;
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.List;
|
|||
|
|
|||
|
import javax.swing.Box;
|
|||
|
import javax.swing.ImageIcon;
|
|||
|
import javax.swing.JButton;
|
|||
|
import javax.swing.JFileChooser;
|
|||
|
import javax.swing.JFrame;
|
|||
|
import javax.swing.JLabel;
|
|||
|
import javax.swing.JOptionPane;
|
|||
|
import javax.swing.JPanel;
|
|||
|
import javax.swing.JSpinner;
|
|||
|
import javax.swing.JToolBar;
|
|||
|
import javax.swing.SpinnerNumberModel;
|
|||
|
import javax.swing.SwingUtilities;
|
|||
|
import javax.swing.event.ChangeEvent;
|
|||
|
import javax.swing.event.ChangeListener;
|
|||
|
|
|||
|
import simulator.control.Controller;
|
|||
|
import simulator.exceptions.UnsupportedFileException;
|
|||
|
import simulator.misc.Pair;
|
|||
|
import simulator.model.Event;
|
|||
|
import simulator.model.NewSetContClassEvent;
|
|||
|
import simulator.model.NewSetWeatherEvent;
|
|||
|
import simulator.model.RoadMap;
|
|||
|
import simulator.model.TrafficSimObserver;
|
|||
|
import simulator.model.Weather;
|
|||
|
|
|||
|
public class ControlPanel extends JPanel implements TrafficSimObserver {
|
|||
|
|
|||
|
/**
|
|||
|
*
|
|||
|
*/
|
|||
|
private static final long serialVersionUID = 1L;
|
|||
|
|
|||
|
//Atributos:
|
|||
|
private JButton loadFile; //Abre un di<64>logo para seleccionar un fichero de eventos (utilizando JFileChooser).
|
|||
|
private JButton saveFile; //Abre un di<64>logo para guardar el estado actual (utilizando JFileChooser).
|
|||
|
private JButton changeVehicleContClass; //Abre una ventana de di<64>logo donde el usuario puede seleccionar un veh<65>culo V, una clase de contaminaci<63>n C (0-10) y un n<>mero de ticks N.
|
|||
|
private JButton changeRoadWeather; //Abre una ventana de di<64>logo donde el usuario puede seleccionar una carretera R, unas condiciones atmosf<73>ricas W, y un n<>mero de ticks N
|
|||
|
private JButton run; //Ejecuta el simulador.
|
|||
|
private JButton stop; //Para el simulador.
|
|||
|
private JButton restart; //Reinicia el simulador desde el archivo cargado previamente.
|
|||
|
private JButton exit; //Sale del simulador.
|
|||
|
|
|||
|
private JSpinner nTicks; //N<>mero de veces que se ejecuta la simulaci<63>n.
|
|||
|
private JLabel ticks; //Barra para mostrar el n<>mero de ticks de la simulaci<63>n.
|
|||
|
|
|||
|
private JToolBar toolbar; //Barra de herramientas.
|
|||
|
private JFileChooser fileChooser; //Selector de archivos.
|
|||
|
|
|||
|
private Controller _ctrl;
|
|||
|
private RoadMap _map;
|
|||
|
private int _time;
|
|||
|
private static boolean _stopped = true;
|
|||
|
private int _nTicks = 10;
|
|||
|
|
|||
|
private File file;
|
|||
|
|
|||
|
|
|||
|
//Constructor:
|
|||
|
public ControlPanel(Controller ctrl) {
|
|||
|
super();
|
|||
|
this._ctrl = ctrl;
|
|||
|
this._nTicks = 0;
|
|||
|
this.file = null;
|
|||
|
this.InitGUI();
|
|||
|
ctrl.addObserver(this);
|
|||
|
}
|
|||
|
|
|||
|
//M<>todos:
|
|||
|
private void InitGUI() {
|
|||
|
|
|||
|
//Inicia el panel de control:
|
|||
|
this.toolbar = new JToolBar();
|
|||
|
this.setLayout(new BorderLayout());
|
|||
|
this.add(toolbar, BorderLayout.PAGE_START);
|
|||
|
|
|||
|
//A<>ade la carga de ficheros:
|
|||
|
this.initLoadButton();
|
|||
|
//this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el guardado de la simulaci<63>n: (no se pide en la pr<70>ctica, lo a<>ado como parte opcional)
|
|||
|
this.initSaveButton();
|
|||
|
this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de cambio de clase de contaminaci<63>n del veh<65>culo:
|
|||
|
this.initChangeVehicleContClassButton();
|
|||
|
this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de cambio de condiciones atmosf<73>ricas en la carretera:
|
|||
|
this.initChangeRoadWeather();
|
|||
|
this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de incio:
|
|||
|
this.initRunButton();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de parada:
|
|||
|
this.initStopButton();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de reinicio: (no se pide en la pr<70>ctica, lo a<>ado como parte opcional)
|
|||
|
this.initRestartButton();
|
|||
|
this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el n<>mero de ticks de la simulaci<63>n:
|
|||
|
this.ticks = new JLabel();
|
|||
|
this.ticks.setText("Ticks: ");
|
|||
|
this.toolbar.add(this.ticks);
|
|||
|
this.initTicksSpinner();
|
|||
|
this.toolbar.addSeparator();
|
|||
|
|
|||
|
//A<>ade el bot<6F>n de salir:
|
|||
|
this.initExitButton();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void initLoadButton() {
|
|||
|
this.fileChooser = new JFileChooser();
|
|||
|
this.fileChooser.setDialogTitle("Elige el archivo de eventos para la simulaci<63>n");
|
|||
|
this.fileChooser.setCurrentDirectory(new File("resources/examples/"));
|
|||
|
this.loadFile = new JButton();
|
|||
|
this.loadFile.setToolTipText("Carga el archivo de eventos de la simulaci<63>n");
|
|||
|
this.loadFile.setIcon(new ImageIcon(this.getClass().getResource("/icons/open.png")));
|
|||
|
|
|||
|
this.loadFile.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
int choseF = fileChooser.showOpenDialog(fileChooser);
|
|||
|
|
|||
|
if (choseF == JFileChooser.APPROVE_OPTION) {
|
|||
|
System.out.println("Archivo seleccionado: " + fileChooser.getSelectedFile());
|
|||
|
JOptionPane.showMessageDialog(fileChooser, "Has seleccionado el archivo: " + fileChooser.getSelectedFile());
|
|||
|
|
|||
|
//File file = fileChooser.getSelectedFile();
|
|||
|
file = fileChooser.getSelectedFile();
|
|||
|
InputStream input;
|
|||
|
try {
|
|||
|
input = new FileInputStream(file);
|
|||
|
if(input != null) {
|
|||
|
_ctrl.reset();
|
|||
|
try {
|
|||
|
_ctrl.loadEvents(input);
|
|||
|
} catch (UnsupportedFileException e2) {
|
|||
|
onError("Algo sali<6C> mal al cargar el archivo: " + e2.getMessage());
|
|||
|
}
|
|||
|
}
|
|||
|
try {
|
|||
|
input.close();
|
|||
|
} catch (IOException e1) {
|
|||
|
onError("Algo sali<6C> mal al cerrar el archivo: " + e1.getMessage());
|
|||
|
}
|
|||
|
} catch (FileNotFoundException ex) {
|
|||
|
onError("Algo sali<6C> mal al cargar el archivo: " + ex.getMessage());
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
System.out.println("No se ha cargado ning<6E>n archivo.");
|
|||
|
JOptionPane.showMessageDialog(fileChooser, "No se ha cargado ning<6E>n archivo.");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.loadFile);
|
|||
|
}
|
|||
|
|
|||
|
//A<>adido como parte opcional:
|
|||
|
private void initSaveButton() {
|
|||
|
this.fileChooser = new JFileChooser();
|
|||
|
this.fileChooser.setDialogTitle("Guarda el estado actual de la simulaci<63>n");
|
|||
|
this.fileChooser.setCurrentDirectory(new File("resources/examples/"));
|
|||
|
this.saveFile = new JButton();
|
|||
|
this.saveFile.setToolTipText("Guarda en un archivo el estado actual del simulador");
|
|||
|
this.saveFile.setIcon(new ImageIcon(this.getClass().getResource("/icons/save.png")));
|
|||
|
|
|||
|
this.saveFile.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
int choseF = fileChooser.showSaveDialog(fileChooser);
|
|||
|
|
|||
|
if (choseF == JFileChooser.APPROVE_OPTION) {
|
|||
|
System.out.println("Estado guardado: " + fileChooser.getSelectedFile());
|
|||
|
JOptionPane.showMessageDialog(fileChooser, "Estado guardado en el archivo: " + fileChooser.getSelectedFile());
|
|||
|
|
|||
|
File saveFile = fileChooser.getSelectedFile();
|
|||
|
OutputStream output;
|
|||
|
try {
|
|||
|
output = new FileOutputStream(saveFile + ".json");
|
|||
|
if(output != null) {
|
|||
|
_ctrl.save(output);
|
|||
|
}
|
|||
|
try {
|
|||
|
output.close();
|
|||
|
} catch (IOException e1) {
|
|||
|
onError("Algo sali<6C> mal al cerrar el archivo: " + e1.getMessage());
|
|||
|
}
|
|||
|
} catch (FileNotFoundException ex) {
|
|||
|
onError("Algo sali<6C> mal al guardar el archivo: " + ex.getMessage());
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
System.out.println("No se ha guardado el archivo.");
|
|||
|
JOptionPane.showMessageDialog(fileChooser, "No se ha guardado el archivo.");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.saveFile);
|
|||
|
}
|
|||
|
|
|||
|
private void initChangeVehicleContClassButton() {
|
|||
|
this.changeVehicleContClass = new JButton();
|
|||
|
this.changeVehicleContClass.setToolTipText("Cambia la clase de contaminaci<63>n del veh<65>culo.");
|
|||
|
this.changeVehicleContClass.setIcon(new ImageIcon(this.getClass().getResource("/icons/co2class.png")));
|
|||
|
|
|||
|
this.changeVehicleContClass.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
select_CO2Class();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.changeVehicleContClass);
|
|||
|
}
|
|||
|
|
|||
|
protected void select_CO2Class() {
|
|||
|
ChangueCO2Dialog dialog = new ChangueCO2Dialog ((Frame) SwingUtilities.getWindowAncestor(this));
|
|||
|
int status = dialog.open(_map);
|
|||
|
|
|||
|
if (status == 0) {
|
|||
|
System.out.println("Evento de cambio de contaminaci<63>n de veh<65>culo, cancelado.");
|
|||
|
//JOptionPane.showMessageDialog(new JFrame(), "Cancelado");
|
|||
|
}
|
|||
|
else {
|
|||
|
List<Pair<String, Integer>> cs = new ArrayList<>();
|
|||
|
cs.add(new Pair<String, Integer>((dialog.getVehicle()).getId(), dialog.getCO2Class()));
|
|||
|
try {
|
|||
|
_ctrl.addEvent(new NewSetContClassEvent(_time + dialog.getTicks(), cs));
|
|||
|
System.out.println("Nuevo evento de cambio de contaminaci<63>n de veh<65>culo a<>adido.");
|
|||
|
} catch (Exception ex) {
|
|||
|
onError("Algo sali<6C> mal: " + ex.getLocalizedMessage());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void initChangeRoadWeather() {
|
|||
|
this.changeRoadWeather = new JButton();
|
|||
|
this.changeRoadWeather.setToolTipText("Cambia el tiempo atmosf<73>rico de la carretera.");
|
|||
|
this.changeRoadWeather.setIcon(new ImageIcon(this.getClass().getResource("/icons/weather.png")));
|
|||
|
|
|||
|
this.changeRoadWeather.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
select_Weather();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.changeRoadWeather);
|
|||
|
}
|
|||
|
|
|||
|
protected void select_Weather() {
|
|||
|
ChangueWeatherDialog dialog = new ChangueWeatherDialog ((Frame) SwingUtilities.getWindowAncestor(this));
|
|||
|
int status = dialog.open(_map);
|
|||
|
|
|||
|
if (status == 0) {
|
|||
|
System.out.println("Evento de cambio de tiempo atmosf<73>rico, cancelado.");
|
|||
|
//JOptionPane.showMessageDialog(new JFrame(), "Cancelado");
|
|||
|
}
|
|||
|
else {
|
|||
|
List<Pair<String, Weather>> ws = new ArrayList<>();
|
|||
|
ws.add(new Pair<String, Weather>((dialog.getRoad()).getId(), dialog.getWeather()));
|
|||
|
try {
|
|||
|
_ctrl.addEvent(new NewSetWeatherEvent(_time + dialog.getTicks(), ws));
|
|||
|
System.out.println("Nuevo evento de cambio de tiempo atmosf<73>tico a<>adido.");
|
|||
|
} catch (Exception ex) {
|
|||
|
onError("Algo sali<6C> mal: " + ex.getLocalizedMessage());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void initRunButton() {
|
|||
|
this.run = new JButton();
|
|||
|
this.run.setToolTipText("Ejecuta el simulador.");
|
|||
|
this.run.setIcon(new ImageIcon(this.getClass().getResource("/icons/run.png")));
|
|||
|
|
|||
|
this.run.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
_stopped = false;
|
|||
|
enableToolBar(false);
|
|||
|
run_sim(_nTicks);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.run);
|
|||
|
}
|
|||
|
|
|||
|
private void initStopButton() {
|
|||
|
this.stop = new JButton();
|
|||
|
this.stop.setToolTipText("Para la simulaci<63>n.");
|
|||
|
this.stop.setIcon(new ImageIcon(this.getClass().getResource("/icons/stop.png")));
|
|||
|
|
|||
|
this.stop.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
stop();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.stop);
|
|||
|
}
|
|||
|
|
|||
|
//A<>adido como parte opcional:
|
|||
|
private void initRestartButton() {
|
|||
|
this.restart = new JButton();
|
|||
|
this.restart.setToolTipText("Reinicia la simulaci<63>n.");
|
|||
|
this.restart.setIcon(new ImageIcon(this.getClass().getResource("/icons/reset.png")));
|
|||
|
|
|||
|
this.restart.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
if(file != null) {
|
|||
|
InputStream input = null;
|
|||
|
try {
|
|||
|
input = new FileInputStream(file);
|
|||
|
} catch (FileNotFoundException e1) {
|
|||
|
e1.printStackTrace();
|
|||
|
}
|
|||
|
_ctrl.reset();
|
|||
|
try {
|
|||
|
_ctrl.loadEvents(input);
|
|||
|
} catch (UnsupportedFileException e2) {
|
|||
|
onError("Algo sali<6C> mal al cargar el archivo: " + e2.getMessage());
|
|||
|
}
|
|||
|
System.out.println("Reiniciado el simulador con el archivo: " + file);
|
|||
|
JOptionPane.showMessageDialog(fileChooser, "Se ha reiniciado el simulador.");
|
|||
|
try {
|
|||
|
input.close();
|
|||
|
} catch (IOException e1) {
|
|||
|
// TODO Auto-generated catch block
|
|||
|
e1.printStackTrace();
|
|||
|
}
|
|||
|
}else {
|
|||
|
onError("Error al reiniciar el simulador: No se ha cargado ning<6E>n archivo.");
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.restart);
|
|||
|
}
|
|||
|
|
|||
|
private void initExitButton() {
|
|||
|
this.exit = new JButton();
|
|||
|
this.exit.setToolTipText("Sale del simulador.");
|
|||
|
this.exit.setIcon(new ImageIcon(this.getClass().getResource("/icons/exit.png")));
|
|||
|
|
|||
|
this.exit.addActionListener(new ActionListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void actionPerformed(ActionEvent e) {
|
|||
|
int opt = JOptionPane.showConfirmDialog(null, "<EFBFBD>Est<EFBFBD>s seguro que quieres salir?", "SALIR", JOptionPane.YES_NO_OPTION);
|
|||
|
if (opt == JOptionPane.YES_OPTION) {
|
|||
|
System.out.println("Fin de la simulaci<63>n.");
|
|||
|
System.exit(0);
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(Box.createHorizontalGlue());
|
|||
|
this.toolbar.add(this.exit);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void initTicksSpinner() {
|
|||
|
SpinnerNumberModel model = new SpinnerNumberModel(1, 0, 10000, 1);
|
|||
|
this.nTicks = new JSpinner(model);
|
|||
|
this.nTicks.setValue(0);
|
|||
|
this.nTicks.setMinimumSize(new Dimension(70, 20));
|
|||
|
this.nTicks.setMaximumSize(new Dimension(200, 20));
|
|||
|
this.nTicks.setPreferredSize(new Dimension(70, 20));
|
|||
|
this.nTicks.addChangeListener(new ChangeListener() {
|
|||
|
|
|||
|
@Override
|
|||
|
public void stateChanged(ChangeEvent e) {
|
|||
|
_nTicks = Integer.valueOf(nTicks.getValue().toString());
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
this.toolbar.add(this.nTicks);
|
|||
|
}
|
|||
|
|
|||
|
private void run_sim(int n) {
|
|||
|
if (n > 0 && !_stopped) {
|
|||
|
try {
|
|||
|
this._ctrl.run(1);
|
|||
|
} catch (Exception e) {
|
|||
|
// TODO show error message
|
|||
|
e.getCause();
|
|||
|
//e.getMessage("Error al ejecutar el simulador.");
|
|||
|
_stopped = true;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
SwingUtilities.invokeLater(new Runnable() {
|
|||
|
@Override
|
|||
|
public void run() {
|
|||
|
run_sim(n - 1);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
enableToolBar(true);
|
|||
|
//this.toolbar.setEnabled(true);
|
|||
|
_stopped = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void stop() {
|
|||
|
_stopped = true;
|
|||
|
}
|
|||
|
|
|||
|
private void enableToolBar(boolean set) {
|
|||
|
this.loadFile.setEnabled(set);
|
|||
|
this.saveFile.setEnabled(set);
|
|||
|
this.changeVehicleContClass.setEnabled(set);
|
|||
|
this.changeRoadWeather.setEnabled(set);
|
|||
|
this.run.setEnabled(set);
|
|||
|
this.restart.setEnabled(set);
|
|||
|
this.exit.setEnabled(set);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@Override
|
|||
|
public void onAdvanceStart(RoadMap map, List<Event> events, int time) {
|
|||
|
this._map = map;
|
|||
|
this._time = time;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onAdvanceEnd(RoadMap map, List<Event> events, int time) {
|
|||
|
this._map = map;
|
|||
|
this._time = time;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onEventAdded(RoadMap map, List<Event> events, Event e, int time) {
|
|||
|
this._map = map;
|
|||
|
this._time = time;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onReset(RoadMap map, List<Event> events, int time) {
|
|||
|
this._map = map;
|
|||
|
this._time = time;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onRegister(RoadMap map, List<Event> events, int time) {
|
|||
|
this._map = map;
|
|||
|
this._time = time;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onError(String err) {
|
|||
|
System.err.println(err);
|
|||
|
JOptionPane.showMessageDialog(new JFrame(), err);
|
|||
|
}
|
|||
|
|
|||
|
}
|