/*/*
 * ClassLab.java		Jonathan Kallay 8/13/99
 * (c) 1999 Williams College
 */
import java.awt.*;
import java.awt.event.*;
import objectdraw.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
 /** 
 *  A program for exploring the objectdraw package.  A drawing window 
 * is displayed along with an interface for adding and manipulating
 * objects in the drawing window.
 *
 * @author Jonathan Kallay
 * @version 1.0 last update 8/25/99 <P>
 * NEWEST VERSION 2.0
 * Modified to check for cancel buttons and do nothing.  Barbara Lerner  9/00
 * Updated to remove getBounds setBounds sendToFront and sendToBack buttons
 * Replaced them with getHeight, getWidth, setHeight, setWidth.
 */
public class ClassLab extends JFrame implements ActionListener, Observer
{
	// The singleton class lab object
	static ClassLab lab;
	
	// The DrawingCanvas where objects are displayed.
	SelectionCanvas canvas;
	
	
	// TextArea for output.
	JTextArea output;
	
	/*
	 * Method buttons.
	 */
	JButton get_Color;
	JButton set_Color;
	JButton hide;
	JButton show;
	JButton get_Location;
	JButton set_Bounds;
	JButton get_Height;
	JButton get_Width;
	JButton move;
	JButton move_To;
	JButton send_Backward;
	JButton send_Forward;
	JButton get_Start;
	JButton get_End;
	JButton set_Height;
	JButton set_Width;	
	JButton set_EndPts;	
	
	
	/*
	 * Dialogs.
	 */
	ColorDialog color_dialog;
	
	// constants defining the different looks and feels
	private static final int METAL = 0;
    private static final int MAC_OS = 1;
    private static final int MOTIF = 2;
    private static final int WINDOWS = 3;
    
