/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package atmsdriver.trafficeventseditor;

import atmsdriver.model.Highway;
import atmsdriver.model.LoopDetector;
import atmsdriver.model.LoopDetector.DOTCOLOR;
import atmsdriver.model.Station;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Observable;
import java.util.Observer;
import javax.swing.AbstractButton;
import javax.swing.AbstractListModel;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;

/**
 *
 * @author jtorres
 */
public class TrafficEventsEditor extends javax.swing.JFrame implements Observer
{
    
    TimeFrames timeFrames;
    
    /**
     * Creates new form BatchBuilderGUI
     */
    public TrafficEventsEditor(TimeFrames timeFrames)
    {
        initComponents();
        this.timeFrames = timeFrames;
        
        HighwayList.setModel(new HighwaysListModel());
        HighwayList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        HighwayList.addListSelectionListener(new HighwaysListSelectionListener());
        
        StationTable.setModel(new StationTableModel());
        StationTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        StationTable.getSelectionModel().addListSelectionListener(
                new StationTableListSelectionListener());
        
        TimeFrameList.setModel(new TimeFrameListModel());
        TimeFrameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        TimeFrameList.addListSelectionListener(new TimeFrameListSelectionListener());
        
        LoopDetectorTable.setModel(new LoopDetectorTableModel());
        LoopDetectorTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        LoopDetectorTable.getSelectionModel().addListSelectionListener(
                new LoopDetectorTableListSelectionListener());
        
        TrafficLaneEventsTable.setModel(new TrafficLaneEventsTableModel());
        TrafficLaneEventsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        TrafficLaneEventsTable.getSelectionModel().addListSelectionListener(
                new TrafficLaneEventsTableSelectionListener());
        
        GreenButton.setSelected(true);
    }
    
    private class TrafficLaneEventsTableModel extends AbstractTableModel
    {
        String[] columnNames = {"Route", "StationID", "Postmile", "LoopID", "LoopType", 
            "LoopDesc", "Color"};
        int rows;
        int cols;
        String[][] data;
        TimeFrame currFrame;
        public TrafficLaneEventsTableModel()
        {            
            currFrame = timeFrames.currentTimeFrame;
            rows = currFrame != null ? currFrame.events.size() : 0;
            cols = columnNames.length;
            data = new String[rows][cols];
            for(int i = 0; i < rows; i++)
            {
                TrafficLaneEvent currEvent = currFrame.events.get(i);
                data[i][0] = Integer.toString(currEvent.routeNum);
                data[i][1] = Integer.toString(currEvent.station.ldsID);
                data[i][2] = Double.toString(currEvent.station.postmile);
                data[i][3] = Integer.toString(currEvent.loopDetector.loopID);
                data[i][4] = currEvent.loopDetector.loopLocationID;
                data[i][5] = currEvent.loopDetector.loopLocation;
                data[i][6] = currEvent.color.getLetter();
            }
        }
        
        @Override
        public String getColumnName(int col)
        {
            return columnNames[col];
        }
        
        @Override
        public int getRowCount()
        {
            return rows;
        }

        @Override
        public int getColumnCount()
        {
            return cols;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex)
        {
            return data[rowIndex][columnIndex];
        }
        
    }
    
    private class LoopDetectorTableModel extends AbstractTableModel
    {
        String[] columnnames = {"Loop_ID", "Loop_Type", "Loop_Desc"};
        int rows;
        int cols;
        String[][] data;
        Station currStn;
        
        public LoopDetectorTableModel()
        {
            currStn = timeFrames.currentStation;
            rows = currStn != null ? currStn.loops.size() : 0;
            cols = columnnames.length;
            data = new String[rows][cols];
            for(int i = 0; i < rows; i++)
            {
                data[i][0] = Integer.toString(currStn.loops.get(i).loopID);
                data[i][1] = currStn.loops.get(i).loopLocationID;
                data[i][2] = currStn.loops.get(i).loopLocation;
            }
        }
        
