package jplot;
/*
 * This file is part of jPlot
 *
 * jPlot is a Java version of Tim Shepard's xplot which is distributed 
 * under the M.I.T. license (as below).
 *
 * Tim Shepard's original xplot is an amazing piece of software. It was
 * designed to be extraordinarily fast and efficient and as such, it has
 * only a very thin user interface. Those design goals, however, make
 * xplot extremely difficult to port to new architectures and also make it
 * difficult to use for the casual user. jPlot was designed to address
 * these limitations while keeping as much of the original efficiency as
 * possible. We thank Tim Shepard for his hard work on xplot and hope that
 * jPlot can live up to his high standards.
 *
 * jPlot was developed by Avinash Lakhiani at the Internetworking Research
 * Lab (IRG), Ohio University, as part of Dr. Shawn Ostermann's tcptrace
 * project. The main goal behind the development of jPlot was to make the 
 * plotting tool used with tcptrace more portable. As a result, jPlot
 * retains many of the original algorithms implemented in xplot, and as per
 * the terms and conditions of the M.I.T. license, continue to remain under
 * that license. The M.I.T license is as follows:
 *
 * --- M.I.T License Begin ---
 * 
 * Copyright 1992,1993 by the Massachusetts Institute of Technology.
 *                   All rights reserved.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
 * OR WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
 * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
 * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE
 * OF THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD
 * PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
 *
 * The name of the Massachusetts Institute of Technology or M.I.T. may
 * NOT be used in advertising or publicity pertaining to distribution of
 * the software.  Title to copyright in this software and any associated
 * documentation shall at all times remain with M.I.T., and USER agrees
 * to preserve same.
 * 
 * --- M.I.T. License End ---
 * 
 * jPlot also has a lot of added features that are not part of the original
 * xplot code. Those sections of code are distributed under the following
 * BSD License:
 *
 * --- BSD License Begin ---
 *
 * Copyright (c) 2002, 2003 by Avinash Lakhiani
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *	
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution. 
 *   - Neither the name of Ohio University nor the names of its contributors
 *     may be used to endorse or promote products derived from this software
 *     without specific prior written permission. 
 *	   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * --- BSD License End ---
 * 
 * You should have received a file named "DISTINCTION" along with this
 * distribution, that clearly identifies all the algorithms that were
 * retained from the original xplot code, and remain under the M.I.T.
 * license. The rest of the code was written for jPlot, and falls under
 * the BSD license.
 * 
 * jPlot is free software; you can redistribute it and/or modify it under the
 * terms and conditions of both the above licenses.
 *
 * jPlot is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the above licenses for more details.
 *
 * Author:  Avinash Lakhiani
 *          Internetworking Research Group
 *          Ohio University
 *          Athens, OH
 *          avinash.lakhiani@ohiou.edu
 *          http://www.tcptrace.org/jPlot
 *
 */

/*
 * $Id: ApplicationFrame.java,v 1.2 2002/12/04 01:58:52 alakhian Exp $
 */ 

/* Import Packages */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

/* Class       - jPlot
 * Description - This class is the main class that provides the JFrame for plotting the
 * the graphs. It also adds the buttons and title panel.
 * Extends     - JFrame
 * Implements  - KeyListener
 */
public class ApplicationFrame extends JFrame implements KeyListener
{
   /* Declaration of member variables */
   protected jPlot parent; /* keeping a reference to the parent.
			    * (used to implement correct exit of program, when all the windows are disposed. See
			    * killJFrame()).
			    */
   
   /* Creating the main panel (which is the plotter that draws the graphs), and the buttons panel */
   DrawPlot mainPanel;
   JPanel  buttonsPanel = new JPanel();

   /* Instantiate an action listener */
   actionAdapter al = new actionAdapter();

   /* Creating layout managers to set the frame layout */
   int rows    = 1;     // rows of buttons
   int columns = 5;     // number of buttons
   BorderLayout mainPanelLayout = new BorderLayout();
   GridLayout   buttonsLayout   = new GridLayout(rows, columns);

   /* Instances of file filters to be added to the file chooser */
   PNGFileFilter    pngFilter     = new PNGFileFilter();
   A4PSFileFilter   a4psFilter    = new A4PSFileFilter();
   TEX3PSFileFilter tex3psFilter  = new TEX3PSFileFilter();
   LVSPSFileFilter  lvspsFilter   = new LVSPSFileFilter();

   /* Creating the buttons */
   JButton button1     = new JButton();
   JButton button2     = new JButton();
   JButton button3     = new JButton();
   JButton button4     = new JButton();
   JButton button5     = new JButton();

   /* Creating the Menu Bar */
   JMenuBar mbar = new JMenuBar();