    private UIManager.LookAndFeelInfo[] info;

	
	/**
	 * Initializes the applet by laying out the components.
	 */
	public ClassLab() {
		super("Class Lab");
		
		//set the layout manager
		getContentPane().setLayout(new BorderLayout());

		/*
		 * Makes the Frame resizable
		 */
		this.setResizable(true);		
		
		
		// set the initial look and feel
 		info = UIManager.getInstalledLookAndFeels();        
		try
		{
	    	UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Exception e)
		{
		}

		/*
		 * Create the menu.
		 */
		JMenuBar menubar=new JMenuBar();
		JMenu menu_file=new JMenu("File");
		JMenuItem menu_file_save=new JMenuItem("Save");
		JMenuItem menu_file_load=new JMenuItem("Load");		
		JMenuItem menu_file_quit=new JMenuItem("Quit");
		menu_file.add(menu_file_save);
		menu_file.add(menu_file_load);
		menu_file.addSeparator();
		menu_file.add(menu_file_quit);
		menubar.add(menu_file);
		
		// create the PLAF menu and generate the menu items
		JMenu menu_plaf = new JMenu("Look and Feel");

		JMenuItem temp;
		for(int i = 0; i < info.length; i++)
		{
			temp = new JMenuItem(info[i].getName());
			menu_plaf.add(temp);
			temp.addActionListener(this);
		}

		menubar.add(menu_plaf);
		setJMenuBar(menubar);
		
		menu_file_save.addActionListener(this);
	 	menu_file_load.addActionListener(this);
		menu_file_quit.addActionListener(this);

		/*
		 * create the panels
		 */
		JPanel display_panel = new JPanel();
			display_panel.setLayout(new BorderLayout() );
		JPanel output_panel = new JPanel();
			output_panel.setLayout(new BorderLayout() );
		JPanel canvas_panel = new JPanel();
			canvas_panel.setLayout( new BorderLayout() );
		JPanel panel_buttons=new JPanel();
   			panel_buttons.setLayout(new GridLayout(2,8));
   		JPanel control_panel = new JPanel();
   			control_panel.setLayout(new BorderLayout() );
		JPanel panel_mousepos=new JPanel();

		/*
		 * Create the output text area.
		 */
		output=new JTextArea(22,24);
		output.setEditable(false);
		output.setLineWrap(true); //p. applegate
                
                JScrollPane scrollPane = new JScrollPane(output);
		
		output_panel.add(new JLabel("Output",JLabel.CENTER),"North");
		output_panel.add( scrollPane, "Center");
		
		display_panel.add(output_panel,"West");

		
		//create the canvas
		canvas=new SelectionCanvas(this);
		canvas_panel.add(new JLabel("Drawing Window", JLabel.CENTER),"North");
		canvas_panel.add( canvas, "Center");
		
		display_panel.add(canvas_panel,"Center");
		
		getContentPane().add( display_panel, "Center");

		
		/*
		 * Create the buttons
		 */
		get_Color=new JButton("getColor()");
		set_Color=new JButton("setColor(...)");
		hide=new JButton("hide()");
		show=new JButton("show()");
		get_Location=new JButton("getLocation()");
		get_Height = new JButton("getHeight()");
		get_Width = new JButton("getWidth()");
		move=new JButton("move(...)");
		move_To=new JButton("moveTo(...)");
		send_Backward=new JButton("sendBackward()");
		send_Forward=new JButton("sendForward()");
		get_Start=new JButton("getStart()");
		get_End=new JButton("getEnd()");
		set_Height = new JButton("setHeight(...)");
		set_Width = new JButton("setWidth(...)");
		set_EndPts = new JButton("setEndPoints(...)");
	

		MyJLabel label_mousex=new MyJLabel("x: 100");
		MyJLabel label_mousey=new MyJLabel("y: 100");


		//Create the mouse position tracker.
		MousePosTracker mpt=new MousePosTracker(label_mousex, label_mousey);
		
		/*
		 * Create the dialogs.
		 */
		color_dialog=new ColorDialog(this,true);
		
		/*
		 * Set up the event listeners.
		 */
		canvas.addMouseMotionListener(mpt);
		
		
		get_Color.addActionListener(this);
		set_Color.addActionListener(this);
		hide.addActionListener(this);
		show.addActionListener(this);
		get_Location.addActionListener(this);
//		set_Bounds.addActionListener(this);
		get_Height.addActionListener(this);
		get_Width.addActionListener(this);
		move.addActionListener(this);
		move_To.addActionListener(this);
		send_Backward.addActionListener(this);
		send_Forward.addActionListener(this);
		get_Start.addActionListener(this);
		get_End.addActionListener(this);
		set_Height.addActionListener(this);
		set_Width.addActionListener(this);
		set_EndPts.addActionListener(this);
		
		
		
		/*
		 * Adds the mouse position tracking.
		 */
		panel_mousepos.add(label_mousex);
		panel_mousepos.add(label_mousey);
		
		/*
		 * Adds the method buttons.
		 */
		panel_buttons.add(move);
		panel_buttons.add(hide);
		panel_buttons.add(send_Backward);
		panel_buttons.add(get_Color);
		panel_buttons.add(get_Width);
		panel_buttons.add(get_Height);
		panel_buttons.add(get_Start);
		panel_buttons.add(get_Location);
		
		panel_buttons.add(move_To);
		panel_buttons.add(show);
		panel_buttons.add(send_Forward);
		panel_buttons.add(set_Color);
		panel_buttons.add(set_Width);
		panel_buttons.add(set_Height);
		panel_buttons.add(get_End);
		panel_buttons.add(set_EndPts);
		
		ConstructorPanel panel_construct = new ConstructorPanel(canvas);
			
		control_panel.add(panel_mousepos, "North");
		control_panel.add(panel_construct, "Center");
		control_panel.add(panel_buttons, "South");
		
		getContentPane().add(control_panel, "South");
		
		pack();
	}

	
	/**
	 * Invoked when a button or menu item has been used.
	 */
	public void actionPerformed(ActionEvent e){
		String command=e.getActionCommand();
		DrawableInterface selected=canvas.getSelected();
			
		if(command.equals("Load"))
		{
		    this.loadFile();
		}
		if(command.equals("Save"))
		{
	 	    this.saveFile();
		}		
		if(command.equals ("Quit")){
			System.exit(0);
		}


		for (int j = 0; j < info.length; j++)
		{
			if (command.equals(info[j].getName()))
			{
				try
				{
					UIManager.setLookAndFeel(info[j].getClassName());
	    			SwingUtilities.updateComponentTreeUI(ClassLab.this);
	  	    		ClassLab.this.pack();
				}
				catch (ClassNotFoundException excep) {
					new ErrorDialog(this, "Couldn't find class for specified look and feel:" + info[j].getName(), true);         
            	} catch (UnsupportedLookAndFeelException excep) {
                	new ErrorDialog(this, "Can't use the specified look and feel (" + info[j].getName() + ") on this platform.", true);                	
            	} catch (Exception excep) {
                	new ErrorDialog(this, "Couldn't get specified look and feel (" + info[j].getName() + "), for some reason.", true);
                }
			}
		}		

		if(selected!=null){
			if(command.equals("getColor()")){
				Color color=selected.getColor();
				if(color.equals(Color.black)){
					output.append("Color.black"+"\n");
				}else if(color.equals(Color.black)){
					output.append("Color.black"+"\n");
				}else if(color.equals(Color.darkGray)){
					output.append("Color.darkGray"+"\n");
				}else if(color.equals(Color.gray)){
					output.append("Color.gray"+"\n");
				}else if(color.equals(Color.lightGray)){
					output.append("Color.lightGray"+"\n");
				}else if(color.equals(Color.cyan)){
					output.append("Color.cyan"+"\n");
				}else if(color.equals(Color.magenta)){
					output.append("Color.magenta"+"\n");
				}else if(color.equals(Color.pink)){
					output.append("Color.pink"+"\n");
				}else if(color.equals(Color.green)){
					output.append("Color.green"+"\n");
				}else if(color.equals(Color.orange)){
					output.append("Color.orange"+"\n");
				}else if(color.equals(Color.blue)){
					output.append("Color.blue"+"\n");
				}else if(color.equals(Color.white)){
					output.append("Color.white"+"\n");
				}else if(color.equals(Color.red)){
					output.append("Color.red"+"\n");
				}else if(color.equals(Color.yellow)){
					output.append("Color.yellow"+"\n");
				}
			} else if(command.equals ("setColor(...)")){
				color_dialog.show();
				Color newColor = color_dialog.getColor();
				if (newColor != null) {
					selected.setColor(newColor);
				}
			} else if(command.equals ("getLocation()")) {
				if ( selected instanceof Drawable2DInterface) {
					Location bLocn = ((Drawable2DInterface)selected).getLocation();
					output.append("  Location: (" + bLocn.getX() + " , " + bLocn.getY() + " )\n");
				} else {
					output.append ("getLocation() not \nimplemented for lines!\n");
				}
				
				
			} else if(command.equals ("getHeight()")){
			  if (selected instanceof Drawable2DInterface) {
					double height=((Drawable2DInterface)selected).getHeight();
					Location bLocn = ((Drawable2DInterface)selected).getLocation();
					output.append("  height: "+ height +"\n");

				} 
				else {
					output.append ("getHeight() not \nimplemented for lines!\n");
				}
				
				
			} else if(command.equals ("getWidth()")){
			  if (selected instanceof Drawable2DInterface) {
					double width=((Drawable2DInterface)selected).getWidth();
					Location bLocn = ((Drawable2DInterface)selected).getLocation();
					output.append("  width: " + width +"\n");
					
				} 
				else {
					output.append ("getWidth not \nimplemented for lines!\n");
				}
				
			} else if(command.equals ("getStart()")){
			  if (selected instanceof Line) {
					Location start=((Line)selected).getStart();
					output.append("Start at "+"("+start.getX()+","+start.getY()+")"+"\n");
				} 
				else {
					output.append ("getStart only \nimplemented for lines!\n");
				}
			} else if(command.equals ("getEnd()")){
			  if (selected instanceof Line) {
					Location end=((Line)selected).getEnd();
					output.append("End at "+"("+end.getX()+","+end.getY()+")"+"\n");
				} 
				else {
					output.append ("getEnd only \nimplemented for lines!\n");
				}
			} else if(command.equals ("move(...)")){
				TwoParamDialog moveDialog =
					new TwoParamDialog( this, true, "move","x-offset", "y-offset");
				if (!moveDialog.cancelled()) {
					selected.move(moveDialog.getFirstParam(),moveDialog.getSecondParam());
				}
			} else if(command.equals ("moveTo(...)")){
				TwoParamDialog moveDialog =
					new TwoParamDialog(this, true, "moveTo", "x", "y");
				if (!moveDialog.cancelled()) {
					selected.moveTo(moveDialog.getFirstParam(),moveDialog.getSecondParam());
				}
			} else if(command.equals ("setHeight(...)")){
				if (selected instanceof Resizable2DInterface) {
					OneParamDialog heightDialog = new OneParamDialog( this, true, 
																		"setHeight", "height");
					if (!heightDialog.cancelled()) {
						((Resizable2DInterface)selected).setHeight(heightDialog.getFirstParam());
					}
				}
				else {
					output.append ("setHeight(...) not implemented \nfor lines or text!\n");
				}
			} else if(command.equals ("setWidth(...)")){
				if (selected instanceof Resizable2DInterface) {
					OneParamDialog widthDialog = new OneParamDialog( this, true, 
																		"setWidth", "width");
					if (!widthDialog.cancelled()) {
						((Resizable2DInterface)selected).setWidth(widthDialog.getFirstParam());
					}
				}
				else {
					output.append ("setWidth(...) not implemented \nfor lines or text!\n");
			}	
			} else if(command.equals ("setEndPoints(...)")){
				if (selected instanceof Line) {
					FourParamDialog endPtsDialog =
						new FourParamDialog( this, true, "setEndPoints",
											"x1", "y1", "x2", "y2");
					if (!endPtsDialog.cancelled()) {
						Location newStart = new Location (endPtsDialog.getFirstParam(), 
													  endPtsDialog.getSecondParam());
						Location newEnd = new Location (endPtsDialog.getThirdParam(), 
													  endPtsDialog.getFourthParam());
						((Line)selected).setEndPoints(newStart, newEnd);
					}
				}
				else {
					output.append ("setEndpoints only \nimplemented for lines!\n");
				}
			} else if(command.equals ("hide()")){
				selected.hide();
			} else if(command.equals ("show()")){
				selected.show();
			} else if(command.equals ("sendForward()")){
				selected.sendForward();
			} else if(command.equals ("sendBackward()")){
				selected.sendBackward();
			} else {
				//output.append("This should never happen.  Tell your instructor.\n");
				}
			
		}
		canvas.repaint();
	}
	