        @Override
        public String getColumnName(int col)
        {
            return columnnames[col];
        }
        
        @Override
        public int getRowCount()
        {
            return rows;
        }

        @Override
        public int getColumnCount()
        {
            return cols;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex)
        {
            return data[rowIndex][columnIndex];
        }
        
    }
    
    private class TimeFrameListModel extends AbstractListModel
    {
        ArrayList<TimeFrame> frames;
        
        public TimeFrameListModel()
        {
            frames = (ArrayList<TimeFrame>) timeFrames.frames;
        }

        @Override
        public int getSize()
        {
            return frames.size();
        }

        @Override
        public Object getElementAt(int index)
        {
            return frames.get(index);
        }
        
    }

    private class TrafficLaneEventsTableSelectionListener implements ListSelectionListener
    {
        @Override
        public void valueChanged(ListSelectionEvent e)
        {
            if(e.getValueIsAdjusting())
                return;
            DefaultListSelectionModel mod = (DefaultListSelectionModel) e.getSource();
            int index = mod.getMaxSelectionIndex();
            if(index >= 0)
                timeFrames.setCurrentTrafficLaneEvent(index);
        }
    }
    
    private class HighwaysListSelectionListener implements ListSelectionListener
    {
        @Override
        public void valueChanged(ListSelectionEvent e)
        {
            if(e.getValueIsAdjusting())
                return;
            JList source = (JList) e.getSource();
            timeFrames.setCurrentHighway(source.getSelectedIndex());
        }
    }
    
    private class TimeFrameListSelectionListener implements ListSelectionListener
    {
        @Override
        public void valueChanged(ListSelectionEvent e)
        {
            if(e.getValueIsAdjusting())
                return;
            JList source = (JList) e.getSource();
            int index = source.getSelectedIndex();
            if(index >= 0)
            {
                timeFrames.setCurrentTimeFrame(index);
            }
        }
    }
    
    private class StationTableListSelectionListener implements ListSelectionListener
    {

        @Override
        public void valueChanged(ListSelectionEvent e)
        {
            if(e.getValueIsAdjusting())
                return;
            DefaultListSelectionModel mod = (DefaultListSelectionModel) e.getSource();
            int index = mod.getMaxSelectionIndex();
            if(index >= 0)
                timeFrames.setCurrentStation(index);
        }
    }
    
    private class LoopDetectorTableListSelectionListener implements ListSelectionListener
    {

        @Override
        public void valueChanged(ListSelectionEvent e)
        {
            if(e.getValueIsAdjusting())
                return;
            DefaultListSelectionModel mod = (DefaultListSelectionModel) e.getSource();
            int index = mod.getMaxSelectionIndex();
            if(index >= 0)
                timeFrames.setCurrentLoopDetector(index);
        }
        
    }
    
    private class StationTableModel extends AbstractTableModel
    {
        String[] columnNames = {"lds_id", "direction", "postmile", "location"};
        String[][] data;
        Highway hwy;
        int rows;
        int cols;
        
        public StationTableModel()
        {
            hwy = TrafficEventsEditor.this.timeFrames.currentHighway;
            cols = columnNames.length;
            rows = hwy != null ? hwy.stations.size() : 0;
            data = new String[rows][cols];
            for(int i = 0; i < rows; i++)
            {
                data[i][0] = Integer.toString(hwy.stations.get(i).ldsID);
                data[i][1] = hwy.stations.get(i).direction.getLetter();
                data[i][2] = Double.toString(hwy.stations.get(i).postmile);
                data[i][3] = hwy.stations.get(i).location;
            }
        }
        
        @Override
        public String getColumnName(int col)
        {
            return columnNames[col];
        }

        @Override
        public int getRowCount()
        {
            return rows;
        }

        @Override
        public int getColumnCount()
        {
            return cols;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex)
        {
            return data[rowIndex][columnIndex];
        }
    }
    