   /* Creating the different menus */
   JMenu file     = new JMenu("File");
   JMenu view     = new JMenu("View");
   JMenu options  = new JMenu("Options");
   JMenu help     = new JMenu("Help");
   JMenu colors   = new JMenu("Colors");
      
   /* Creating items within each menu */
   JMenuItem saveAs         = new JMenuItem("Save As..."           , KeyEvent.VK_S);
   JMenuItem close          = new JMenuItem("Close"                , KeyEvent.VK_C);
   JMenuItem exit           = new JMenuItem("Exit"                 , KeyEvent.VK_X);
   JMenuItem refresh        = new JMenuItem("Refresh"              , KeyEvent.VK_R);
   JMenuItem resync         = new JMenuItem("Resync"               , KeyEvent.VK_S);
   JMenuItem whiteOnBlack   = new JMenuItem("White On Black"       , KeyEvent.VK_W);
   JMenuItem blackOnWhite   = new JMenuItem("Black On White"       , KeyEvent.VK_B);
   JMenuItem blackOnGray    = new JMenuItem("Black On Gray"        , KeyEvent.VK_G);
   JMenuItem contents       = new JMenuItem("Contents"             , KeyEvent.VK_C);
   JMenuItem about          = new JMenuItem("About"                , KeyEvent.VK_A);
   
   /* Help Menu */
   HelpMenu helpMenu = null;

   /* About Box */
   AboutBox aboutBox = null;
   
   /* Creating the file chooser */
   JFileChooser fc = new JFileChooser(".");

   /* Method      - default constructor
    * Parameters  - NULL
    * Returns     - NULL
    * Description - called by default when the class is instantiated.
    */
   public ApplicationFrame()
     {
	
     }
   
   /* Method      - constructor
    * Parameters  - NULL
    * Returns     - NULL
    * Description - called when the class is instantiated.
    */
   public ApplicationFrame(String file, jPlot parent)
     {
	try
	  {
	     this.parent = parent;                   // Maintaining a reference to the parent. (Used for proper exit in the case of multiple plots)
	     mainPanel = new DrawPlot(file, this, parent.args);   // Creating the main panel with the plot of the specified file
	     jbInit();                               // This call actually creates the frame.
	     addKeyListener(this);	             // Add listener for keyboard events
	  }
	catch(Exception e)
	  {
	     e.printStackTrace();
	  }
     }
   
   /* Method      - jbInit
    * Parameters  - NULL
    * Returns     - NULL
    * Description - this method creates the frame and sets its layout.
    * It adds the buttons to it too.
    */
   private void jbInit() throws Exception
     {
	/* Setting attributes for the main panel */
	mainPanel.setLayout(mainPanelLayout);
	this.getContentPane().add(mainPanel);
	
	/* Setting attributes for the buttons' panel.
	 * Adding the buttons to the panel, and the buttons' panel
	 * to the main panel.
	 */
	buttonsPanel.setLayout(buttonsLayout);
	
	/* Set the labels for the buttons */
	button1.setText("Refresh");
	button2.setText("Original");
	button3.setText("Resync");
	button4.setText("Close");
	button5.setText("Exit");

	/* Setting the button Mnemonics */
	button1.setMnemonic(KeyEvent.VK_R);
	button2.setMnemonic(KeyEvent.VK_O);
	button3.setMnemonic(KeyEvent.VK_S);
	button4.setMnemonic(KeyEvent.VK_C);
	button5.setMnemonic(KeyEvent.VK_X);

	/* Adding action listeners to the buttons */
	button1.addActionListener(al);
	button2.addActionListener(al);
	button3.addActionListener(al);
	button4.addActionListener(al);
	button5.addActionListener(al);

	 /* Add the buttons */
	buttonsPanel.add(button1, null);
	buttonsPanel.add(button2, null);
	buttonsPanel.add(button3, null);
	buttonsPanel.add(button4, null);
	buttonsPanel.add(button5, null);

	/* Add the buttons panel to the frame */
	this.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);

	/* Setting the Mnemonics for the menus */
	file.setMnemonic(KeyEvent.VK_F);
	view.setMnemonic(KeyEvent.VK_V);
	options.setMnemonic(KeyEvent.VK_O);
	help.setMnemonic(KeyEvent.VK_H);
	colors.setMnemonic(KeyEvent.VK_C);

