/*
 * CobUI.java
 *
 * Created on April 23, 2001, 1:44 PM
 */

package cse605;

/**
 *
 * @author  adev
 * @version 
 */
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.KeyStroke;
import javax.swing.ImageIcon;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
import javax.swing.*;
import java.util.*;
import java.lang.*;
import javax.swing.text.*;
import java.awt.print.*; 
import java.awt.Window;
import javax.swing.JMenuBar;

public class CobUI extends JFrame implements ActionListener, Observer
{
    private final int EDITOR = 7121;
    private final int CODE = 8349;
    private final int HELP = 6832;
    private final int DIAGNOSE= 3934;
    private final int RESULT = -4237;
    private final int DEFAULTWIN = 9436;

    public Canvas  canvas;
    private Memento myMemento;
    //private JButton resBut;
    private JButton beamBut;    

    private JButton delBut;
    private JButton moveBut;
    private JButton backBut;
    private JButton forwardBut;
    private JButton clearAllBut;
    private JButton deselectBut;
    private JButton selectAllBut;
    private JButton printBut;
    private JButton loadBut;    
    private CanvasScrollPane rightPane;
    private JMenuBar menuBar;
    private JMenu menu;
    private JSplitPane splitPane ;
    private JPanel leftPane ;
    private JPanel canvasPane ;
    private CobCode cobCode;
    private JPanel codePane;
    private JDesktopPane desktop;
    private JInternalFrame resultWindow;
    private Color bgColor = Color.white;
    private Color codeBgColor = Color.black;
    private int display = EDITOR;
    private boolean codeOK;
    private CobUI selfRef;
    private ResultPane resultPane;
    private CodeTracer tracePane;
    private Font font = CobLib.font;
    private Document cobCodeDocument;
    private Document clprCodeDocument;
    public JMenuItem newAction, openAction, saveAction, saveAsAction, printAction, closeAction, exitAction , compileAction, runAction, bgAction, fontAction,  circuitAction, resultsAction, codeAction, diagAction, ejectAction ;
    public JMenu viewMenu;
    private File cktFile, cobFile;
    /** Creates new CobUI */
    public CobUI(String title) {
      super(title);
      selfRef = this;
      myMemento = new Memento(this);
      canvasPane = new JPanel();
      cobCode = new CobCode();
                
      addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
              System.exit(0);
          }
      });
      
        menuBar = new JMenuBar();

        setJMenuBar(menuBar);

	menu = new JMenu("File");

	newAction  =  menu.add(new AbstractAction("New"){
	    public void actionPerformed(ActionEvent evt){
                Runtime.getRuntime().gc();
                remove(splitPane);
                 myMemento.clearAll();
                 canvas = new Canvas(myMemento, bgColor, selfRef);
                 startAfresh();
                 canvas.storeCurrentState();
                 rightPane = new CanvasScrollPane( canvas );
                 canvas.setContainer(rightPane);
                 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,rightPane);

                 splitPane.setOneTouchExpandable(false);
                 setContentPane(splitPane);
                 invalidate();
                 validate();
                 repaint();
                 setVisible(true);
                 cobCode.clearAll();
		 display = EDITOR;
		 windowSwitchAction();	 
	    }
	  });

	openAction = menu.add(new AbstractAction("Open"){
	    public void actionPerformed(ActionEvent evt){
                openFile();
            }
	  });

        saveAction =  menu.add(new AbstractAction("Save"){
	    public void actionPerformed(ActionEvent evt){
                if(display==CODE) saveCobFile();
                else saveFile();
            }
	  });

        saveAsAction =  menu.add(new AbstractAction("Save As"){
	    public void actionPerformed(ActionEvent evt){
                if(display==CODE) saveAsCobFile();
                else saveAsFile();
            }
	  });

        menu.addSeparator();
	printAction = menu.add(new AbstractAction("Print"){
	    public void actionPerformed(ActionEvent evt){
               if(display == EDITOR){
                  if(canvas!=null){
                    canvas.isPrinting= true; 

                    JComponentVista vista = new JComponentVista(canvas, new PageFormat()); 
                    vista.scaleToFit(true);
                    PrinterJob pj = PrinterJob.getPrinterJob(); 
                    pj.setPageable(vista); 
                    try {
                        if (pj.printDialog()) {
                            pj.print();
                        }
                    } 
                    catch (PrinterException ex) {
                        System.out.println(ex);
                    }
                  }
                else{
	            JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE); 
    	        }
               }
               else if(display == CODE){
                if(codePane!=null){
//                    PrintText.printText(cobCode.getCode());
                    
                    
                    JComponentVista vista = new JComponentVista(codePane, new PageFormat()); 
                    vista.scaleToFit(true);
                    PrinterJob pj = PrinterJob.getPrinterJob(); 
                    pj.setPageable(vista); 
                    try {
                        if (pj.printDialog()) { 
                            pj.print();
                        }
                    }
                    catch (PrinterException ex) {
                        System.out.println(ex);
                    }

                  }
                else{
	            JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE); 
    	        }                   
               }
             }
       	  });
        menu.addSeparator();

        closeAction = menu.add(new AbstractAction("Close"){
	    public void actionPerformed(ActionEvent evt){

                 remove(splitPane);
                 myMemento.clearAll();
                 rightPane = new CanvasScrollPane();
                 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,rightPane);
                 splitPane.setOneTouchExpandable(false);
                 setContentPane(splitPane);
                 invalidate();
                 validate();
                 repaint();
                 setVisible(true);
		 display = DEFAULTWIN;
		 windowSwitchAction();
		 canvas=null;
		 cktFile = null;
		 cobFile = null;
	    }
	  });

          
          exitAction = menu.add(new AbstractAction("Exit"){
	    public void actionPerformed(ActionEvent evt){
                System.exit(0);
            }
	  });

	  
        menuBar.add(menu);

	JMenu toolMenu = new JMenu("Tools");


