// Carnegie Mellon University
//   Information Networking Institute and
//   School of Computer Science
//
// Master Thesis: A Monitoring Tool for Overlay Network
// By: TungFai Chan and Annie Cheng
//
// File: MainScreen.java
// Path: userInterfaces/
// Description: Main Frame for the application


package userInterfaces;

import eventbase.*;
import eventbase.event.*;
import network.*;
import parser.*;
import timesyn.*;
import userInterfaces.componentManagers.*;
import userInterfaces.graph.*;
import userInterfaces.images.*;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;


public class MainScreen extends JFrame {

    final boolean PRINT_EXCEPTION_AS_DIALOG = true;
    final boolean PRINT_CONSOLE_MESSAGE = true;
    final int BORDER_DIFF = 10;
    final int LEFT_PANE = 0;
    final int RIGHT_PANE = 1;
    final int BOTH_PANES = 2;
    final int SLIDER_MOVEMENT_DELAY = 10; // Interval for slider to update the time
    final int SLIDER_MOVEMENT_STEP = 1000;
    final double TIME_DIFF = 2208988800.0;
    final String DATE_FORMAT = "yyyy.MM.dd";
    final String TIME_FORMAT = "HH:mm:ss.SSS";
    final int DEFAULT_SLIDER_RANGE = 60; // in secs


    final static int LOGFILE_MODE = 0;
    final static int NETWORK_MODE = 1;

    // UI Parameters
    final int preset_ContentSplitPane_location = 200;
    final int preset_LeftSplitPane_location = 300;
    final int preset_RightSplitPane_location = 400;

    int realTimeDelay = SLIDER_MOVEMENT_DELAY;

    int numViewablePaneLeft = 2;
    int numViewablePaneRight = 2;

    boolean menuDrivenEvent = false;
    boolean eventPlayMode = false;
    boolean compactControlPanelMode = false;
    boolean userSliderMode = false;

    // yhchu: add coarser timescale, 10x 20x 50x 100x, ... (one unit is 1 msec)
    // in the future, we could dynamically adjust the time scale for
    // different CPU speed
    final String[] timeScaleOptions = {"1x", "1/10x", "1/4x", "1/2x", "2x", "4x", "10x", "20x", "50x", "100x", "200x", "500x", "1000x", "2000x", "5000x", "10000x"};
    final String[] sliderOptions = {"Time Based", "Event Based"};

    int dragNodeID = -1;

    double baseTime = -1.0;
    double currentTime;
    int currentNumEvent;

    boolean timeBased = true;

    int mode;

    int savedSliderPosition;

    // Defined Components
    FilesParser filesParser = null;


    // UI Components
    JPanel contentPane;
    BorderLayout contentBorderLayout = new BorderLayout();

    JMenuBar menuBar = new JMenuBar();

    JMenu menuFile = new JMenu();
    JMenuItem menuFileOpenLog = new JMenuItem();
    JMenuItem menuFileNetworkInit = new JMenuItem();
    JMenuItem menuFileSaveEventText = new JMenuItem();
    JMenuItem menuFileNetworkInfo = new JMenuItem();
    JMenuItem menuFileExit = new JMenuItem();

    JMenu menuView = new JMenu();
    JCheckBoxMenuItem menuViewNodeTree = new JCheckBoxMenuItem();
    JCheckBoxMenuItem menuViewNodeInfoTables = new JCheckBoxMenuItem();
    JCheckBoxMenuItem menuViewGraph = new JCheckBoxMenuItem();
    JCheckBoxMenuItem menuViewMsg = new JCheckBoxMenuItem();
    JMenuItem menuViewControlPanel = new JMenuItem();
    JMenu menuViewPreset = new JMenu();
    JMenuItem menuViewPresetNormal = new JMenuItem();
    JMenuItem menuViewPresetCompact = new JMenuItem();
    JMenuItem menuViewPresetDetail = new JMenuItem();
    JMenuItem menuViewPlayPause = new JMenuItem();
    JMenuItem menuViewStop = new JMenuItem();
    JMenuItem menuViewRelocate = new JMenuItem();
    JMenu menuViewTimeScale = new JMenu();
    JMenu menuViewSlider = new JMenu();

    JMenu menuHelp = new JMenu();
    JMenuItem menuHelpAbout = new JMenuItem();

    JToolBar mainToolBar = new JToolBar();
    JButton openButton = new JButton();
    JButton networkButton = new JButton();
    JButton closeButton = new JButton();
    JButton helpButton = new JButton();
    JButton relocateButton = new JButton();
    JButton play_pauseToolbarButton = new JButton();
    JButton stopToolbarButton = new JButton();
    JButton stepBackToolbarButton = new JButton();
    JButton stepForwardToolbarButton = new JButton();
    JButton timeToolbarButton = new JButton();


    JPanel statusBar = new JPanel();
    JLabel statusBarLabel = new JLabel();
    BorderLayout statusBarBorderLayout = new BorderLayout();
    JProgressBar progressBar = new JProgressBar();

    JSplitPane contentSplitPane = new JSplitPane();
    JSplitPane leftSplitPane = new JSplitPane();
    JSplitPane rightSplitPane = new JSplitPane();
    JScrollPane treeScrollPane = new JScrollPane();
    JScrollPane textScrollPane = new JScrollPane();
    JPanel nodeInfoPanel = new JPanel();
    JPanel eventPanel = new JPanel();
    JPanel sliderControlPanel = new JPanel();
    JTabbedPane tabbedPane = new JTabbedPane();

    JList nodesList = new JList();
    JTextPane infoTextPane = new JTextPane();
    BorderLayout nodeInfoPanelBorderLayout = new BorderLayout();
    BorderLayout eventPanelBorderLayout = new BorderLayout();
    JComboBox tableSelectionComboBox = new JComboBox();
    JTextArea selectedElementLabel = new JTextArea();
    JScrollPane tableScrollPane = new JScrollPane();
    JTable infoTable = new JTable();

    FlowLayout sliderControlPanelFlowLayout = new FlowLayout();
    JComboBox timeScaleComboBox = new JComboBox();
    JTextField timeTextField = new JTextField();
    JSlider timeSlider = new JSlider();

    JButton play_pauseButton = new JButton();
    JButton stopButton = new JButton();
    JButton stepBackButton = new JButton();
    JButton stepForwardButton = new JButton();

    NodeGraphPanel neighborNodeGraphPanel = new NodeGraphPanel(NodeGraphPanel.NEIGHBOR_TYPE);
    NodeGraphPanel routingNodeGraphPanel = new NodeGraphPanel(NodeGraphPanel.ROUTING_TYPE);


    // Network Information Dialog Box
    NetworkStatDataModel netDataModel = null;

    // Timer Control
    SliderMovementTimerListener sliderListener =
                   new SliderMovementTimerListener(this);
    javax.swing.Timer sliderMoveTimer = 
		   new javax.swing.Timer(SLIDER_MOVEMENT_DELAY, sliderListener);


    // Button Group for Time Scales and Slider
    ButtonGroup timeScaleGroup = new ButtonGroup();
    ButtonGroup sliderGroup = new ButtonGroup();


    // Event Database
    EventBaseAgent dbAgent = new EventBaseAgent();
    EventTableEntry tableEntry = null;


    // Network Manager
    NetworkManager networkManager = null;

    // Component Mangements
    GraphManager graphManager = new GraphManager(neighborNodeGraphPanel, this, dbAgent);
    ListControlManager listManager = new ListControlManager(nodesList, this);
    InfoTextManager infoManager = new InfoTextManager(infoTextPane, this);
    TableManager tableManager = new TableManager(infoTable, tableSelectionComboBox,
                                                 dbAgent, this);


    //Construct the frame
    public MainScreen() {
	enableEvents(AWTEvent.WINDOW_EVENT_MASK);

	try {
	    jbInit();
	}
	catch(Exception e) {
	    e.printStackTrace();
	}
    }


    /////////////////////////////////////////////////////////
    // Components initialization
    /////////////////////////////////////////////////////////