	 public void update (Observable o, Object arg) {

	}
	
	/**
	  * Appends a string to the output text area
	  * @param s the string to append
	  */
	/* This was added so that messages could be appended to the output text area instead of using
	   the Java console.  Barbara Lerner  9/00
	 */
	public static void appendToOutput (String s) {
		lab.output.append (s);
	}

	public Dimension getMinimumSize()
	{
	    return new Dimension(0, 0);
	}


     public void saveFile()
     {
		 File theSaveFile;
		 
		 Vector savedObjects = new Vector();
		 FileDialog saveDialog = new FileDialog(this, "Save File", FileDialog.SAVE);
		 saveDialog.show();
		 String saveFileDirectory = saveDialog.getDirectory();
		 String saveFileName = saveDialog.getFile();


		 if (saveFileName == null) // Cancel
		 {
		     return;
		 }
		 else
		 {
		     theSaveFile = new File(saveFileDirectory + saveFileName);
		 }

		 DrawableIterator iter = canvas.getCanvasContent().getObjectIterator();
		 while (iter.hasNext())
		 {
		     savedObjects.add(iter.next());
		 }

		 try
		 {
		     FileOutputStream fileOut = new FileOutputStream(theSaveFile);
		     ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
		     objectOut.writeObject(savedObjects);
		     fileOut.close();
		     objectOut.close();
		 }
		 catch(Exception e)
		 {
		     new ErrorDialog(this, "Your file could not be saved for some reason.", true);
		 }
     }