    private class HighwaysListModel extends AbstractListModel
    {
        
        @Override
        public int getSize()
        {
            return TrafficEventsEditor.this.timeFrames.highways.highways.size();
        }

        @Override
        public Object getElementAt(int index)
        {
            return TrafficEventsEditor.this.timeFrames.highways.highways.get(index);
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents()
    {

        colorRadioButtons = new javax.swing.ButtonGroup();
        jPanel6 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        HighwayScrollPane = new javax.swing.JScrollPane();
        HighwayList = new javax.swing.JList();
        jPanel4 = new javax.swing.JPanel();
        StationScrollPane = new javax.swing.JScrollPane();
        StationTable = new javax.swing.JTable();
        jPanel5 = new javax.swing.JPanel();
        LoopDetectorScrollPane = new javax.swing.JScrollPane();
        LoopDetectorTable = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jPanel9 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        CurrentTimeFrameLabel = new javax.swing.JLabel();
        CurrentHighwayLabel = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        CurrentStationLabel = new javax.swing.JLabel();
        CurrentStationPostmileLabel = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        CurrentStationLocationLabel = new javax.swing.JLabel();
        CurrentLoopDetectorLabel = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        CurrentLoopDetectorTypeLabel = new javax.swing.JLabel();
        CurrentLoopDetectorDescLabel = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        CurrentStationDirectionLabel = new javax.swing.JLabel();
        jPanel7 = new javax.swing.JPanel();
        GreenButton = new javax.swing.JRadioButton();
        YellowButton = new javax.swing.JRadioButton();
        RedButton = new javax.swing.JRadioButton();
        AddNewEventButton = new javax.swing.JButton();
        DeleteEventButton = new javax.swing.JButton();
        jPanel11 = new javax.swing.JPanel();
        jPanel12 = new javax.swing.JPanel();
        SinglePreviewStationButton = new javax.swing.JButton();
        SinglePreviewHighwaysButton = new javax.swing.JButton();
        jPanel13 = new javax.swing.JPanel();
        CumulativePreviewStationButton = new javax.swing.JButton();
        CumulativePreviewHighwaysButton = new javax.swing.JButton();
        jPanel15 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        TimeFrameScrollPane = new javax.swing.JScrollPane();
        TimeFrameList = new javax.swing.JList();
        jPanel10 = new javax.swing.JPanel();
        AddNewTimeFrameButton = new javax.swing.JButton();
        DeleteTimeFrameButton = new javax.swing.JButton();
        jPanel8 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        TrafficLaneEventsTable = new javax.swing.JTable();
        jPanel14 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Traffic Events Editor");

        jPanel6.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Lane Selection Panel"));

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1), "Highway"));

        HighwayList.setModel(new javax.swing.AbstractListModel()
        {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        HighwayScrollPane.setViewportView(HighwayList);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(HighwayScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(HighwayScrollPane)
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1), "Station"));

        StationTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][]
            {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String []
            {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        StationScrollPane.setViewportView(StationTable);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(StationScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 546, Short.MAX_VALUE)
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(StationScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        );

        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1), "Loop Detector"));

        LoopDetectorTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][]
            {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String []
            {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        LoopDetectorScrollPane.setViewportView(LoopDetectorTable);

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LoopDetectorScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 479, Short.MAX_VALUE)
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LoopDetectorScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addGap(6, 6, 6)
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Current Selection"));
        jPanel1.setLayout(new java.awt.GridLayout(1, 0));

        jLabel1.setText("TimeFrame:");

        CurrentTimeFrameLabel.setText("null");

        CurrentHighwayLabel.setText("null");

        jLabel2.setText("Highway:");

        jLabel3.setText("Station:");

        CurrentStationLabel.setText("null");

        CurrentStationPostmileLabel.setText("null");

        jLabel4.setText("Postmile:");

        jLabel5.setText("Location:");

        CurrentStationLocationLabel.setText("null");

        CurrentLoopDetectorLabel.setText("null");

        jLabel6.setText("Loop:");

        jLabel7.setText("Type:");

        CurrentLoopDetectorTypeLabel.setText("null");

        CurrentLoopDetectorDescLabel.setText("null");

        jLabel8.setText("Desc:");

        jLabel9.setText("Direction:");

        CurrentStationDirectionLabel.setText("null");

        javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9);
        jPanel9.setLayout(jPanel9Layout);
        jPanel9Layout.setHorizontalGroup(
            jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel9Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel3)
                    .addComponent(jLabel6)
                    .addGroup(jPanel9Layout.createSequentialGroup()
                        .addGap(6, 6, 6)
                        .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel9)
                            .addComponent(jLabel5)
                            .addComponent(jLabel4)
                            .addComponent(jLabel7)
                            .addComponent(jLabel8))))
                .addGap(18, 18, 18)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(CurrentLoopDetectorTypeLabel)
                    .addComponent(CurrentLoopDetectorLabel)
                    .addComponent(CurrentStationLocationLabel)
                    .addComponent(CurrentStationDirectionLabel)
                    .addComponent(CurrentStationLabel)
                    .addComponent(CurrentHighwayLabel)
                    .addComponent(CurrentTimeFrameLabel)
                    .addComponent(CurrentStationPostmileLabel)
                    .addComponent(CurrentLoopDetectorDescLabel))
                .addContainerGap(239, Short.MAX_VALUE))
        );
        jPanel9Layout.setVerticalGroup(
            jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel9Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(CurrentTimeFrameLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(CurrentHighwayLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(CurrentStationLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel9)
                    .addComponent(CurrentStationDirectionLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(CurrentStationPostmileLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(CurrentStationLocationLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(CurrentLoopDetectorLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(CurrentLoopDetectorTypeLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel8)
                    .addComponent(CurrentLoopDetectorDescLabel))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1.add(jPanel9);

        jPanel7.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));

        colorRadioButtons.add(GreenButton);
        GreenButton.setText("Green");

        colorRadioButtons.add(YellowButton);
        YellowButton.setText("Yellow");

        colorRadioButtons.add(RedButton);
        RedButton.setText("Red");

        AddNewEventButton.setText("Add New Event");
        AddNewEventButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                AddLaneEventButtonActionPerformed(evt);
            }
        });

        DeleteEventButton.setText("Delete Selected Event");
        DeleteEventButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                DeleteEventButtonActonPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(DeleteEventButton, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(RedButton)
                            .addComponent(YellowButton)
                            .addComponent(GreenButton))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(AddNewEventButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(GreenButton)
                .addGap(12, 12, 12)
                .addComponent(YellowButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(RedButton)
                .addGap(18, 18, 18)
                .addComponent(AddNewEventButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(DeleteEventButton)
                .addContainerGap(25, Short.MAX_VALUE))
        );

        jPanel1.add(jPanel7);

        jPanel11.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Preview Lane Events on ATMS"));
        jPanel11.setLayout(new java.awt.BorderLayout());

        jPanel12.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED), "Selected Time Frame Preview"));

        SinglePreviewStationButton.setText("Send Selected Station Events");
        SinglePreviewStationButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                SinglePreviewStationButtonActionPerformed(evt);
            }
        });

        SinglePreviewHighwaysButton.setText("Send All Events");
        SinglePreviewHighwaysButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                SinglePreviewHighwaysButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel12Layout = new javax.swing.GroupLayout(jPanel12);
        jPanel12.setLayout(jPanel12Layout);
        jPanel12Layout.setHorizontalGroup(
            jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel12Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(SinglePreviewHighwaysButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(SinglePreviewStationButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(10, Short.MAX_VALUE))
        );
        jPanel12Layout.setVerticalGroup(
            jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel12Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(SinglePreviewStationButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(SinglePreviewHighwaysButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel11.add(jPanel12, java.awt.BorderLayout.CENTER);

        jPanel13.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED), "Cumulative Preview"));

        CumulativePreviewStationButton.setText("Send Selected Station Events");
        CumulativePreviewStationButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                CumulativeStationPreviewButtonActionPerformed(evt);
            }
        });

        CumulativePreviewHighwaysButton.setText("Send All Events");
        CumulativePreviewHighwaysButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                CumulativeHighwaysPreviewButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel13Layout = new javax.swing.GroupLayout(jPanel13);
        jPanel13.setLayout(jPanel13Layout);
        jPanel13Layout.setHorizontalGroup(
            jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel13Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(CumulativePreviewHighwaysButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(CumulativePreviewStationButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel13Layout.setVerticalGroup(
            jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel13Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(CumulativePreviewStationButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(CumulativePreviewHighwaysButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel11.add(jPanel13, java.awt.BorderLayout.PAGE_START);

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Time Frame"));

        TimeFrameList.setModel(new javax.swing.AbstractListModel()
        {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        TimeFrameScrollPane.setViewportView(TimeFrameList);

        jPanel10.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        AddNewTimeFrameButton.setText("New");
        AddNewTimeFrameButton.setActionCommand("addTimeFrame");
        AddNewTimeFrameButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                addNewTimeFrameButtonClicked(evt);
            }
        });

        DeleteTimeFrameButton.setText("Delete");
        DeleteTimeFrameButton.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                DeleteTimeFrameButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10);
        jPanel10.setLayout(jPanel10Layout);
        jPanel10Layout.setHorizontalGroup(
            jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel10Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(AddNewTimeFrameButton, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 40, Short.MAX_VALUE)
                .addComponent(DeleteTimeFrameButton, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanel10Layout.setVerticalGroup(
            jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel10Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(AddNewTimeFrameButton)
                    .addComponent(DeleteTimeFrameButton))
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(TimeFrameScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jPanel10, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(TimeFrameScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel10, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGap(76, 76, 76))
        );

        jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Traffic Lane Events"));

        TrafficLaneEventsTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][]
            {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String []
            {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jScrollPane1.setViewportView(TrafficLaneEventsTable);

        javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
        jPanel8.setLayout(jPanel8Layout);
        jPanel8Layout.setHorizontalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING)
        );
        jPanel8Layout.setVerticalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel15Layout = new javax.swing.GroupLayout(jPanel15);
        jPanel15.setLayout(jPanel15Layout);
        jPanel15Layout.setHorizontalGroup(
            jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel15Layout.createSequentialGroup()
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel15Layout.setVerticalGroup(
            jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel15Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel14.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)), "Export/Import Scripts"));

        jButton1.setText("Load Script");

        btnSave.setText("Save Script");
        btnSave.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                btnSaveActionPerformed(evt);
            }
        });

        jButton3.setText("Save Script As");

        javax.swing.GroupLayout jPanel14Layout = new javax.swing.GroupLayout(jPanel14);
        jPanel14.setLayout(jPanel14Layout);
        jPanel14Layout.setHorizontalGroup(
            jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel14Layout.createSequentialGroup()
                .addContainerGap(28, Short.MAX_VALUE)
                .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(btnSave, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButton3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(27, 27, 27))
        );
        jPanel14Layout.setVerticalGroup(
            jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel14Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btnSave)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton3)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel15, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 730, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addComponent(jPanel11, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addComponent(jPanel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jPanel11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(jPanel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel15, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void AddLaneEventButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_AddLaneEventButtonActionPerformed
    {//GEN-HEADEREND:event_AddLaneEventButtonActionPerformed
        int rows[] = LoopDetectorTable.getSelectedRows();
        timeFrames.addEventsToTimeFrame(rows, getDotColorFromText(
                getSelectedButtonText(colorRadioButtons)));
    }//GEN-LAST:event_AddLaneEventButtonActionPerformed

    private void DeleteTimeFrameButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_DeleteTimeFrameButtonActionPerformed
    {//GEN-HEADEREND:event_DeleteTimeFrameButtonActionPerformed
        timeFrames.deleteTimeFrame(TimeFrameList.getSelectedIndex());
    }//GEN-LAST:event_DeleteTimeFrameButtonActionPerformed

    private String[] getTimeChoices()
    {
        String[] choices = new String[60];
        for(int i = 0; i < 60; i++)
        {
            choices[i] = String.format("%02d", i);
        }
        return choices;
    }
    
    private void addNewTimeFrameButtonClicked(java.awt.event.ActionEvent evt)//GEN-FIRST:event_addNewTimeFrameButtonClicked
    {//GEN-HEADEREND:event_addNewTimeFrameButtonClicked
        // String name = JOptionPane.showInputDialog(this, "Enter a time frame (HH:MM:SS)");
        String[] hourChoices = getTimeChoices();
        String[] minChoices = getTimeChoices();
        String[] secChoices = {"00", "30"};
        
        JComboBox hourCombo = new JComboBox(hourChoices);
        JComboBox minCombo = new JComboBox(minChoices);
        JComboBox secCombo = new JComboBox(secChoices);
        
        Object[] message = {
            "Hour:", hourCombo,
            "Minute:", minCombo,
            "Second:", secCombo
        };
        int option = JOptionPane.showConfirmDialog(this, message, "Enter a time frame:", JOptionPane.OK_CANCEL_OPTION);
        if(option == JOptionPane.OK_OPTION)
        {
            String h = hourCombo.getSelectedItem().toString();
            String m = minCombo.getSelectedItem().toString();
            String s = secCombo.getSelectedItem().toString();
            String cum = h + ":" + m + ":" + s;
            timeFrames.addTimeFrame(cum);
        }
        /*if(name != null)
        {
            timeFrames.addTimeFrame(name);
        }*/
    }//GEN-LAST:event_addNewTimeFrameButtonClicked

    private void DeleteEventButtonActonPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_DeleteEventButtonActonPerformed
    {//GEN-HEADEREND:event_DeleteEventButtonActonPerformed
        timeFrames.deleteTrafficLaneEvent(TrafficLaneEventsTable
                .getSelectionModel().getMaxSelectionIndex());
    }//GEN-LAST:event_DeleteEventButtonActonPerformed

    private void SinglePreviewStationButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_SinglePreviewStationButtonActionPerformed
    {//GEN-HEADEREND:event_SinglePreviewStationButtonActionPerformed
        timeFrames.singlePreviewStation();
    }//GEN-LAST:event_SinglePreviewStationButtonActionPerformed

    private void SinglePreviewHighwaysButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_SinglePreviewHighwaysButtonActionPerformed
    {//GEN-HEADEREND:event_SinglePreviewHighwaysButtonActionPerformed
        timeFrames.singlePreviewHighways();
    }//GEN-LAST:event_SinglePreviewHighwaysButtonActionPerformed

    private void CumulativeStationPreviewButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_CumulativeStationPreviewButtonActionPerformed
    {//GEN-HEADEREND:event_CumulativeStationPreviewButtonActionPerformed
        timeFrames.cumulativePreviewStation();
    }//GEN-LAST:event_CumulativeStationPreviewButtonActionPerformed

    private void CumulativeHighwaysPreviewButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_CumulativeHighwaysPreviewButtonActionPerformed
    {//GEN-HEADEREND:event_CumulativeHighwaysPreviewButtonActionPerformed
        timeFrames.cumulativePreviewHighways();
    }//GEN-LAST:event_CumulativeHighwaysPreviewButtonActionPerformed

     /**
     * Shows the dialog for choosing a file to save the script data to.
     * @author jdalbey
     */
    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnSaveActionPerformed
    {//GEN-HEADEREND:event_btnSaveActionPerformed
        boolean saved = false;
        JFileChooser chooser = new JFileChooser(".");
        int choice = chooser.showSaveDialog(chooser);
        if (choice == JFileChooser.APPROVE_OPTION)
        {
            File selectedFile = chooser.getSelectedFile();
            //TODO: Save the script to the selected file
            JOptionPane.showMessageDialog(null, "Saving Not Implemented Yet");
        }
//        return choice == JFileChooser.APPROVE_OPTION && saved;
    }//GEN-LAST:event_btnSaveActionPerformed

    private DOTCOLOR getDotColorFromText(String text)
    {
        return DOTCOLOR.toDotColor(text);
    }
    
    private String getSelectedButtonText(ButtonGroup buttonGroup)
    {
        for(Enumeration<AbstractButton> buttons = buttonGroup.getElements(); buttons.hasMoreElements();)
        {
            AbstractButton button = buttons.nextElement();
            if(button.isSelected())
            {
                return button.getText();
            }
        }
        return null;
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try
        {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
            {
                if ("Nimbus".equals(info.getName()))
                {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex)
        {
            java.util.logging.Logger.getLogger(TrafficEventsEditor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex)
        {
            java.util.logging.Logger.getLogger(TrafficEventsEditor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex)
        {
            java.util.logging.Logger.getLogger(TrafficEventsEditor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex)
        {
            java.util.logging.Logger.getLogger(TrafficEventsEditor.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>
        
        TimeFrames timeFrames = new TimeFrames();
        final TrafficEventsEditor gui = new TrafficEventsEditor(timeFrames);
        timeFrames.addObserver(gui);
        
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                gui.update(null, null);
                gui.setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton AddNewEventButton;
    private javax.swing.JButton AddNewTimeFrameButton;
    private javax.swing.JButton CumulativePreviewHighwaysButton;
    private javax.swing.JButton CumulativePreviewStationButton;
    private javax.swing.JLabel CurrentHighwayLabel;
    private javax.swing.JLabel CurrentLoopDetectorDescLabel;
    private javax.swing.JLabel CurrentLoopDetectorLabel;
    private javax.swing.JLabel CurrentLoopDetectorTypeLabel;
    private javax.swing.JLabel CurrentStationDirectionLabel;
    private javax.swing.JLabel CurrentStationLabel;
    private javax.swing.JLabel CurrentStationLocationLabel;
    private javax.swing.JLabel CurrentStationPostmileLabel;
    private javax.swing.JLabel CurrentTimeFrameLabel;
    private javax.swing.JButton DeleteEventButton;
    private javax.swing.JButton DeleteTimeFrameButton;
    private javax.swing.JRadioButton GreenButton;
    private javax.swing.JList HighwayList;
    private javax.swing.JScrollPane HighwayScrollPane;
    private javax.swing.JScrollPane LoopDetectorScrollPane;
    private javax.swing.JTable LoopDetectorTable;
    private javax.swing.JRadioButton RedButton;
    private javax.swing.JButton SinglePreviewHighwaysButton;
    private javax.swing.JButton SinglePreviewStationButton;
    private javax.swing.JScrollPane StationScrollPane;
    private javax.swing.JTable StationTable;
    private javax.swing.JList TimeFrameList;
    private javax.swing.JScrollPane TimeFrameScrollPane;
    private javax.swing.JTable TrafficLaneEventsTable;
    private javax.swing.JRadioButton YellowButton;
    private javax.swing.JButton btnSave;
    private javax.swing.ButtonGroup colorRadioButtons;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel12;
    private javax.swing.JPanel jPanel13;
    private javax.swing.JPanel jPanel14;
    private javax.swing.JPanel jPanel15;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables
    
    private void updateStatusLabels()
    {
        CurrentTimeFrameLabel.setText(timeFrames.currentTimeFrame != null
                ? timeFrames.currentTimeFrame.toString()
                : "");
        
        CurrentStationLabel.setText(timeFrames.currentStation != null
                ? timeFrames.currentStation.toString()
                : "");
        
        CurrentHighwayLabel.setText(timeFrames.currentHighway != null
                ? timeFrames.currentHighway.toString()
                : "");
        CurrentStationPostmileLabel.setText(timeFrames.currentStation != null
                ? Double.toString(timeFrames.currentStation.postmile)
                : "");
        CurrentStationDirectionLabel.setText(timeFrames.currentStation != null
                ? timeFrames.currentStation.direction.getLetter()
                : "");
        CurrentStationLocationLabel.setText(timeFrames.currentStation != null
                ? timeFrames.currentStation.location
                : "");
        
        CurrentLoopDetectorLabel.setText(timeFrames.currentLoopDetector != null
                ? Integer.toString(timeFrames.currentLoopDetector.loopID)
                : "");
        CurrentLoopDetectorTypeLabel.setText(timeFrames.currentLoopDetector != null
                ? timeFrames.currentLoopDetector.loopLocationID
                : "");
        CurrentLoopDetectorDescLabel.setText(timeFrames.currentLoopDetector != null
                ? timeFrames.currentLoopDetector.loopLocation
                : "");
    }
    
    private void updateButtonEnabled()
    {
        // add event button
        this.AddNewEventButton.setEnabled(
                timeFrames.currentTimeFrame != null 
                && timeFrames.currentHighway != null
                && timeFrames.currentStation != null 
                && timeFrames.currentLoopDetector != null
        );
        
        // delete event button
        DeleteEventButton.setEnabled(
                !TrafficLaneEventsTable.getSelectionModel().isSelectionEmpty());
        
        // delete time frame button
        DeleteTimeFrameButton.setEnabled(!TimeFrameList.isSelectionEmpty());
        
        // single preview buttons
        SinglePreviewStationButton.setEnabled(
                timeFrames.currentStation != null
                && timeFrames.currentTimeFrame != null
        );
        
        SinglePreviewHighwaysButton.setEnabled(
                timeFrames.currentTimeFrame != null
        );
        
        // cumulative preview buttons
        CumulativePreviewHighwaysButton.setEnabled(
                timeFrames.currentTimeFrame != null
        );
        
        CumulativePreviewStationButton.setEnabled(
                timeFrames.currentTimeFrame != null
                && timeFrames.currentStation != null
        );
    }
    
    @Override
    public void update(Observable o, Object arg)
    {
        String updateArg = (String) arg;
        updateStatusLabels();
        if(updateArg != null)
        {
            if(updateArg.equals("add frame") || updateArg.equals("delete frame"))
            {
                TimeFrameList.setModel(new TimeFrameListModel());
                TimeFrameList.setSelectedIndex(
                        timeFrames.getCurrentTimeFrameIndex());
                TrafficLaneEventsTable.setModel(new TrafficLaneEventsTableModel());
            }
            else if(updateArg.equals("select hwy"))
            {
                StationTable.setModel(new StationTableModel());
                LoopDetectorTable.setModel(new LoopDetectorTableModel());
            }
            else if(updateArg.equals("select station"))
            {
                LoopDetectorTable.setModel(new LoopDetectorTableModel());
            }
            else if(updateArg.equals("select frame"))
            {
                TrafficLaneEventsTable.setModel(
                        new TrafficLaneEventsTableModel());
            }
            else if(updateArg.equals("add event") 
                    || updateArg.equals("delete event"))
            {
                TrafficLaneEventsTable.setModel(
                        new TrafficLaneEventsTableModel());
                TrafficLaneEventsTable.getSelectionModel()
                        .setSelectionInterval(
                                timeFrames.getCurrentTrafficEventIndex(), 
                                timeFrames.getCurrentTrafficEventIndex());
            }
        }
        updateButtonEnabled();
    }
}