/*
	toolMenu.add(new AbstractAction("temp dir"){
	    public void actionPerformed(ActionEvent evt){
	    	CobLib.setTempDir();
            }
	  });

        toolMenu.addSeparator();          
*/

        compileAction = toolMenu.add(new AbstractAction("Compile"){
	    public void actionPerformed(ActionEvent evt){
//                canvas.clearSelection();
                codeOK = canvas.finalize(cobCode);
		if(codeOK) {
		  cobCodeDocument = null;
		  clprCodeDocument = null;
		  tracePane = null ;
          cobCode.clearAll();
		  CobLib.clearUp();		  
		}
            }
	  });

        runAction = toolMenu.add(new AbstractAction("Run"){
	    public void actionPerformed(ActionEvent evt){
                if(codeOK) cobCode.generateCode(canvas.adjMatrix);
                else
       	            JOptionPane.showMessageDialog(null,"Truss not compiled.","ERROR", JOptionPane.ERROR_MESSAGE); 
		if(CobLib.runCobCode(cobCode.getCode())) /*show result window*/
		{
	            displayResults();		
		}
		else displayResults(); /* delete after testing */
            }
	  });
        toolMenu.addSeparator();          

        bgAction = toolMenu.add(new AbstractAction("Background"){
	    public void actionPerformed(ActionEvent evt){
               Color newColor = JColorChooser.showDialog(CobUI.this, "Select cell color", bgColor );
               if(canvas!=null){

                   canvas.changeBgColor(bgColor);
                }
            }
	  });

        fontAction = toolMenu.add(new AbstractAction("Font"){
	    public void actionPerformed(ActionEvent evt){
	    	if( FontSelection.choose())
		{
		  if(getContentPane() == codePane){
		    remove(codePane);
		    codePane = null;
		    showCode();
		  }
	  	  else if (getContentPane() == resultPane){
		    remove(resultPane);
		    resultPane = null;
		    displayResults();
		  }
	  	  else if (getContentPane() == tracePane){
		    remove(tracePane);
		    tracePane = null;
		    trace();
		  }
		}
            }
	  });