     public void loadFile()
     {
		 File theLoadFile;
		 boolean loaded = true;

		 Vector loadedObjects;
		 FileDialog loadDialog = new FileDialog(this, "Load File", FileDialog.LOAD);
		 loadDialog.show();
		 String loadFileDirectory = loadDialog.getDirectory();
		 String loadFileName = loadDialog.getFile();
		 if (loadFileName == null) // Cancel
		 {
		     return;
		 }
		 else
		 {
		     theLoadFile = new File(loadFileDirectory + loadFileName);
		 }
		 try
		 {
		     FileInputStream fileIn = new FileInputStream(theLoadFile);
		     ObjectInputStream objectIn = new ObjectInputStream(fileIn);
		     loadedObjects = (Vector)objectIn.readObject();
		     fileIn.close();
		     objectIn.close();
		 }
		 catch(ClassCastException e)
		 {
		     new ErrorDialog(this, "The file you tried to load is unreadable.", true);
		     loadedObjects = new Vector();
		     loaded = false;
		     
		 }
		 catch(Exception e)
		 {
		     new ErrorDialog(this, "Your file could not be loaded for some reason.", true);
		     loadedObjects = new Vector();
		     loaded = false;
		 }
		 
		 if (loaded)
		 { 
			 Iterator iter = loadedObjects.iterator();
			 canvas.clear();
			 while(iter.hasNext())
			 {
			     canvas.addToCanvas((Drawable)iter.next());
			 }
		 }
     }




	/**
	 * Creates an instance of the lab program frame.
	 */
	public static void main(String[] args){
		lab=new ClassLab();
		// lab.setSize(700,520);
		lab.pack();
		lab.setVisible(true);
	}
	
}