	/* Setting Accelerators */
	refresh.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_R, java.awt.event.KeyEvent.CTRL_MASK, false));	
	resync.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_L, java.awt.event.KeyEvent.CTRL_MASK, false));
	saveAs.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_S, java.awt.event.KeyEvent.CTRL_MASK, false));
	close.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_C, java.awt.event.KeyEvent.CTRL_MASK, false));
	exit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_X, java.awt.event.KeyEvent.CTRL_MASK, false));
	contents.setAccelerator(javax.swing.KeyStroke.getKeyStroke(KeyEvent.VK_H, java.awt.event.KeyEvent.CTRL_MASK, false));
	
	/* Setting the size of the file filter (for proper display) */
	fc.setPreferredSize(new Dimension(Constant.FC_WIDTH, Constant.FC_HEIGHT));

	/* Adding the file filters to the file chooser */
	fc.addChoosableFileFilter(lvspsFilter);
	fc.addChoosableFileFilter(tex3psFilter);
	fc.addChoosableFileFilter(a4psFilter);
	fc.addChoosableFileFilter(pngFilter);

	/* Adding the action listener for the "Save As" menu */
	fc.setAcceptAllFileFilterUsed(false);
	fc.addActionListener(al);

	/* Adding the items to each menu */
	/* File menu*/
	file.add(saveAs);
	file.addSeparator();
	file.add(close);
	file.add(exit);
	/* View Menu */
	view.add(refresh);
	view.add(resync);
	/* Options menu */
	colors.add(whiteOnBlack);
	colors.add(blackOnWhite);
	colors.add(blackOnGray);
	options.add(colors);
	/* Help menu */
	help.add(contents);
	help.addSeparator();	
	help.add(about);
	
	/* Adding the menus to the menu bar */
	mbar.add(file);
	mbar.add(view);
	mbar.add(options);
	mbar.add(help);

	/* Adding actionlisteners to the items */
	saveAs.addActionListener(al);
	close.addActionListener(al);
	exit.addActionListener(al);
	
	refresh.addActionListener(al);
	resync.addActionListener(al);
	
	colors.addActionListener(al);
	whiteOnBlack.addActionListener(al);
	blackOnWhite.addActionListener(al);
	blackOnGray.addActionListener(al);

	contents.addActionListener(al);
	about.addActionListener(al);

	/* Adding the menu bar to the frame */
	this.getContentPane().add(mbar, BorderLayout.NORTH);

     } // End of jbInit()

   
   /* Method for processing actions button actions */
   public void processAction(ActionEvent ae)
     {
	String str = ae.getActionCommand();
	if(str.equals("Refresh"))
	  {
	     mainPanel.repaint();
	  }
	else if(str.equals("Original"))
	  {
	     mainPanel.getPl().setViewNo(0);
	     mainPanel.repaint();
	  }
	else if(str.equals("Resync"))
	  {
	     mainPanel.getPl().reSync();
	     mainPanel.repaint();
	  }
	else if(str.equals("Close"))
	  {
	     callKillJFrame(true);
	  }
	else if(str.equals("Exit"))
	  {
	     System.exit(1);
	  }
	else if(str.equals("Save As..."))
	  {
	     fc.showSaveDialog(this);
	  }
	else if(str.equals("Colors"))
	  {
	     /* Do nothing since it has a sub-menu */
	  }
	else if(str.equals("Contents"))
	  {
	     if(helpMenu == null)
	       {
		  helpMenu = new HelpMenu(this, "Help", true);
		  helpMenu.setLocationRelativeTo(this);
	       }
	     helpMenu.setVisible(true);
	  }
	else if(str.equals("About"))
	  {
	     if(aboutBox == null)
	       {
		  aboutBox = new AboutBox(this);
		  aboutBox.setLocationRelativeTo(this);
	       }
	     aboutBox.setVisible(true);
	  }
	else if(str.equals("ApproveSelection"))
	  {
	     String fileName         = fc.getSelectedFile().getName();
	     String currentDirectory = fc.getCurrentDirectory().getPath();
	     fileName = new String(currentDirectory + File.separatorChar + fileName);
	     
	     if(fc.getFileFilter().equals(pngFilter))
	       {
		  if(fileName.endsWith(".png") == false)
		    fileName = fileName.concat(".png");
		  mainPanel.getPl().setState(State.PRINTING);
		  mainPanel.emitPng(mainPanel.openPngFile(fileName), mainPanel.getCanvas());
		  mainPanel.getPl().setState(State.NORMAL);
	       }
	     else if(fc.getFileFilter().equals(a4psFilter))
	       {
		  if(fileName.endsWith(".a4.ps") == false)
		    fileName = fileName.concat(".a4.ps");
		  mainPanel.getPl().setState(State.PRINTING);
		  mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().getState());
		  mainPanel.getPl().setState(State.NORMAL);
	       }
	     else if(fc.getFileFilter().equals(tex3psFilter))
	       {
		  if(fileName.endsWith(".tex3.ps") == false)
		    fileName = fileName.concat(".tex3.ps");
		  mainPanel.getPl().setState(State.FIGING);
		  mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().getState());
		  mainPanel.getPl().setState(State.NORMAL);
		   }
	     else if(fc.getFileFilter().equals(lvspsFilter))
	       {
		  if(fileName.endsWith(".lvs.ps") == false)
		    fileName = fileName.concat(".lvs.ps");
		  mainPanel.getPl().setState(State.THINFIGING);
		  mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().getState());
		  mainPanel.getPl().setState(State.NORMAL);
	       }
	     else
	       System.out.println("jPlot: unknown file type specified while saving, file NOT saved");
	  }
	else if(str.equals("CancelSelection"))
	  {
	     return;
	  }
	else if(str.equals("Black On White"))
	  {
	     mainPanel.getPl().defaultColor    = Color.black;
	     mainPanel.getPl().currentColor    = Color.black;
	     mainPanel.getPl().foregroundColor = Color.black;
	     mainPanel.getPl().backgroundColor = Color.white;
	     mainPanel.whiteOnBlack = false;
	     mainPanel.repaint();
	  }
	else if(str.equals("Black On Gray"))
	  {
	     mainPanel.getPl().defaultColor    = Color.black;
	     mainPanel.getPl().currentColor    = Color.black;
	     mainPanel.getPl().foregroundColor = Color.black;
	     mainPanel.getPl().backgroundColor = Color.gray;
	     mainPanel.whiteOnBlack = false;
	     mainPanel.repaint();
	  }
	else if(str.equals("White On Black"))
	  {
	     mainPanel.getPl().defaultColor    = Color.white;
	     mainPanel.getPl().currentColor    = Color.white;
	     mainPanel.getPl().foregroundColor = Color.white;
	     mainPanel.getPl().backgroundColor = Color.black;
	     mainPanel.whiteOnBlack = true;
	     mainPanel.repaint();
	  }
	else
	  {
	     System.out.println("jPlot: {ApplicationFrame.java: processAction(ActionEvent)}: unknown event");
	     System.out.println("\tAction Returned: " + str);
	     System.exit(1);
	  }
	
     } // End of method ActionPerformed()
   
   /* Processes window events occurring on this window by dispatching
    * them to any registered WindowListener objects.
    * Basically makes sure that the process is killed when the window is
    * closed.
    */
   protected void processWindowEvent(WindowEvent e)
     {
	super.processWindowEvent(e);
	if (e.getID() == WindowEvent.WINDOW_CLOSING)
	  {
	     callKillJFrame(true);
	  }
     }
   
   /* Method      - callKillJFrame
    * Parameters  - flag indicating whether the mouse was right-clicked, or the x-button at the top
    * right corner of the window was pressed.
    * Returns     - NULL
    * Description - this method kills the jFrame. (The reason for having the implementation
    * this way is to allow the lower level classes also to call this method).
    */
   public void callKillJFrame(boolean xPressed)
     {
	if(parent.killJFrame(xPressed))
	  this.dispose();
	else
	  {
	     /* Hide the frame */
	     this.hide();
	     /* Check if this is the only frame, and if so, display it again */
	     if(parent.args.getFileCount() == 1)
	       {
		  /* Set the location back to the origin */
		  this.setLocation(0, 0);
		  /* Set the next frame's focus */
		  this.setState(Frame.NORMAL);
		  /* Show the next frame */
		  this.show();
	       }
	  }
     } // End of method killJFrame()
   
   /* Methods for keyboard events */
   /* Invoked when a key has been pressed */
   public void keyPressed(KeyEvent ke)
     {
	int key = ke.getKeyCode();
	switch(key)
	  {
	   case KeyEvent.VK_SHIFT   : mainPanel.shiftPressed   = true ; break;   // Shift key pressed
	   case KeyEvent.VK_CONTROL : mainPanel.controlPressed = true ; break;   // Control key pressed
	   case KeyEvent.VK_ALT     : mainPanel.altPressed     = true ; break;   // Alt key pressed (for future use)
	   default                  : /* Do nothing for other keys */ ; break;
	  }
	 }

   /* Invoked when a key has been released */
   public void keyReleased(KeyEvent ke)
	 {
	int key = ke.getKeyCode();
	switch(key)
	  {
	   case KeyEvent.VK_SHIFT   : mainPanel.shiftPressed   = false ; break;   // Shift key pressed
	   case KeyEvent.VK_CONTROL : mainPanel.controlPressed = false ; break;   // Control key pressed
	   case KeyEvent.VK_ALT     : mainPanel.altPressed     = false ; break;   // Alt key pressed (for future use)
	   default                  : /* Do nothing for other keys */  ; break;
	  }
	 }

   /* Invoked when a key has been typed */
   public void keyTyped(KeyEvent ke)
     {
	/* Do Nothing */
     }
   
   /* Class       - actionAdapter
    * Description - used to add a listener for action & item events
    * Extends     - NULL
    * Implements  - ActionListener
    */
   private class actionAdapter implements java.awt.event.ActionListener
     {
	public void actionPerformed(ActionEvent ae)
	  {
	     processAction(ae);
	  }
	
     } // End of private class actionAdapter

} // End of class ApplicationFrame