/*
        toolMenu.add(new AbstractAction("Skin"){
	    public void actionPerformed(ActionEvent evt){
		  CobEssentials.changeLnF() ;
            }
	  });
*/	  

        menuBar.add(toolMenu);

        viewMenu = new JMenu("View");

        circuitAction = viewMenu.add(new AbstractAction("Truss"){
	    public void actionPerformed(ActionEvent evt){
                 remove(splitPane);
                 rightPane = new CanvasScrollPane( canvas );
                 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,rightPane);
                 splitPane.setOneTouchExpandable(false);
                 setContentPane(splitPane);



                 invalidate();
                 validate();
                 repaint();
                 setVisible(true);
                 display = EDITOR;
 		 windowSwitchAction();
            }
	  });
                
          resultsAction = viewMenu.add(new AbstractAction("Results"){
	      public void actionPerformed(ActionEvent evt){
                displayResults();
            }
	  });

          codeAction = viewMenu.add(new AbstractAction("Code"){
	    public void actionPerformed(ActionEvent evt){
                //canvas.storeCurrentState();
                showCode();
            }
	  });
	  
          diagAction = viewMenu.add(new AbstractAction("Diagnose"){
	    public void actionPerformed(ActionEvent evt){
                trace();
            }
	  });
	  
          ejectAction = viewMenu.add(new AbstractAction("Eject"){
	    public void actionPerformed(ActionEvent evt){
	    	if(getContentPane()==splitPane || getContentPane()==resultPane)
		{
       	            JOptionPane.showMessageDialog(null,"Cannot eject this window\nYou can only eject Code or Diagnostic window","ERROR", JOptionPane.ERROR_MESSAGE); 
		}
		else if(getContentPane()==tracePane)
		{
		    remove(tracePane);
		    setContentPane(resultPane);
                    invalidate();
                    validate();
                    repaint();
		    windowSwitchAction();

		    JFrame frame = new JFrame("Diagnose");
		    frame.setContentPane(tracePane);
		    frame.setSize((int)(getWidth()*0.66), (int)(getHeight()*0.66));
		    frame.setVisible(true);		    
 		}
		else if(getContentPane()==codePane)
		{
		    remove(codePane);
		    setContentPane(resultPane);
                    invalidate();
                    validate();
                    repaint();
		    windowSwitchAction();
		    
		    JFrame frame = new JFrame("Code");
		    frame.setContentPane(codePane);
		    frame.setSize((int)(getWidth()*0.66), (int)(getHeight()*0.66));
		    frame.setVisible(true);
		    
		}
            }
	  });

	  

        menuBar.add(viewMenu);

        JMenu helpMenu = new JMenu("Help");

	JMenu aboutMenu = new JMenu("About");
	aboutMenu.add(new AbstractAction("Truss System"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.TOOL);
            }
	  });
	  
	aboutMenu.add(new AbstractAction("Authors"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.AUTHOR);
            }
	  });


  	helpMenu.add(aboutMenu);


	JMenu contentsMenu = new JMenu("Contents");
	contentsMenu.add(new AbstractAction("Drawing Truss"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.DRAW);
            }
	  });
	contentsMenu.add(new AbstractAction("Putting Constraints"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.CONSTRAINTS);
            }
	  });
	  
	contentsMenu.add(new AbstractAction("Running Code"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.RUN);
            }
	  });

	contentsMenu.add(new AbstractAction("Debugging"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.DEBUG);
            }
	  });

	contentsMenu.add(new AbstractAction("Saving truss/code"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.SAVE);
            }
	  });

	contentsMenu.add(new AbstractAction("Loading truss"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.LOAD);
            }
	  });



  	helpMenu.add(contentsMenu);


	helpMenu.add(new AbstractAction("Troubleshooting"){
	    public void actionPerformed(ActionEvent evt){
	    	CobHelp.showHelp(CobHelp.TROUBLE);
            }
	  });

        menuBar.add(helpMenu);
        
        
//      canvas = new Canvas(myMemento);
      rightPane = new CanvasScrollPane();
      leftPane = new JPanel();
      leftPane.setLayout(new GridLayout(8,1));

      
/*
      
//      resBut = new JButton("Resistor");
      resBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "resistor_but.gif"), "Creates a Resistor at the mouse click position"));

      resBut.setRolloverEnabled(true);
      resBut.setBorderPainted(true);
      resBut.setToolTipText("Resistor");
      resBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.task = Canvas.CREATE_RESISTOR;
		unselectButtons();
		resBut.setSelected(true);
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE); 
    	    }
	}
      });
      
      
*/


      beamBut = new JButton( new
      ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "beam_but.gif"),
      "Creates a Beam at the mouse click position"));

      beamBut.setRolloverEnabled(true);
      beamBut.setBorderPainted(true);
      beamBut.setToolTipText("Beam");
      beamBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                canvas.task = Canvas.CREATE_BEAM;
		unselectButtons();
		beamBut.setSelected(true);
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE); 
    	    }
	}
      }); 
      

/*
      loadBut = new JButton( new
      ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "beam_but.gif"),
      "Creates a Load at the mouse click position"));

      loadBut.setRolloverEnabled(true);
      loadBut.setBorderPainted(true);
      loadBut.setToolTipText("Beam");
      loadBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                canvas.task = Canvas.CREATE_LOAD;
		unselectButtons();
		loadBut.setSelected(true);
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE); 
    	    }
	}
      }); 

*/
            