    private void jbInit() throws Exception  {

 	// MenuBar Configurations -----------------------------
	// Menu - File
	menuFile.setFont(new java.awt.Font("SansSerif", 0, 12));
	menuFile.setText("File");
        menuFile.setMnemonic(KeyEvent.VK_F);

	menuFileOpenLog.setText("Open Log Files...");
	menuFileOpenLog.setFont(new java.awt.Font("SansSerif", 0, 12));
	menuFileOpenLog.setIcon(ImagesList.openImage);
        menuFileOpenLog.setMnemonic(KeyEvent.VK_O);
        menuFileOpenLog.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
                                                              Event.CTRL_MASK));
	menuFileOpenLog.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    fileOpenLog_actionPerformed(e);
		}
	    });

        menuFileNetworkInit.setText("Initialize Network...");
        menuFileNetworkInit.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuFileNetworkInit.setIcon(ImagesList.networkImage);
        menuFileNetworkInit.setMnemonic(KeyEvent.VK_N);
        menuFileNetworkInit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                                                                  Event.CTRL_MASK));
        menuFileNetworkInit.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    fileNetwork_actionPerformed(e);
                }
            });

        menuFileSaveEventText.setText("Save Event Text As...");
        menuFileSaveEventText.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuFileSaveEventText.setIcon(ImagesList.emptyImage);
        menuFileSaveEventText.setMnemonic(KeyEvent.VK_S);
        menuFileSaveEventText.setEnabled(false);
        menuFileSaveEventText.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
                                                                  Event.CTRL_MASK));
        menuFileSaveEventText.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    fileSaveEventText_actionPerformed(e);
                }
            });


        menuFileNetworkInfo.setText("Network Information...");
        menuFileNetworkInfo.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuFileNetworkInfo.setIcon(ImagesList.emptyImage);
        menuFileNetworkInfo.setEnabled(false);
        menuFileNetworkInfo.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                   fileNetworkInfo_actionPerformed(e);
                }
            });

	menuFileExit.setFont(new java.awt.Font("SansSerif", 0, 12));
	menuFileExit.setText("Exit");
        menuFileExit.setMnemonic(KeyEvent.VK_X);
        menuFileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
                                                           Event.ALT_MASK));
	menuFileExit.setIcon(ImagesList.emptyImage);
	menuFileExit.addActionListener(new ActionListener()  {
		public void actionPerformed(ActionEvent e) {
		    fileExit_actionPerformed(e);
		}
	    });

        menuFile.add(menuFileOpenLog);
        menuFile.add(menuFileNetworkInit);
	menuFile.addSeparator();
        menuFile.add(menuFileSaveEventText);
        menuFile.addSeparator();
        menuFile.add(menuFileNetworkInfo);
        menuFile.addSeparator();
	menuFile.add(menuFileExit);

        // Menu - View
        menuView.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuView.setText("View");
        menuView.setMnemonic(KeyEvent.VK_V);

        menuViewNodeTree.setText("Nodes Tree");
        menuViewNodeTree.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewNodeTree.setMnemonic(KeyEvent.VK_N);
        menuViewNodeTree.setState(true);
        menuViewNodeTree.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewNodeTree_actionPerformed(e);
                }
            });

        menuViewNodeInfoTables.setText("Node Information Tables");
        menuViewNodeInfoTables.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewNodeInfoTables.setMnemonic(KeyEvent.VK_I);
        menuViewNodeInfoTables.setState(true);
        menuViewNodeInfoTables.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewNodeInfoTables_actionPerformed(e);
                }
            });

        menuViewGraph.setText("Graph/Time Slider");
        menuViewGraph.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewGraph.setMnemonic(KeyEvent.VK_G);
        menuViewGraph.setState(true);
        menuViewGraph.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewGraph_actionPerformed(e);
                }
            });

        menuViewMsg.setText("Messages");
        menuViewMsg.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewMsg.setMnemonic(KeyEvent.VK_M);
        menuViewMsg.setState(true);
        menuViewMsg.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewMsg_actionPerformed(e);
                }
            });

        menuViewControlPanel.setText("Compact Control Panel");
        menuViewControlPanel.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewControlPanel.setMnemonic(KeyEvent.VK_C);
        menuViewControlPanel.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewControlPanel_actionPerformed(e);
                }
            });

        menuViewTimeScale.setText("Time Scale");
        menuViewTimeScale.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewTimeScale.setMnemonic(KeyEvent.VK_T);

	// Insert subMenuItem according to TimeScaleOptions
        for (int i = 0; i < timeScaleOptions.length; i++) {
            JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(timeScaleOptions[i]);
            menuItem.setFont(new java.awt.Font("SansSerif", 0, 12));
            menuItem.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewTimeScales_actionPerformed(e);
                }
            });
            menuViewTimeScale.add(menuItem);
            timeScaleGroup.add(menuItem);
            if (i == 0)  // set the first one to be default
                menuItem.setSelected(true);
        }

        menuViewSlider.setText("Slider");
        menuViewSlider.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewSlider.setMnemonic(KeyEvent.VK_L);

        // Insert subMenuItem according to SliderOptions
        for (int i = 0; i < sliderOptions.length; i++) {
            JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(sliderOptions[i]);
            menuItem.setFont(new java.awt.Font("SansSerif", 0, 12));
            menuItem.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewSlider_actionPerformed(e);
                }
            });
            menuViewSlider.add(menuItem);
            sliderGroup.add(menuItem);
            if (i == 0)  // set the first on to be default
                menuItem.setSelected(true);
        }

        menuViewPreset.setText("Preseted View");
        menuViewPreset.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewPreset.setMnemonic(KeyEvent.VK_P);

        menuViewPresetNormal.setText("Normal");
        menuViewPresetNormal.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewPresetNormal.setMnemonic(KeyEvent.VK_N);
        menuViewPresetNormal.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewPresetNormal_actionPerformed(e);
                }
            });

        menuViewPresetCompact.setText("Compact");
        menuViewPresetCompact.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewPresetCompact.setMnemonic(KeyEvent.VK_C);
        menuViewPresetCompact.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewPresetCompact_actionPerformed(e);
                }
            });

        menuViewPresetDetail.setText("Detail");
        menuViewPresetDetail.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewPresetDetail.setMnemonic(KeyEvent.VK_D);
        menuViewPresetDetail.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewPresetDetail_actionPerformed(e);
                }
            });

        menuViewPreset.add(menuViewPresetNormal);
        menuViewPreset.add(menuViewPresetCompact);
        menuViewPreset.add(menuViewPresetDetail);

        menuViewPlayPause.setText("Play");
        menuViewPlayPause.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewPlayPause.setMnemonic(KeyEvent.VK_P);
        menuViewPlayPause.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewPlayPause_actionPerformed(e);
                }
            });

        menuViewStop.setText("Stop");
        menuViewStop.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewStop.setMnemonic(KeyEvent.VK_S);
        menuViewStop.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewStop_actionPerformed(e);
                }
            });

        menuViewRelocate.setText("Relocate Elements");
        menuViewRelocate.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuViewRelocate.setMnemonic(KeyEvent.VK_R);
        menuViewRelocate.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    viewRelocate_actionPerformed(e);
                }
            });


        menuView.add(menuViewNodeTree);
        menuView.add(menuViewNodeInfoTables);
        menuView.addSeparator();
        menuView.add(menuViewGraph);
        menuView.add(menuViewMsg);
        menuView.addSeparator();
        menuView.add(menuViewControlPanel);
        menuView.add(menuViewSlider);
        menuView.add(menuViewTimeScale);
        menuView.addSeparator();
        menuView.add(menuViewPreset);
        menuView.addSeparator();
        menuView.add(menuViewPlayPause);
        menuView.add(menuViewStop);
        menuView.addSeparator();
        menuView.add(menuViewRelocate);

	// Menu - Help
	menuHelp.setText("Help");
	menuHelp.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuHelp.setMnemonic(KeyEvent.VK_H);

	menuHelpAbout.setText("About...");
	menuHelpAbout.setFont(new java.awt.Font("SansSerif", 0, 12));
        menuHelpAbout.setMnemonic(KeyEvent.VK_A);
	menuHelpAbout.addActionListener(new ActionListener()  {
		public void actionPerformed(ActionEvent e) {
		    helpAbout_actionPerformed(e);
		}
	    });

	menuHelp.add(menuHelpAbout);

	// Add Menus into MenuBar
	menuBar.setFont(new java.awt.Font("SansSerif", 0, 12));
	menuBar.add(menuFile);
        menuBar.add(menuView);
        menuBar.add(Box.createHorizontalGlue());
	menuBar.add(menuHelp);


	// Buttons --------------------------------------------
	openButton.setIcon(ImagesList.openImage);
	openButton.setToolTipText("Open File");
        openButton.setMaximumSize(new Dimension(25, 25));
        openButton.setMinimumSize(new Dimension(25, 25));
        openButton.setPreferredSize(new Dimension(25, 25));
        openButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    openButton_actionPerformed(e);
		}
	    });

        networkButton.setIcon(ImagesList.networkImage);
        networkButton.setToolTipText("Initialize Network Connection");
        networkButton.setMaximumSize(new Dimension(25, 25));
        networkButton.setMinimumSize(new Dimension(25, 25));
        networkButton.setPreferredSize(new Dimension(25, 25));
        networkButton.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    networkButton_actionPerformed(e);
                }
            });

	closeButton.setIcon(ImagesList.closeImage);
	closeButton.setToolTipText("Close File");
        closeButton.setMaximumSize(new Dimension(25, 25));
        closeButton.setMinimumSize(new Dimension(25, 25));
        closeButton.setPreferredSize(new Dimension(25, 25));
	closeButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    closeButton_actionPerformed(e);
		}
	    });

	helpButton.setIcon(ImagesList.helpImage);
	helpButton.setToolTipText("Help");
        helpButton.setMaximumSize(new Dimension(25, 25));
        helpButton.setMinimumSize(new Dimension(25, 25));
        helpButton.setPreferredSize(new Dimension(25, 25));

        relocateButton.setIcon(ImagesList.relocateImage);
        relocateButton.setToolTipText("Relocate");
        relocateButton.setMaximumSize(new Dimension(25, 25));
        relocateButton.setMinimumSize(new Dimension(25, 25));
        relocateButton.setPreferredSize(new Dimension(25, 25));
	relocateButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    relocateButton_actionPerformed(e);
		}
	    });

        play_pauseToolbarButton.setIcon(ImagesList.playImage);
        play_pauseToolbarButton.setVisible(false);
        play_pauseToolbarButton.setMaximumSize(new Dimension(25, 25));
        play_pauseToolbarButton.setMinimumSize(new Dimension(25, 25));
        play_pauseToolbarButton.setPreferredSize(new Dimension(25, 25));
        play_pauseToolbarButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    play_pauseToolbarButton_actionPerformed(e);
		}
	    });

        stopToolbarButton.setIcon(ImagesList.stopImage);
        stopToolbarButton.setVisible(false);
        stopToolbarButton.setMaximumSize(new Dimension(25, 25));
        stopToolbarButton.setMinimumSize(new Dimension(25, 25));
        stopToolbarButton.setPreferredSize(new Dimension(25, 25));
        stopToolbarButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    stopToolbarButton_actionPerformed(e);
		}
	    });

        stepBackToolbarButton.setIcon(ImagesList.stepBackImage);
        stepBackToolbarButton.setVisible(false);
        stepBackToolbarButton.setMaximumSize(new Dimension(25, 25));
        stepBackToolbarButton.setMinimumSize(new Dimension(25, 25));
        stepBackToolbarButton.setPreferredSize(new Dimension(25, 25));
        stepBackToolbarButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    stepBackToolbarButton_actionPerformed(e);
		}
	    });

        stepForwardToolbarButton.setIcon(ImagesList.stepForwardImage);
        stepForwardToolbarButton.setVisible(false);
        stepForwardToolbarButton.setMaximumSize(new Dimension(25, 25));
        stepForwardToolbarButton.setMinimumSize(new Dimension(25, 25));
        stepForwardToolbarButton.setPreferredSize(new Dimension(25, 25));
        stepForwardToolbarButton.addActionListener(new java.awt.event.ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    stepForwardToolbarButton_actionPerformed(e);
		}
	    });

        timeToolbarButton.setBackground(Color.white);
        timeToolbarButton.setEnabled(false);
        timeToolbarButton.setFont(new java.awt.Font("SansSerif", 0, 10));
        timeToolbarButton.setBorder(BorderFactory.createLoweredBevelBorder());
        timeToolbarButton.setMaximumSize(new Dimension(100, 20));
        timeToolbarButton.setMinimumSize(new Dimension(100, 20));
        timeToolbarButton.setPreferredSize(new Dimension(100, 20));
        timeToolbarButton.setVisible(false);



	// Toolbar --------------------------------------------
	mainToolBar.add(openButton);
        mainToolBar.add(networkButton);
	mainToolBar.add(closeButton);
	mainToolBar.add(helpButton);
        mainToolBar.add(relocateButton);
        mainToolBar.addSeparator();
        mainToolBar.add(play_pauseToolbarButton);
        mainToolBar.add(stopToolbarButton);
        mainToolBar.add(stepBackToolbarButton);
        mainToolBar.add(stepForwardToolbarButton);
        mainToolBar.add(timeToolbarButton, null);


 	// StatusBar Configrations ----------------------------
	statusBarLabel.setFont(new java.awt.Font("SansSerif", 0, 12));
	statusBarLabel.setForeground(Color.black);
	statusBarLabel.setBorder(BorderFactory.createLoweredBevelBorder());
	statusBarLabel.setMaximumSize(new Dimension(600, 15));
	statusBarLabel.setMinimumSize(new Dimension(400, 15));
	statusBarLabel.setPreferredSize(new Dimension(600, 15));
	statusBarLabel.setText("Ready");

  	progressBar.setBorder(BorderFactory.createLoweredBevelBorder());
     	progressBar.setForeground(Color.blue);
        progressBar.setFont(new java.awt.Font("SansSerif", 1, 10));

	statusBar.setBorder(BorderFactory.createEtchedBorder());
	statusBar.setMinimumSize(new Dimension(447, 20));
	statusBar.setPreferredSize(new Dimension(447, 25));
	statusBar.setLayout(statusBarBorderLayout);
	statusBar.add(statusBarLabel, BorderLayout.CENTER);
	statusBar.add(progressBar, BorderLayout.EAST);


        // Slider Control Panel Configuration -------------
        timeScaleComboBox.setFont(new java.awt.Font("SansSerif", 0, 10));
        timeScaleComboBox.setMinimumSize(new Dimension(70, 20));
        timeScaleComboBox.setPreferredSize(new Dimension(70, 20));
	timeScaleComboBox.setMaximumSize(new Dimension(70, 20));
        timeScaleComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                timeScaleComboBox_actionPerformed(e);
            }
        });
        initializeTimeScaleComboBox();

	timeTextField.setMaximumSize(new Dimension(100, 20));
        timeTextField.setMinimumSize(new Dimension(100, 20));
	timeTextField.setDisabledTextColor(Color.black);
        timeTextField.setFont(new java.awt.Font("SansSerif", 0, 10));
        timeTextField.setBorder(BorderFactory.createLoweredBevelBorder());
        timeTextField.setPreferredSize(new Dimension(100, 20));
        timeTextField.setHorizontalAlignment(SwingConstants.CENTER);
        timeTextField.setEnabled(false);
        timeTextField.setText("0.0000");

        play_pauseButton.setBorder(BorderFactory.createRaisedBevelBorder());
        play_pauseButton.setPreferredSize(new Dimension(30, 20));
        play_pauseButton.setIcon(ImagesList.playImage);
        play_pauseButton.setMaximumSize(new Dimension(30, 25));
        play_pauseButton.setMinimumSize(new Dimension(20, 20));
        play_pauseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                play_pauseButton_actionPerformed(e);
            }
        });

        stopButton.setBorder(BorderFactory.createRaisedBevelBorder());
        stopButton.setPreferredSize(new Dimension(30, 20));
        stopButton.setIcon(ImagesList.stopImage);
        stopButton.setMaximumSize(new Dimension(30, 25));
        stopButton.setMinimumSize(new Dimension(20, 20));
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                stopButton_actionPerformed(e);
            }
        });

        stepBackButton.setBorder(BorderFactory.createRaisedBevelBorder());
        stepBackButton.setPreferredSize(new Dimension(30, 20));
        stepBackButton.setIcon(ImagesList.stepBackImage);
        stepBackButton.setMaximumSize(new Dimension(30, 25));
        stepBackButton.setMinimumSize(new Dimension(20, 20));
        stepBackButton.setVisible(false);
        stepBackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                stepBackButton_actionPerformed(e);
            }
        });

        stepForwardButton.setBorder(BorderFactory.createRaisedBevelBorder());
        stepForwardButton.setPreferredSize(new Dimension(30, 20));
        stepForwardButton.setIcon(ImagesList.stepForwardImage);
        stepForwardButton.setMaximumSize(new Dimension(30, 25));
        stepForwardButton.setMinimumSize(new Dimension(20, 20));
        stepForwardButton.setVisible(false);
        stepForwardButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                stepForwardButton_actionPerformed(e);
            }
        });

        timeSlider.setPreferredSize(new Dimension(300, 20));
        timeSlider.putClientProperty("JSlider.isFilled", Boolean.TRUE);
        timeSlider.setFont(new java.awt.Font("SansSerif", 0, 10));
        timeSlider.setValue(0);
        timeSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                timeSlider_stateChanged(e);
            }
        });
        timeSlider.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                timeSlider_mousePressed(e);
            }

            public void mouseReleased(MouseEvent e) {
                timeSlider_mouseReleased(e);
            }
        });

        timeSlider.revalidate();

        sliderControlPanel.setPreferredSize(new Dimension(10, 40));
        sliderControlPanel.setLayout(sliderControlPanelFlowLayout);
        sliderControlPanel.add(timeScaleComboBox, null);
        sliderControlPanel.add(timeTextField, null);
        sliderControlPanel.add(timeSlider, null);
        sliderControlPanel.add(play_pauseButton, null);
        sliderControlPanel.add(stopButton, null);
        sliderControlPanel.add(stepBackButton, null);
        sliderControlPanel.add(stepForwardButton, null);


        // Tabbed Panel Configurations --------------------
        neighborNodeGraphPanel.setVisible(true);
        neighborNodeGraphPanel.setOpaque(true);
        neighborNodeGraphPanel.attach(graphManager);
        neighborNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                neighborNodeGraphPanel_mouseClicked(e);
            }
        });
        neighborNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                neighborNodeGraphPanel_mousePressed(e);
            }
        });
        neighborNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                neighborNodeGraphPanel_mouseReleased(e);
            }
        });

        routingNodeGraphPanel.setVisible(true);
        routingNodeGraphPanel.setOpaque(true);
        routingNodeGraphPanel.attach(graphManager);
        routingNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                routingNodeGraphPanel_mouseClicked(e);
            }
        });
        routingNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                routingNodeGraphPanel_mousePressed(e);
            }
        });
        routingNodeGraphPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                routingNodeGraphPanel_mouseReleased(e);
            }
        });



        // LeftPane Configurations ------------------------
        nodesList.setFont(new java.awt.Font("SansSerif", 0, 10));
        nodesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        nodesList.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                nodesList_valueChanged(e);
            }
        });

        treeScrollPane.getViewport().add(nodesList, null);
        treeScrollPane.setFont(new java.awt.Font("SansSerif", 0, 10));
	treeScrollPane.setAutoscrolls(true);
	treeScrollPane.setBorder(BorderFactory.createLoweredBevelBorder());
	treeScrollPane.setMinimumSize(new Dimension(100, 200));
	treeScrollPane.setPreferredSize(new Dimension(150, 300));

	leftSplitPane.setBorder(null);
	leftSplitPane.setMinimumSize(new Dimension(150, 50));
	leftSplitPane.setPreferredSize(new Dimension(150, 399));

        tableSelectionComboBox.setFont(new java.awt.Font("SansSerif", 0, 10));
        tableSelectionComboBox.setBackground(new Color(255, 255, 255));
        tableSelectionComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                tableSelectionComboBox_itemStateChanged(e);
            }
        });

        selectedElementLabel.setBorder(BorderFactory.createRaisedBevelBorder());
        selectedElementLabel.setBackground(new Color(204, 204, 204));
        selectedElementLabel.setLineWrap(true);
        selectedElementLabel.setRows(2);
        selectedElementLabel.setMaximumSize(new Dimension(100, 100));
        selectedElementLabel.setMinimumSize(new Dimension(100, 20));
        selectedElementLabel.setFont(new java.awt.Font("SansSerif", 0, 10));
        selectedElementLabel.setPreferredSize(new Dimension(100, 30));
        selectedElementLabel.setEditable(false);

        infoTable.setFont(new java.awt.Font("SansSerif", 0, 10));

        tableScrollPane.setAutoscrolls(true);
        tableScrollPane.getViewport().add(infoTable, null);

	nodeInfoPanel.setLayout(nodeInfoPanelBorderLayout);
	nodeInfoPanel.setBorder(BorderFactory.createLoweredBevelBorder());
        nodeInfoPanel.setMinimumSize(new Dimension(0, 0));
        nodeInfoPanel.add(tableSelectionComboBox, BorderLayout.NORTH);
        nodeInfoPanel.add(selectedElementLabel, BorderLayout.SOUTH);
        nodeInfoPanel.add(tableScrollPane, BorderLayout.CENTER);

        leftSplitPane.add(treeScrollPane, JSplitPane.TOP);
	leftSplitPane.add(nodeInfoPanel, JSplitPane.BOTTOM);
        leftSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        leftSplitPane.setOneTouchExpandable(true);
        leftSplitPane.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                leftSplitPane_propertyChange(e);
            }
        });


        // RightPane Configurations -----------------------
        infoTextPane.setEditable(false);

	textScrollPane.getViewport().add(infoTextPane, null);
        textScrollPane.setMinimumSize(new Dimension(0, 0));

        eventPanel.setLayout(eventPanelBorderLayout);
        eventPanel.add(sliderControlPanel, BorderLayout.SOUTH);
        eventPanel.add(tabbedPane, BorderLayout.CENTER);

        tabbedPane.add(neighborNodeGraphPanel, "Neighbor");
        tabbedPane.add(routingNodeGraphPanel, "Routing");
        tabbedPane.setFont(new java.awt.Font("SansSerif", 0, 12));
        tabbedPane.setOpaque(true);

	rightSplitPane.add(eventPanel, JSplitPane.TOP);
	rightSplitPane.add(textScrollPane, JSplitPane.BOTTOM);
        rightSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        rightSplitPane.setMinimumSize(new Dimension(0, 0));
        rightSplitPane.setOneTouchExpandable(true);
        rightSplitPane.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                rightSplitPane_propertyChange(e);
            }
        });


        // ContentSplitPane Configuration -----------------
	contentSplitPane.add(leftSplitPane, JSplitPane.LEFT);
	contentSplitPane.add(rightSplitPane, JSplitPane.RIGHT);
        contentSplitPane.setOneTouchExpandable(true);
        contentSplitPane.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                contentSplitPane_propertyChange(e);
            }
        });


	// ContentPane Configurations ---------------------
	contentPane = (JPanel) this.getContentPane();
	contentPane.setLayout(contentBorderLayout);
	contentPane.setBackground(new Color(140, 134, 199));
	contentPane.setPreferredSize(new Dimension(800, 600));
	contentPane.add(mainToolBar, BorderLayout.NORTH);
	contentPane.add(statusBar, BorderLayout.SOUTH);
	contentPane.add(contentSplitPane, BorderLayout.CENTER);

	this.setSize(new Dimension(800, 600));
	this.setTitle("Overlay Network Monitor");
	this.setJMenuBar(menuBar);

        contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
        leftSplitPane.setDividerLocation(preset_LeftSplitPane_location);
        rightSplitPane.setDividerLocation(preset_RightSplitPane_location);

        ImagesList.waitForImagesReady(neighborNodeGraphPanel, this);

        enableControls(false);
        contraEnableControls(false);

    }















    /////////////////////////////////////////////////////////
    // Event Handling Functions
    /////////////////////////////////////////////////////////

    // Menu Item Events Handlers ----------------------------
    // File | Open Log Files action performed
    void fileOpenLog_actionPerformed(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION &&
            fileChooser.getSelectedFile().isDirectory()) {

            dbAgent.setMonitorMode(mode);

            File[] filesList = fileChooser.getSelectedFile().listFiles();
            filesParser = new LogFilesParser();
            filesParser.getFrame(this);
            filesParser.getDBObject(dbAgent);
            filesParser.parseFiles(filesList);

            mode = LOGFILE_MODE;

        }

    }

    // File | Network action performed
    void fileNetwork_actionPerformed(ActionEvent e) {
        JLabel label = new JLabel("Please enter the communication port:");
        label.setFont(new java.awt.Font("SansSerif", 0, 10));
        String name = (String)JOptionPane.showInputDialog(this, label,
                                                  "Network Connection", JOptionPane.PLAIN_MESSAGE,
                                                  ImagesList.networkBigImage, null, null);
        if (name == null)
            return;

        label = new JLabel("Please enter Time Server address:");
        label.setFont(new java.awt.Font("SansSerif", 0, 10));
        String timeServer = (String)JOptionPane.showInputDialog(this, label,
                                                    "Time Server", JOptionPane.PLAIN_MESSAGE,
                                                    ImagesList.networkBigImage, null, null);

        if (timeServer == null)
            return;

        try {
            double globalTime = -1.0;

            while (globalTime == -1) {
                try {
                    globalTime = TimeSyn.getGlobalTime(timeServer, Integer.parseInt(name));
                }
                catch (Exception ex) {
                    System.out.println(ex);
                }
            }

            dbAgent.setGodBaseTime(globalTime);

            netDataModel = new NetworkStatDataModel();
            networkManager = new NetworkManager(Integer.parseInt(name), dbAgent,
                                                netDataModel);
            networkManager.activate();

            mode = NETWORK_MODE;
            contraEnableControls(true);

            dbAgent.setMonitorMode(mode);

            // TODO: is this necessary? - tungfai
            //setupSliderControl();   // Default is time based

            enableControls(true);
            play_pauseButton_actionPerformed(null);

        }
        catch (java.net.SocketException ex) {
            printConsoleError("MainScreen", "fileNetwork_actionPerformed", "Socket Exception",
                              ex);
        }
    }

    // File | Save Event Text action performed
    void fileSaveEventText_actionPerformed(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            try {
                FileWriter writer = new FileWriter(fileChooser.getSelectedFile());
                writer.write(infoTextPane.getText());
                writer.close();
            }
            catch (IOException ex) {

            }
        }

    }

    // File | Network Info Event action performed
    void fileNetworkInfo_actionPerformed(ActionEvent e) {
        NetworkInfoBox networkInfo = new NetworkInfoBox(this);
        networkInfo.setNetworkStatDataModel(netDataModel);

        Dimension dlgSize = networkInfo.getPreferredSize();
	Dimension frmSize = getSize();
	Point loc = getLocation();
	networkInfo.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
			(frmSize.height - dlgSize.height) / 2 + loc.y);
        networkInfo.show();


    }

    // File | Exit action performed
    void fileExit_actionPerformed(ActionEvent e) {
        if (showDialog(this, JOptionPane.QUESTION_MESSAGE,
                       JOptionPane.OK_CANCEL_OPTION,
                       "Any unsaved information may lose.  Are you sure?",
                       "Exit") == JOptionPane.OK_OPTION)
    	    System.exit(0);
    }


    // View | Node Tree action performed
    void viewNodeTree_actionPerformed(ActionEvent e) {

        if (!menuViewNodeTree.getState()) {
            if (menuViewNodeInfoTables.getState())
                leftSplitPane.setDividerLocation(0);
            else
                contentSplitPane.setDividerLocation(0);

            numViewablePaneLeft --;
        }
        else {
            if (menuViewNodeInfoTables.getState())
                leftSplitPane.setDividerLocation(preset_LeftSplitPane_location);
            else {

                contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
                leftSplitPane.setDividerLocation((int)contentSplitPane.getHeight());

            }
            numViewablePaneLeft ++;
        }

        disableLastMenuItem();
        menuDrivenEvent = true;

    }


    // View | Node Info Tables action performed
    void viewNodeInfoTables_actionPerformed(ActionEvent e) {

       if (!menuViewNodeInfoTables.getState()) {
            if (menuViewNodeTree.getState())
                leftSplitPane.setDividerLocation(1.0);
            else
                contentSplitPane.setDividerLocation(0);

            numViewablePaneLeft --;
        }
        else {
            if (menuViewNodeTree.getState())
                leftSplitPane.setDividerLocation(preset_LeftSplitPane_location);
            else {
                contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
                leftSplitPane.setDividerLocation(0);
            }
            numViewablePaneLeft ++;
        }

        disableLastMenuItem();
        menuDrivenEvent = true;

    }


    // View | Graph action performed
    void viewGraph_actionPerformed(ActionEvent e) {

        if (!menuViewGraph.getState()) {
            if (menuViewMsg.getState())
                rightSplitPane.setDividerLocation(0);
            else
                contentSplitPane.setDividerLocation(1.0);
            numViewablePaneRight --;
        }
        else {
            if (menuViewMsg.getState())
                rightSplitPane.setDividerLocation(preset_RightSplitPane_location);
            else {
                contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
                rightSplitPane.setDividerLocation((int)contentSplitPane.getHeight() - 2);
            }
            numViewablePaneRight ++;
        }
        disableLastMenuItem();
        menuDrivenEvent = true;
    }


    // View | Message action performed
    void viewMsg_actionPerformed(ActionEvent e) {
        if (!menuViewMsg.getState()) {
            if (menuViewGraph.getState())
                rightSplitPane.setDividerLocation(1.0);
            else
                contentSplitPane.setDividerLocation(1.0);

            numViewablePaneRight --;
        }
        else {
            if (menuViewGraph.getState())
                rightSplitPane.setDividerLocation(preset_RightSplitPane_location);
            else {
                contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
                rightSplitPane.setDividerLocation(0);
            }
            numViewablePaneRight ++;
        }
        disableLastMenuItem();
        menuDrivenEvent = true;

    }


    // View | Time Scales action performed
    void viewTimeScales_actionPerformed(ActionEvent e) {
        timeScaleComboBox.setSelectedItem( ((JRadioButtonMenuItem)e.getSource()).getText());

    }

    // View | Slider  action performed
    void viewSlider_actionPerformed(ActionEvent e) {
        if ( ((JRadioButtonMenuItem)e.getSource()).getText().equals(sliderOptions[0])) {
            // Time Based
            timeScaleComboBox.setVisible(true);
            menuViewTimeScale.setEnabled(true);
            timeScaleComboBox_actionPerformed(null);
            stepBackButton.setVisible(false);
            stepForwardButton.setVisible(false);
            stepBackToolbarButton.setVisible(false);
            stepForwardToolbarButton.setVisible(false);
            sliderMoveTimer.setDelay(SLIDER_MOVEMENT_DELAY);
            timeBased = true;
        }
        else {
            // Event Based
            timeScaleComboBox.setVisible(false);
            menuViewTimeScale.setEnabled(false);
            stepBackButton.setVisible(true);
            stepForwardButton.setVisible(true);
            stepBackToolbarButton.setVisible(compactControlPanelMode);
            stepForwardToolbarButton.setVisible(compactControlPanelMode);
            sliderMoveTimer.setDelay(SLIDER_MOVEMENT_STEP);
            timeBased = false;
        }

        setupSliderControl();

    }

    // View | Control Panel action performed
    void viewControlPanel_actionPerformed(ActionEvent e) {

        if (compactControlPanelMode) {
            sliderControlPanel.setVisible(true);
            play_pauseToolbarButton.setVisible(false);
            stopToolbarButton.setVisible(false);
            timeToolbarButton.setVisible(false);
            stepBackToolbarButton.setVisible(false);
            stepForwardToolbarButton.setVisible(false);
            menuViewControlPanel.setText("Compact Control Panel");
        }
        else {
            sliderControlPanel.setVisible(false);
            play_pauseToolbarButton.setVisible(true);
            stopToolbarButton.setVisible(true);
            timeToolbarButton.setVisible(true);
            stepBackToolbarButton.setVisible(!timeBased);
            stepForwardToolbarButton.setVisible(!timeBased);
            menuViewControlPanel.setText("Expand Control Panel");
        }
        compactControlPanelMode = !compactControlPanelMode;

        // Do this to focus frame repaint on Solaris
        // No such problem on NT and Linux
        rightSplitPane.setDividerLocation(rightSplitPane.getDividerLocation());

    }


    // View | Preset | Normal action performed
    void viewPresetNormal_actionPerformed(ActionEvent e) {
        contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
        leftSplitPane.setDividerLocation(preset_LeftSplitPane_location);
        rightSplitPane.setDividerLocation(contentPane.getHeight() - BORDER_DIFF);

        if (compactControlPanelMode)
            viewControlPanel_actionPerformed(e);

    }


    // View | Preset | Compact action performed
    void viewPresetCompact_actionPerformed(ActionEvent e) {
        contentSplitPane.setDividerLocation(0);
        rightSplitPane.setDividerLocation(contentPane.getHeight() - BORDER_DIFF);

        if (compactControlPanelMode)
            viewControlPanel_actionPerformed(e);

    }


    // View | Preset | Detail action performed
    void viewPresetDetail_actionPerformed(ActionEvent e) {
        contentSplitPane.setDividerLocation(preset_ContentSplitPane_location);
        leftSplitPane.setDividerLocation(preset_LeftSplitPane_location);
        rightSplitPane.setDividerLocation(preset_RightSplitPane_location);

        if (compactControlPanelMode)
            viewControlPanel_actionPerformed(e);

    }


    // View | Play/Pause action performed
    void viewPlayPause_actionPerformed(ActionEvent e) {
        play_pauseButton_actionPerformed(e);
    }


    // View | Stop action performed
    void viewStop_actionPerformed(ActionEvent e) {
        stopButton_actionPerformed(e);
    }

    // View | Relocate Elements action performed
    void viewRelocate_actionPerformed(ActionEvent e) {
        graphManager.relocateElements();
        neighborNodeGraphPanel.repaint();
        routingNodeGraphPanel.repaint();
    }

    // Help | About action performed
    public void helpAbout_actionPerformed(ActionEvent e) {
	AboutBox dlg = new AboutBox(this);
	Dimension dlgSize = dlg.getPreferredSize();
	Dimension frmSize = getSize();
	Point loc = getLocation();
	dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
			(frmSize.height - dlgSize.height) / 2 + loc.y);
	dlg.setModal(true);
	dlg.show();
    }


    // Toolbar Events Handlers ------------------------------
    // Open Toolbar Button Events
    void openButton_actionPerformed(ActionEvent e) {
	fileOpenLog_actionPerformed(e);
    }

    void networkButton_actionPerformed(ActionEvent e) {
        fileNetwork_actionPerformed(e);
    }

    void closeButton_actionPerformed(ActionEvent e) {
        System.out.println("DISK SIZE: " + dbAgent.getDiskSize());
	System.out.println("MEMORY SIZE: " + dbAgent.getVMSize());
	System.out.println("NEIGHBOR TBL SIZE: " + 
			   dbAgent.getNeighborTableSize());
	System.out.println("EVENT TBL SIZE: " + dbAgent.getEventTableSize());
	
    }

    void relocateButton_actionPerformed(ActionEvent e) {
        viewRelocate_actionPerformed(e);
    }


    // Play/Pause Toolbar Button Events
    void play_pauseToolbarButton_actionPerformed(ActionEvent e) {
        play_pauseButton_actionPerformed(e);
    }


    // Stop Toolbar Button Events
    void stopToolbarButton_actionPerformed(ActionEvent e) {
        stopButton_actionPerformed(e);
    }


    // StepBack Toolbar Button Events
    void stepBackToolbarButton_actionPerformed(ActionEvent e) {
        stepBackButton_actionPerformed(e);
    }


    // StepForward Toolbar Button Events
    void stepForwardToolbarButton_actionPerformed(ActionEvent e) {
        stepForwardButton_actionPerformed(e);
    }


    // Split Panes Events Handers ---------------------------
    // ContentSplit Events
    void contentSplitPane_propertyChange(PropertyChangeEvent e) {
        if (e.getPropertyName().equals(JSplitPane.LAST_DIVIDER_LOCATION_PROPERTY) &&
            !menuDrivenEvent) {

            if (contentSplitPane.getDividerLocation() <= 2) {
                menuViewNodeTree.setState(false);
                menuViewNodeInfoTables.setState(false);
                if (numViewableSplitPane(leftSplitPane) == 2)
                    numViewablePaneLeft -= 2;
                else
                    numViewablePaneLeft --;

                disableLastMenuItem();
            }
            else if (contentSplitPane.getDividerLocation() >=
                     contentSplitPane.getWidth() - BORDER_DIFF) {
                menuViewGraph.setState(false);
                menuViewMsg.setState(false);
                if (numViewableSplitPane(rightSplitPane) == 2)
                    numViewablePaneRight -= 2;
                else
                    numViewablePaneRight --;

                disableLastMenuItem();
            }
            else
                checkViewablePaneStatus(2);

        }
        menuDrivenEvent = false;

    }


    // LeftSplitPane Events
    void leftSplitPane_propertyChange(PropertyChangeEvent e) {
        if (e.getPropertyName().equals(JSplitPane.LAST_DIVIDER_LOCATION_PROPERTY) &&
            !menuDrivenEvent)
            checkViewablePaneStatus(0);
        menuDrivenEvent = false;
    }


    // RightSplitPane Events
    void rightSplitPane_propertyChange(PropertyChangeEvent e) {
        if (e.getPropertyName().equals(JSplitPane.LAST_DIVIDER_LOCATION_PROPERTY) &&
            !menuDrivenEvent)
            checkViewablePaneStatus(1);
        menuDrivenEvent = false;
    }


    // Slider Control Panel Events Handlers -------------------------
    // Play/Pause Button Event
    void play_pauseButton_actionPerformed(ActionEvent e) {

        if (eventPlayMode) {
            play_pauseButton.setIcon(ImagesList.playImage);
            play_pauseToolbarButton.setIcon(ImagesList.playImage);
            stepBackButton.setEnabled(true);
            stepForwardButton.setEnabled(true);
            stepBackToolbarButton.setEnabled(true);
            stepForwardToolbarButton.setEnabled(true);
            menuViewPlayPause.setText("Play");
            sliderMoveTimer.stop();
        }
        else {
            play_pauseButton.setIcon(ImagesList.pauseImage);
            play_pauseToolbarButton.setIcon(ImagesList.pauseImage);
            stepBackButton.setEnabled(false);
            stepForwardButton.setEnabled(false);
            stepBackToolbarButton.setEnabled(false);
            stepForwardToolbarButton.setEnabled(false);
            menuViewPlayPause.setText("Pause");
            sliderMoveTimer.start();
        }
        eventPlayMode = !eventPlayMode;
    }


    // Stop Button Event
    void stopButton_actionPerformed(ActionEvent e) {
        eventPlayMode = false;
        play_pauseButton.setIcon(ImagesList.playImage);
        play_pauseToolbarButton.setIcon(ImagesList.playImage);
        menuViewPlayPause.setText("Play");
        stepForwardButton.setEnabled(true);
        stepBackButton.setEnabled(true);
        stepForwardToolbarButton.setEnabled(true);
        stepBackToolbarButton.setEnabled(true);
        sliderMoveTimer.stop();
        timeSlider.setValue(timeSlider.getMinimum());

        currentNumEvent = 0;
        currentTime = baseTime;

        neighborNodeGraphPanel.repaint();
        routingNodeGraphPanel.repaint();

    }


    // Step Back Button Event
    void stepBackButton_actionPerformed(ActionEvent e) {
        timeSlider.setValue(timeSlider.getValue() - 1);
    }


    // Step Forward Button Event
    void stepForwardButton_actionPerformed(ActionEvent e) {
        timeSlider.setValue(timeSlider.getValue() + 1);
    }


    // Slider Events
    void timeSlider_stateChanged(ChangeEvent e) {

        // TODO: For v2.0, check if the time is valid first
        // if not, stay at previous value - tungfai

        if (mode == NETWORK_MODE && baseTime == -1)
            return; // do nothing as no data yet

        if (!userSliderMode && timeSlider.isEnabled()) {
            if (timeBased) {
                double newTime = (double)timeSlider.getValue() / 1000 + baseTime;

                String newTimeText = toTimeString(newTime, false);
                // TODO: Change the time display format - tungfai
                timeTextField.setText(newTimeText);
                timeToolbarButton.setText(newTimeText);
                boolean reset = (currentTime > newTime);
                currentTime = newTime;
                refreshData(newTime, -1, reset);

            }
            else {
                int newNumEvent = timeSlider.getValue();
                refreshData(-1, newNumEvent, (currentNumEvent > newNumEvent));

            }
            neighborNodeGraphPanel.repaint();
            routingNodeGraphPanel.repaint();

            if (timeSlider.getValue() == timeSlider.getMaximum() && eventPlayMode)
                play_pauseButton_actionPerformed(null);
        }

    }


    // Slider Mouse Pressed
    void timeSlider_mousePressed(MouseEvent e) {
        userSliderMode = true;
        savedSliderPosition = timeSlider.getValue();
    }


    // Slider Mouse Released
    void timeSlider_mouseReleased(MouseEvent e) {
        userSliderMode = false;

        if (mode == LOGFILE_MODE ||
            (mode == NETWORK_MODE &&
             dbAgent.isTimeValid(baseTime + (double)timeSlider.getValue() / 1000)
		&& baseTime != -1))
            timeSlider_stateChanged(null);
        else
            timeSlider.setValue(savedSliderPosition);
    }


    // Time Scale Combo Box Events
    void timeScaleComboBox_actionPerformed(ActionEvent e) {
        switch (timeScaleComboBox.getSelectedIndex()) {
            case 0:
                realTimeDelay = SLIDER_MOVEMENT_DELAY;
                break;
            case 1:
                realTimeDelay = SLIDER_MOVEMENT_DELAY / 10;
                break;
            case 2:
                realTimeDelay = SLIDER_MOVEMENT_DELAY / 4;
                break;
            case 3:
                realTimeDelay = SLIDER_MOVEMENT_DELAY / 2;
                break;
            case 4:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 2;
                break;
            case 5:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 4;
                break;
		// coarser time scale implemented -- yhchu
            case 6:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 10;
                break;
            case 7:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 20;
                break;
            case 8:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 50;
                break;
            case 9:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 100;
                break;
            case 10:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 200;
                break;
            case 11:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 500;
                break;
            case 12:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 1000;
                break;
            case 13:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 2000;
                break;
            case 14:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 5000;
                break;
            case 15:
                realTimeDelay = SLIDER_MOVEMENT_DELAY * 10000;
                break;
		/*
		  default:
		  throw new Exception("unhandle time scale selection " + 
		  timeScaleComboBox.getSelectedIndex());
		*/
        }
        ((JRadioButtonMenuItem)menuViewTimeScale.getItem(timeScaleComboBox.getSelectedIndex())).setSelected(true);

    }


    //Overridden so we can exit when window is closed
    protected void processWindowEvent(WindowEvent e) {
	super.processWindowEvent(e);
	if (e.getID() == WindowEvent.WINDOW_CLOSING) {
	    fileExit_actionPerformed(null);
	}
    }


    void neighborNodeGraphPanel_mouseClicked(MouseEvent e) {
        nodeGraphPanel_mouseClicked(e, NodeGraphPanel.NEIGHBOR_TYPE);
    }

    void neighborNodeGraphPanel_mousePressed(MouseEvent e) {
        // Use this to distinguish click and press - tungfai
        if (e.isShiftDown()) {
            dragNodeID = graphManager.checkPressedCoordination(e.getX(), e.getY());

            printConsoleMessage("MainScreen", "nodeGraphPanel_mousePressed", "Pressed: " + dragNodeID);
        }
    }

    void neighborNodeGraphPanel_mouseReleased(MouseEvent e) {
        if (dragNodeID != -1) {
            graphManager.setNewNodeCoordination(dragNodeID, new Coordination(e.getX(), e.getY()));
            neighborNodeGraphPanel.repaint();
            routingNodeGraphPanel.repaint();
            printConsoleMessage("MainScreen", "nodeGraphPanel_mouseReleased", "Released: " + dragNodeID);
            dragNodeID = -1;
        }

    }


    void nodeGraphPanel_mouseClicked(MouseEvent e, int graphType) {
        VisualElement element = null;

        // Check surrounding pixels too
        for (int i = -1; i < 1; i++)
            for (int j = -1; j < 1; j++) {
                element = graphManager.checkClickCoordination(e.getX() + i, e.getY() + j,
                                                              graphType);
                if (element != null)
                    break;
            }

        graphManager.updateRoutingInfo(currentTime);
        neighborNodeGraphPanel.repaint();
        routingNodeGraphPanel.repaint();
        printConsoleMessage("MainScreen", "nodeGraphPanel_mouseClicked", "Clicked");

        nodesList.clearSelection();
	tableManager.clearSelection();

        if (element == null)
            return;

        switch (element.getElementType()) {
            case VisualElement.NODE:
                Node node = (Node)element;
                listManager.setSelectedNodeID(node.getNodeID());
                tableManager.updateElementType(VisualElement.NODE, node.getNodeID(), -1);
                break;
            case VisualElement.LINK:
                Link link = (Link)element;
                tableManager.updateElementType(VisualElement.LINK,
                                               link.getSrcNode().getNodeID(),
                                               link.getDestNode().getNodeID());
                break;
        }

        selectedElementLabel.setText(element.toString());
    }


    void routingNodeGraphPanel_mouseClicked(MouseEvent e) {
        nodeGraphPanel_mouseClicked(e, NodeGraphPanel.ROUTING_TYPE);
    }

    void routingNodeGraphPanel_mousePressed(MouseEvent e) {
        neighborNodeGraphPanel_mousePressed(e);
    }

    void routingNodeGraphPanel_mouseReleased(MouseEvent e) {
        neighborNodeGraphPanel_mouseReleased(e);
    }

    void nodesList_valueChanged(ListSelectionEvent e) {

        if (!e.getValueIsAdjusting() && nodesList.getSelectedIndex() != -1) {
            int id = listManager.getSelectedNodeID();
            graphManager.setSelectedNode(id);
            graphManager.updateRoutingInfo(currentTime);
            selectedElementLabel.setText("Node: " + ((LightWeightLabel)nodesList.getSelectedValue()).text);
            tableManager.updateElementType(VisualElement.NODE, id, -1);
            neighborNodeGraphPanel.repaint();
            routingNodeGraphPanel.repaint();
        }

    }

    // TableSelectionComboBox Item Changed
    void tableSelectionComboBox_itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED)
            tableManager.updateTableSelection(tableSelectionComboBox.getSelectedIndex());
    }














    /////////////////////////////////////////////////////////
    // Defined Functions
    /////////////////////////////////////////////////////////

    public void statusBarMessage(String msg) {
	if (msg != null)
	    statusBarLabel.setText(msg);
	else
	    statusBarLabel.setText("Ready");

    }


    public void initProgressBar(int min, int max) {
	progressBar.setMaximum(max);
	progressBar.setMinimum(min);
        progressBar.setStringPainted(true);
    }


    public void updateProgressBar(boolean increment, int value) {
	if (increment)
	    progressBar.setValue(progressBar.getValue() + value);
	else
	    progressBar.setValue(value);
    }


    public void cancelProgressBar() {
	progressBar.setValue(0);
	progressBar.setMaximum(0);
	progressBar.setMinimum(0);
        progressBar.setStringPainted(false);
    }


    public int showDialog(Component parent, int messageType, int optionType,
                           String message, String title) {
        JLabel messageObj = new JLabel(message);
        messageObj.setFont(new java.awt.Font("SansSerif", 0, 12));
       	messageObj.setForeground(Color.black);
        return JOptionPane.showConfirmDialog(parent, messageObj, title,
                                             optionType, messageType);
    }


    public void printConsoleError(String objName, String funcName, String exception,
                                  Exception errorMsg) {
        System.err.println(objName + "." + funcName + "(): " + errorMsg);
        if (PRINT_EXCEPTION_AS_DIALOG)
            showDialog(this, JOptionPane.ERROR_MESSAGE, JOptionPane.DEFAULT_OPTION,
                       errorMsg.toString(), exception);

    }


    public void printConsoleMessage(String objName, String funcName,
                                    String message) {
        if (PRINT_CONSOLE_MESSAGE)
            System.out.println("Console Message:  " + objName + "." + funcName + "(): " + message);
    }


    int numViewableSplitPane(JSplitPane splitPane) {
        // return: 0  left / top
        //         1  right / bottom
        //         2  both

        if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
            if (splitPane.getDividerLocation() > 2 &&
                splitPane.getDividerLocation() < splitPane.getWidth() - BORDER_DIFF)
                return 2;
            else if (splitPane.getDividerLocation() <= 2)
                return 1;
            else
                return 0;

        }
        else {
            if (splitPane.getDividerLocation() > 2 &&
                splitPane.getDividerLocation() < splitPane.getHeight() - BORDER_DIFF)
                return 2;
            else if (splitPane.getDividerLocation() <= 2)
                return 1;
            else
                return 0;
        }

    }


    void disableLastMenuItem() {

        if (numViewablePaneLeft + numViewablePaneRight > 1) {
            menuViewNodeTree.setEnabled(true);
            menuViewNodeInfoTables.setEnabled(true);
            menuViewGraph.setEnabled(true);
            menuViewMsg.setEnabled(true);
            return ;
        }

        if (menuViewNodeTree.getState()) {
            menuViewNodeTree.setEnabled(false);
            return;
        }
        if (menuViewNodeInfoTables.getState()) {
            menuViewNodeInfoTables.setEnabled(false);
            return;
        }
        if (menuViewGraph.getState()) {
            menuViewGraph.setEnabled(false);
            return;
        }
        if (menuViewMsg.getState()) {
            menuViewMsg.setEnabled(false);
            return;
        }

    }


    void checkViewablePaneStatus(int direction) {
        // direction: 0 - left
        //            1 - right
        //            2 - both

        int pane;

        if (direction == 0 || direction == 2) {
            numViewablePaneLeft = 0;
            menuViewNodeTree.setState(false);
            menuViewNodeInfoTables.setState(false);
            menuViewNodeTree.setEnabled(true);
            menuViewNodeInfoTables.setEnabled(true);

            pane =  numViewableSplitPane(leftSplitPane);
            switch (pane) {
                case 0:
                    numViewablePaneLeft ++;
                    menuViewNodeTree.setState(true);
                    break;
                case 1:
                    numViewablePaneLeft ++;
                    menuViewNodeInfoTables.setState(true);
                    break;
                case 2:
                    numViewablePaneLeft += 2;
                    menuViewNodeTree.setState(true);
                    menuViewNodeInfoTables.setState(true);
                    break;
            }
        }

        if (direction == 1 || direction == 2) {
            numViewablePaneRight = 0;
            menuViewGraph.setState(false);
            menuViewMsg.setState(false);

            menuViewGraph.setEnabled(true);
            menuViewMsg.setEnabled(true);

            pane = numViewableSplitPane(rightSplitPane);
            switch (pane) {
                case 0:
                    numViewablePaneRight ++;
                    menuViewGraph.setState(true);
                    break;
                case 1:
                    numViewablePaneRight ++;
                    menuViewMsg.setState(true);
                    break;
                case 2:
                    numViewablePaneRight += 2;
                    menuViewGraph.setState(true);
                    menuViewMsg.setState(true);
                    break;
            }
        }


        //printConsoleMessage("MainScreen", "checkViewablePaneStatus",
        //                    "Left: " + numViewablePaneLeft +
        //                    "  Right: " + numViewablePaneRight);
        disableLastMenuItem();
    }

    void initializeTimeScaleComboBox() {
        for (int i = 0; i < timeScaleOptions.length; i++)
            timeScaleComboBox.addItem(timeScaleOptions[i]);
    }

    public void parserReady() {
        // For debug only - tungfai
        //dbAgent.printEventTable();
        //dbAgent.printNeighborTable();
        //dbAgent.printLinkInfoTable();

        // Set the base time
        baseTime = dbAgent.getBaseTime();
        currentNumEvent = 0;
        currentTime = baseTime;

        enableControls(true);
        contraEnableControls(true);
        setupSliderControl();   // Default is time based

    }

    public String toTimeString(double time, boolean showDate) {
        SimpleDateFormat sdFormat = null;
        if (showDate)
            sdFormat = new SimpleDateFormat(DATE_FORMAT + " " + TIME_FORMAT);
        else
            sdFormat = new SimpleDateFormat(TIME_FORMAT);

        return sdFormat.format(new Date((long)((time - TIME_DIFF) * 1000)));
    }

    void enableControls(boolean enabled) {
        menuViewSlider.setEnabled(enabled && mode != NETWORK_MODE);
        menuViewPlayPause.setEnabled(enabled);
        menuViewStop.setEnabled(enabled);
        menuViewRelocate.setEnabled(enabled);

        timeSlider.setEnabled(enabled);
        play_pauseButton.setEnabled(enabled);
        stopButton.setEnabled(enabled);

        relocateButton.setEnabled(enabled);
        play_pauseToolbarButton.setEnabled(enabled);
        stopToolbarButton.setEnabled(enabled);
        timeToolbarButton.setEnabled(enabled);

        tableSelectionComboBox.setEnabled(enabled);

        menuFileNetworkInfo.setEnabled(enabled && mode == NETWORK_MODE);
        menuFileSaveEventText.setEnabled(enabled);
    }

    void contraEnableControls(boolean enabled) {
        // Contra-enabled
        menuFileOpenLog.setEnabled(!enabled);
        openButton.setEnabled(!enabled);

        menuFileNetworkInit.setEnabled(!enabled);
        networkButton.setEnabled(!enabled);
    }


    void setupSliderControl() {

        // TODO: Real time can't base on getTimeofLastEvent() - tungfai

        if (baseTime == -1 && mode == NETWORK_MODE)
            return;

        timeSlider.setMinimum(0);
        timeSlider.setValue(timeSlider.getMinimum());
        if (timeBased) {
            if (mode == LOGFILE_MODE)
                timeSlider.setMaximum((int)((dbAgent.getTimeOfLastEvent() + 1 - baseTime) * 1000));
            else
                timeSlider.setMaximum((int)((DEFAULT_SLIDER_RANGE) * 1000));

            timeSlider.setMajorTickSpacing(0);
            timeSlider.setSnapToTicks(false);
        }
        else {
            timeSlider.setMaximum(dbAgent.getEventcount());
            timeSlider.setMajorTickSpacing(1);
            timeSlider.setSnapToTicks(true);
        }
        timeSlider.revalidate();
        timeSlider.repaint();

    }

    public void moveSliderControl() {

        if (baseTime == -1) {
            baseTime = dbAgent.getBaseTime();
            setupSliderControl();
        }

        if (baseTime == -1)
            return;

        if (timeBased) {
            if (mode == NETWORK_MODE &&
                !dbAgent.isTimeValid((double)(timeSlider.getValue() + realTimeDelay) / 1000 + baseTime))
                return;

            timeSlider.setValue(timeSlider.getValue() + realTimeDelay);

            if (mode == NETWORK_MODE && timeSlider.getValue() >= timeSlider.getMaximum() * 0.9)
                timeSlider.setMaximum(timeSlider.getMaximum() * 2);

        }
        else
            timeSlider.setValue(timeSlider.getValue() + 1);
    }

    void refreshData(double time, int numEvent, boolean reset) {

        if ( (timeBased && (time == baseTime)) ||
             (!timeBased && (numEvent == 0))  ||
             reset) {
            graphManager.clearAll();
            listManager.clearAll();
            infoManager.clearAll();

            currentNumEvent = 0;
            // NOTE: No need to reset currentTime as it is according to slider

            dbAgent.getNextEventInit(0);
            tableEntry = dbAgent.getNextEvent();
        }

        // TODO: For v2.0, tableEntry != no more event, it should keep
        //       ask database for new event wherever the function is called.

        if (mode == NETWORK_MODE && tableEntry == null)
            tableEntry = dbAgent.getNextEvent();


        while (tableEntry != null &&
               ((timeBased && (tableEntry.getTime() <= time)) ||
                (!timeBased && (currentNumEvent < numEvent))) ) {

            // Pass the event into various componenet managers
            graphManager.updateVisualElements(tableEntry);
            listManager.updateListControl(tableEntry);
            infoManager.updateInfoTextPane(tableEntry);

            currentNumEvent ++;

            if (!timeBased) {   // Event Based
                // Update current time here as it won't be updated by
                //    caller function routine
                // NOTE: Not for Time Based because it is corresponding
                //         to the slider continuous value
                currentTime = tableEntry.getTime();

                // Update corresponding time field
                // TODO: Change preseting format - tungfai
                String timeText = toTimeString(currentTime, false);
                timeTextField.setText(timeText);
                timeToolbarButton.setText(timeText);
            }

            tableEntry = dbAgent.getNextEvent();
        }

        // Update Tables
        tableManager.updateTable(currentTime);

        // UPdates Routing Graph
        graphManager.updateRoutingInfo(currentTime);
    }

}