//      clearAllBut = new JButton("Clear All");
      clearAllBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "clearall_but.jpg"), "Clears the Canvas"));

      clearAllBut.setToolTipText("Clear All");
      clearAllBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                canvas.clearAll();
                canvas.storeCurrentState();
                cobCode.clearAll();
            }
            else{
                 myMemento.clearAll();
                 canvas = new Canvas(myMemento, bgColor, selfRef);
                 startAfresh();
                 canvas.storeCurrentState();
                 rightPane = new CanvasScrollPane( canvas );
                 canvas.setContainer(rightPane);
                 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane,rightPane);

                 splitPane.setOneTouchExpandable(false);
                 setContentPane(splitPane);
                 invalidate();
                 validate();
                 repaint();
                 setVisible(true);
                 cobCode.clearAll();
		 display = EDITOR;
		 windowSwitchAction();

//	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);

    	    }
	}
      });

//      deselectBut = new JButton("Deselect All");
      deselectBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "deselectall_but.gif"), "Deselects the selected part"));

      deselectBut.setToolTipText("Deselect All");
      deselectBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.clearSelection();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

//      selectAllBut = new JButton("Select All");
      selectAllBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "selectall_but.gif"), "Selects all the components on Canvas"));

      selectAllBut.setToolTipText("Select All");
        selectAllBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                canvas.selectAll();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });


/*

//      wireBut = new JButton("Wire");
      wireBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "wire_but.gif"), "Joins the two selected nodes"));

      wireBut.setToolTipText("Wire");
      wireBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.task = Canvas.CREATE_WIRE;
                canvas.testDrawWire();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

//      batBut = new JButton("Battery");
      batBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "battery_but.gif"), "Creates a Source of voltage at the mouse click position"));

      batBut.setToolTipText("Battery");
      batBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.task = Canvas.CREATE_BATTERY;
		unselectButtons();
		batBut.setSelected(true);
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

*/

//      moveBut = new JButton("Move");
      moveBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH+ "move_but.gif"), "moves the selected components to the mouse click position"));

      moveBut.setToolTipText("Move selected components");
      moveBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.task = Canvas.MOVE;
		unselectButtons();
		moveBut.setSelected(true);
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

//      delBut = new JButton("Delete");
      delBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "delete_but.gif"), "Deletes the selected components"));

      delBut.setToolTipText("Delete Selected Component");
      delBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                //canvas.storeCurrentState();
                canvas.delete();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

      //      backBut = new JButton("Go Back");
//      backBut = new JButton("Go Back");
      backBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH+ "undo_but.gif"), "Go Back"));

      backBut.setToolTipText("Go Back");
      backBut.setEnabled(false);
      backBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
//                if(!myMemento.isForwardable()) canvas.saveCurrentState();
                canvas.isPrinting = false;
                canvas.retrievePrevState();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });

//      forwardBut = new JButton("Go Forward");
//      forwardBut = new JButton("Go Forward");
      forwardBut = new JButton( new ImageIcon(CobUI.class.getResource(CobLib.IMAGE_PATH + "redo_but.gif"), "Go Back"));

      forwardBut.setToolTipText("Go Forward");
      forwardBut.setEnabled(false);
      forwardBut.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
            if(canvas!=null){
                canvas.isPrinting = false;
                canvas.retrieveNextState();
            }
            else{
	        JOptionPane.showMessageDialog(null,"Open a canvas to draw the drawing.","ERROR", JOptionPane.ERROR_MESSAGE);
    	    }
	}
      });
      leftPane.add(clearAllBut);
//      leftPane.add(resBut);
      leftPane.add(beamBut);
//      leftPane.add(loadBut);
//      leftPane.add(wireBut);
      leftPane.add(moveBut);
      leftPane.add(delBut);
      leftPane.add(deselectBut);
      leftPane.add(selectAllBut);
      leftPane.add(backBut);
      leftPane.add(forwardBut);

//      canvasPane.add(rightPane);
      splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane, rightPane);
      splitPane.setOneTouchExpandable(false);

      display = DEFAULTWIN;
      windowSwitchAction();

      setContentPane(splitPane);
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args)
    {
    	if(args.length != 1)
	{
	   System.out.println("*Error* : Specify the full path of the config file \"cob.cfg\"");
	   System.exit(0);
	}
	CobLib.setPaths(null, args[0]);
        try{
          JFrame frame = new CobUI("COB Code Generator");
	  frame.setIconImage(Toolkit.getDefaultToolkit().getImage(CobUI.class.getResource(CobLib.IMAGE_PATH+ "Circuitry_icon2.jpg")));
	  frame.setSize(600,400);
	  frame.setVisible(true);

	}
	catch(Exception exp)
	{
    	  /* make the log entry */
	  CobLib.writeLog(exp.toString());
	     
	}
    }


    public void actionPerformed(java.awt.event.ActionEvent p1) {
    }
    
    
    public void update(java.util.Observable p1,java.lang.Object p2) {
//        System.out.println("Getting notifoication");
        backBut.setEnabled(myMemento.isBackable());
        forwardBut.setEnabled(myMemento.isForwardable());
    }
    
        
     public void openFile() {
      JFileChooser fileDialog = new JFileChooser(".");
      fileDialog.setFileFilter(new DrawingFilter());
      int result = fileDialog.showOpenDialog(this);
      if ( result == JFileChooser.APPROVE_OPTION ) {

	 cktFile = fileDialog.getSelectedFile() ;
	 cobFile = null;
	 
	 try {
	    ObjectInputStream input = new ObjectInputStream(new
		  FileInputStream(cktFile));
            
//	    Canvas newCanvas = (Canvas) input.readObject();
            LinkedList newList = (LinkedList) input.readObject();

            input.close();
	    if ( canvas != null ) {//remove existing canvas
                 remove(splitPane);
                 myMemento.clearAll();
//                 canvas.adjMatrix = new LinkedList();
                 canvas.storeCurrentState();                 
                 canvas.replaceAdjMatrix( newList );
            }
            else{
                 myMemento.clearAll();
                 canvas = new Canvas(myMemento, bgColor, this);
                 startAfresh();
                 canvas.storeCurrentState();
                 canvas.replaceAdjMatrix( newList );
//                 canvas.adjMatrix = newList ;
            }
            rightPane = new CanvasScrollPane( canvas );
            splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane, rightPane);

            splitPane.setOneTouchExpandable(false);
            setContentPane(splitPane);
            invalidate();
            validate();
	    repaint();
	    display = EDITOR;
	    windowSwitchAction();	 
	 } catch (FileNotFoundException fne) {
	    JOptionPane.showMessageDialog(this, "Couldn't find file: "
					  + fne.getMessage(), 
					  "Open Error", 
					  JOptionPane.ERROR_MESSAGE);
	 } catch (Exception exp) {
	    JOptionPane.showMessageDialog(this, "Read error: " + 
					  exp.getMessage(), 
					  "Open Error", 
					  JOptionPane.ERROR_MESSAGE);
	    
	 }
      } // end of if ()
   }

   public void unselectButtons()
   {
   
   	beamBut.setSelected(false);
// 	loadBut.setSelected(false);
	delBut.setSelected(false);
	moveBut.setSelected(false);
	backBut.setSelected(false);
	forwardBut.setSelected(false);
	clearAllBut.setSelected(false);
	deselectBut.setSelected(false);
	selectAllBut.setSelected(false);
   }
   
   private void enable(JMenuItem item)
   {
   	item.setEnabled(true);
   }
   private void disable(JMenuItem item)
   {
   	item.setEnabled(false);
   }
   
   private void windowSwitchAction()
   {
   	switch(display){
	case EDITOR:
		enable(newAction);
		enable(openAction);
		enable(saveAction);
		enable(saveAsAction);
		enable(printAction);
		enable(closeAction);
		enable(exitAction);
		enable(compileAction);
		enable(runAction);
		enable(bgAction);
		disable(fontAction);
		enable(viewMenu);
		enable(circuitAction);
		enable(resultsAction);
		enable(codeAction);
		enable(diagAction);
		break;

	case DEFAULTWIN:
		disable(circuitAction);
		disable(resultsAction);
		disable(codeAction);
		disable(diagAction);
		disable(fontAction);
		disable(closeAction);
		disable(saveAction);
		disable(saveAsAction);
		disable(printAction);
		disable(compileAction);
		disable(runAction);
		break;
			
	case CODE:
		disable(bgAction);
		enable(fontAction);		
		enable(saveAction);
		enable(saveAsAction);
		enable(printAction);
		disable(compileAction);
		disable(runAction);
		break;
		
	case DIAGNOSE:
		disable(bgAction);
		
	case RESULT:
	default:
		enable(fontAction);		
		disable(saveAction);
		disable(saveAsAction);
		disable(printAction);
		disable(compileAction);
		disable(runAction);
	}
   }
   
   public void saveFile() {
      if( cktFile!=null && cktFile.exists() )
      {    
         try {
          ObjectOutputStream output = new ObjectOutputStream(new
		  FileOutputStream(cktFile)); 
	    output.writeObject(canvas.adjMatrix);
	    output.close();
	 } 
	 catch (Exception exp) {
	    JOptionPane.showMessageDialog(this, "Write error: " + 
					  exp.getMessage(), 
					  "Save Error", 
					  JOptionPane.ERROR_MESSAGE);
	 }
      } // end of if ()
      else saveAsFile() ;      
   }

   public void saveAsFile() {
      JFileChooser fileDialog = new JFileChooser(".");
      fileDialog.setFileFilter(new DrawingFilter());
      int result = fileDialog.showSaveDialog(this);
      if ( result == JFileChooser.APPROVE_OPTION ) {
	 try {
	    String filename = fileDialog.getSelectedFile().getName();
	    if ( !filename.endsWith(".trs") ) {
	       filename = filename + ".trs";
	    } // end of if ()

	    cktFile = new File(filename) ;
	    ObjectOutputStream output = new ObjectOutputStream(new
		  			FileOutputStream(cktFile)); 
	    output.writeObject(canvas.adjMatrix);
	    output.close();
	 } catch (Exception exp) {
	    JOptionPane.showMessageDialog(this, "Write error: " + 
					  exp.getMessage(), 
					  "Save Error", 
					  JOptionPane.ERROR_MESSAGE);
	    exp.printStackTrace();
	 }
      } // end of if ()
   }

   public void saveCobFile() {

      if( cobFile!=null && cobFile.exists() )
      {
	 try{
	    BufferedWriter output = new 
	       BufferedWriter(new OutputStreamWriter(
	       		      new FileOutputStream(cobFile))); 
	    output.write(cobCode.getCode());
	    output.close();
	 }
	 catch (Exception exp) {
	    JOptionPane.showMessageDialog(this, "Write error: " + 
					  exp.getMessage(), 
					  "Save Error", 
					  JOptionPane.ERROR_MESSAGE);
	 }
      } // end of if ()
      else saveAsCobFile();
   }

   public void saveAsCobFile() {
      JFileChooser fileDialog = new JFileChooser(".");
      fileDialog.setFileFilter(new CobFilter());
      int result = fileDialog.showSaveDialog(this);
      if ( result == JFileChooser.APPROVE_OPTION ) {
	 try {
	    String filename = fileDialog.getSelectedFile().getName();
	    if ( !filename.endsWith(".cob") ) {
	       filename = filename + ".cob";
	    } // end of if ()

	    cobFile = new File(filename) ;	    
	    BufferedWriter output = new BufferedWriter( 
	                            new OutputStreamWriter(new
	       			    FileOutputStream(cobFile))); 
	    output.write(cobCode.getCode());
	    output.close();
	 } catch (Exception exp) {
	    JOptionPane.showMessageDialog(this, "Write error: " + 
					  exp.getMessage(), 
					  "Save Error", 
					  JOptionPane.ERROR_MESSAGE);
	    exp.printStackTrace();
	 }
      } // end of if ()
   }


   private void displayResults()
   {
       if(getContentPane() != resultPane || resultPane == null){
          resultPane = new ResultPane(this);
          remove(splitPane);
          setContentPane(resultPane);
          invalidate();
          validate();
          repaint();
          setVisible(true);
	  display = RESULT;
	  windowSwitchAction();
	}
   }
   
   private void trace()
   {
       if(getContentPane() != tracePane || tracePane==null ) //create a new CodeTracer instance
       	   tracePane = new CodeTracer(CobLib.getPrologOutput(), CobLib.getClprOutput());

       Container c = getContentPane() ;
       if( c != tracePane ){
       	   remove(c);
       	   setContentPane(tracePane);
           invalidate();
           validate();
           repaint();
           setVisible(true);
      	   display = DIAGNOSE;
	   windowSwitchAction();
	}
   }
	
   
   private JPanel getCobCodePane()
   {
       JTextPane codeTextPane = new JTextPane();
       codeTextPane.setEditable(false);
       codeTextPane.setBackground(codeBgColor);
       font = CobLib.font;
       if(cobCodeDocument==null)
       {
           cobCodeDocument = codeTextPane.getDocument();
           try {
              int len = cobCodeDocument.getLength();
              cobCodeDocument.remove(0,len);
           }
 	   catch (BadLocationException ble) {
//              System.err.println("Couldn't insert initial text.");
           }
           String showText = cobCode.getCode() ;

	   StringTokenizer st = new StringTokenizer(showText, " \t\n,;:()[]{}<>=+-*/%$", true);
	   while(st.hasMoreTokens())
	   {
	     String word = st.nextToken();
	     Color textColor = getTextColor(word);
             MutableAttributeSet attr = new SimpleAttributeSet();
             StyleConstants.setForeground(attr, textColor);
             StyleConstants.setFontFamily (attr, font.getFamily());
	     StyleConstants.setFontSize (attr, font.getSize());
	     StyleConstants.setBold (attr, font.isBold());
	     StyleConstants.setItalic (attr, font.isItalic());
             codeTextPane.setCharacterAttributes(attr, false); 

	     try{
               cobCodeDocument.insertString(cobCodeDocument.getLength(), word, attr );
             }
             catch (BadLocationException ble) {
             }
	   }
       }
       else codeTextPane.setDocument(cobCodeDocument);
       
       JPanel pane = new JPanel();
       pane.setLayout( new BorderLayout() );
       pane.add( new JLabel("COB CODE"), BorderLayout.NORTH );
       pane.add( new CanvasScrollPane( codeTextPane ), BorderLayout.CENTER);
       pane.setSize( (int)(getSize().width/2), getSize().height);
       return pane;
   }

   private JPanel getClprCodePane()
   {
       JTextPane codeTextPane = new JTextPane();
       codeTextPane.setEditable(false);
       codeTextPane.setBackground(codeBgColor);
       font = CobLib.font;
       if(clprCodeDocument==null)
       {
           clprCodeDocument = codeTextPane.getDocument();
           try {
              int len = clprCodeDocument.getLength();
              clprCodeDocument.remove(0,len);
           }
 	   catch (BadLocationException ble) {
           }
           String showText = CobLib.getClprCode() ;

	   StringTokenizer st = new StringTokenizer(showText, " \t\n,;:()[]{}<>=+-*/%$", true);
	   while(st.hasMoreTokens())
	   {
	     String word = st.nextToken();
	     Color textColor = getTextColor(word);
             MutableAttributeSet attr = new SimpleAttributeSet();
             StyleConstants.setForeground(attr, textColor);
             StyleConstants.setFontFamily (attr, font.getFamily());
	     StyleConstants.setFontSize (attr, font.getSize());
	     StyleConstants.setBold (attr, font.isBold());
	     StyleConstants.setItalic (attr, font.isItalic());
             codeTextPane.setCharacterAttributes(attr, false); 

	     try{
               clprCodeDocument.insertString(clprCodeDocument.getLength(), word, attr );
             }
             catch (BadLocationException ble) {
             }
	   }
       }
       else codeTextPane.setDocument(clprCodeDocument);
       
       JPanel pane = new JPanel();
       pane.setLayout( new BorderLayout() );
       pane.add( new JLabel("CLP(R) CODE"), BorderLayout.NORTH );
       pane.add( new CanvasScrollPane( codeTextPane ), BorderLayout.CENTER);
       pane.setSize( (int)(getSize().width/2), getSize().height);
       return pane;
   }

   private void showCode()
   {
       if(getContentPane() != codePane || codePane == null){
       	cobCodeDocument=null;
       	clprCodeDocument=null;
      	codePane = new JPanel();
	codePane.setLayout( new GridLayout(1,2) ); 
//       	codePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
//       	codePane.setDividerLocation( (int)(getWidth()/2) );
//       	codePane.setLeftComponent( getCobCodePane() );
//       	codePane.setRightComponent( getClprCodePane() );
       	codePane.add( getCobCodePane() );
       	codePane.add( getClprCodePane());
       	setContentPane(codePane);
       	invalidate();
       	validate();
       	repaint();
       	setVisible(true);
       	display = CODE ;
       	windowSwitchAction();
       }
   }

   /**
   *  returns the color for the text specified by parameter str
   */
   private Color getTextColor(String str)
   {
   	if(str.equals("class")) return Color.orange;
	else if (str.equals("constraints")) return Color.cyan;
	else if (str.equals("attributes")) return Color.cyan;
	else if (str.equals("constructors")) return Color.cyan;
	else if (str.equals("{")) return new Color(203,255,152);
	else if (str.equals("[")) return new Color(203,255,152);
	else if (str.equals("]")) return new Color(203,255,152);
	else if (str.equals("(")) return new Color(203,255,152);		
	else if (str.equals(")")) return new Color(203,255,152);		
	else if (str.equals(",")) return new Color(203,255,152);		
	else if (str.equals(";")) return new Color(203,255,152);		
	else if (str.equals(":")) return new Color(203,255,152);		
	else if (str.equals("=")) return new Color(255,255,185);		
	else if (str.equals("+")) return new Color(255,255,185);		
	else if (str.equals("-")) return new Color(255,255,185);		
	else if (str.equals("*")) return new Color(255,255,185);		
	else if (str.equals("/")) return new Color(255,255,185);		
	else if (str.equals("sum")) return new Color(255,162,255);		
	else if (str.equals("in")) return new Color(255,162,255);
	else if (str.equals("Real")) return new Color(255,162,255);		
	else if (str.equals("real")) return new Color(255,162,255);
	else if (str.equals("$")) return Color.yellow;
	else if (str.equals("new")) return new Color(255,162,255);
	else if (str.equals("node")) return new Color(0, 238,51);
	else if (str.equals("resistor")) return new Color(0, 238,51);
	else if (str.equals("wire")) return new Color(0, 238,51);
	else if (str.equals("beam")) return new Color(0, 238,51);
			
	else return Color.white;
   }

    private void startAfresh(){
        Node.count = 0;
        Beam.count = 0;
        //Resistor.count = 0;
        //Wire.count = 0;
        //Battery.count = 0;
    }

    private void displayHelp()    
    {
        display = HELP;
        HelpPanel pane = new HelpPanel();
        Document doc = pane.getDocument();
        try {
          int len = doc.getLength();
          doc.remove(0,len);
        }
        catch (BadLocationException ble) {
//          System.err.println("Couldn't insert initial text.");
        }
        String showText = "";
        for(int i=0;i<103;i++) showText += "\n";
        try{
           doc.insertString(doc.getLength(), showText, pane.getStyle("bold"));
        }
        catch (BadLocationException ble) {
//           System.err.println("Couldn't insert initial text.");
        }
        
        JScrollPane _rightPane = new javax.swing.JScrollPane( pane );
//        _rightPane.setSize(100,200);
        JFrame frame = new JFrame("Truss System Help");
        frame.setContentPane(_rightPane);
        frame.setLocation(500,20);
        frame.setSize(300,500);
        frame.setVisible(true);
    }
    
    private void removeEnableButtons()
    {
//	resBut.setEnabled(true);
	beamBut.setEnabled(true);	
//	loadBut.setEnabled(true);
//	wireBut.setEnabled(true);
	delBut.setEnabled(true);
	moveBut.setEnabled(true);
	clearAllBut.setEnabled(true);
	deselectBut.setEnabled(false);
	selectAllBut.setEnabled(false);
    }
    
    private void removeDisableButtons()
    {
//	resBut.setEnabled(false);
	beamBut.setEnabled(false);	
//	loadBut.setEnabled(false);
//	wireBut.setEnabled(false);
	delBut.setEnabled(false);
	moveBut.setEnabled(false);
	backBut.setEnabled(false);
	forwardBut.setEnabled(false);
	clearAllBut.setEnabled(false);
	deselectBut.setEnabled(false);
	selectAllBut.setEnabled(false);
    }
    
    
}

class HelpPanel extends JTextPane
{
    String filename = CobLib.IMAGE_PATH + "help_txt.jpg";
    Image pic = Toolkit.getDefaultToolkit().getImage(filename);
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(pic, 0, 0, this);        
    }
}

class CanvasScrollPane extends JScrollPane
{
    Canvas canvas;
    int count = 0;
    public CanvasScrollPane(){
    	super();
    }
    
    public CanvasScrollPane(Canvas childPane){
        super(childPane);
        canvas = childPane ;
    }
    
    public CanvasScrollPane(JPanel childPane){
        super(childPane);
    }

    public CanvasScrollPane(JTextPane childPane){
        super(childPane);
    }
    
   public void paintComponent(Graphics g) {
//      super.paintComponent(g);
       if(canvas!=null){ 
//          System.out.println("--------------------- "+ (count++) +" ----------------------");
          Rectangle canvasRect = new Rectangle( getWidth(), getHeight()) ;
          canvas.modifyArea();
          canvas.scrollRectToVisible( canvasRect );
          canvas.setPreferredSize(canvas.area.getSize());
          revalidate();
       }
      actualPaintComponent(g);
   } // end paint

   public void actualPaintComponent(Graphics g) {
       super.paintComponent(g);
   }
    
    
}
