package sim.lib.memory;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import gjt.BulletinLayout;

import sim.*;
import sim.engine.*;
import sim.lib.memory.hex.*;
import sim.util.SimSeparator;
import sim.util.DialogButton;
import sim.lib.wires.Junction;

public class Rom extends MemoryStructure
{
/* ==================================================================
	Creation Part
	================================================================= */
	private static Image ICON = GuiFileLink.getImage("sim/lib/memory/RomIcon.gif");
	
	public Image getIcon()
	{
		return Rom.ICON;;
	}
	
	public String getBubbleHelp()
	{
		return "ROM";
	}
	
/* ==================================================================
	GUI part
	================================================================= */
	public Rom()
	{
		super();
	}
	
	protected Wrapper getCopy()
	{
		Rom result = new Rom();
		
		result.setBusSize(this.busSize);
		result.setAddressSpace(this.addressSpace);
		result.initializeMemory();
		
		return result;
	}
	
	public void paint(Graphics g)
	{
		// draw if visible
		if(this.isVisible())
		{
			int gridGap = CentralPanel.ACTIVE_GRID.getCurrentGridGap();
			int increment = gridGap / 4;
			
			g.setColor(Color.white);
			g.fillRect(gridGap, 11 * increment, 14 * increment, 6 * increment);
			g.fillRect(22 * increment, 11 * increment, 14 * increment, 6 * increment);
			
			g.setColor(this.brush);
			g.drawRect(gridGap, gridGap, 8 * gridGap, 5 * gridGap);
			
			g.drawLine(2 * gridGap, 6 * gridGap, 2 * gridGap, 7 * gridGap);
			g.drawLine(8 * gridGap, 6 * gridGap, 8 * gridGap, 7 * gridGap);
			
			g.fillRect(0, 2 * gridGap - 1, gridGap, 3);
			g.fillRect(9 * gridGap, 2 * gridGap - 1, gridGap, 3);
			
			g.setFont(new Font(Wrapper.FONT_NAME, Font.BOLD, 3 * increment));
			FontMetrics fm = g.getFontMetrics(g.getFont());
			g.drawString("ROM", 5 * gridGap - fm.stringWidth("ROM") / 2, 2 * gridGap);
			
			g.setFont(new Font(Wrapper.FONT_NAME, Font.PLAIN, 3 * increment));
			fm = g.getFontMetrics(g.getFont());
			
			g.drawString("A" + (this.requiredAddress - 1) + "-0", gridGap + increment, 9 * increment);
			String toDraw = "D" + (this.busSize - 1) + "-0";
			g.drawString(toDraw, 9 * gridGap - increment - fm.stringWidth(toDraw), 9 * increment);
			
			g.drawString("___", 2 * gridGap - fm.stringWidth("___") / 2, 23 * increment - fm.getHeight());
			g.drawString("CE", 2 * gridGap  - fm.stringWidth("CE") / 2, 23 * increment);
			g.drawString("___", 8 * gridGap - fm.stringWidth("___") / 2, 23 * increment - fm.getHeight());
			g.drawString("OE", 8 * gridGap - fm.stringWidth("OE") / 2, 23 * increment);
			
			g.drawRect(gridGap, 11 * increment, 14 * increment, 6 * increment);
			g.drawRect(22 * increment, 11 * increment, 14 * increment, 6 * increment);
			
			Shape old = g.getClip();
			
			if(this.addressToDraw != null)
			{
				g.setClip(gridGap, 11 * increment, 14 * increment, 6 * increment);
				g.drawString(this.addressToDraw, 11 * increment - fm.stringWidth(this.addressToDraw) / 2, 15 * increment);
			}
			
			if(this.dataToDraw != null)
			{
				g.setClip(22 * increment, 11 * increment, 14 * increment, 6 * increment);
				g.drawString(this.dataToDraw, 29 * increment - fm.stringWidth(this.dataToDraw) / 2, 15 * increment);
			}
			
			g.setClip(old);
		}
	}
	
/* ==================================================================
	Maintanance Part
	================================================================= */
	public boolean canDrop()
	{
		boolean result = Wrapper.canDropJuncion(this.gridLocation.x, this.gridLocation.y + 2, this.requiredAddress);
		result = result && Wrapper.canDropJuncion(this.gridLocation.x + 10, this.gridLocation.y + 2, this.busSize);
		result = result && Wrapper.canDropJuncion(this.gridLocation.x + 2, this.gridLocation.y + 7, 1);
		result = result && Wrapper.canDropJuncion(this.gridLocation.x + 8, this.gridLocation.y + 7, 1);
		
		return result;
	}
		
	public void droped()
	{
		this.address = Wrapper.setPinAt(this.gridLocation.x, this.gridLocation.y + 2, this.requiredAddress);
		this.data = Wrapper.setPinAt(this.gridLocation.x + 10, this.gridLocation.y + 2, this.busSize);
		this.notCE = Wrapper.setPinAt(this.gridLocation.x + 2, this.gridLocation.y + 7, 1);
		this.notOE = Wrapper.setPinAt(this.gridLocation.x + 8, this.gridLocation.y + 7, 1);

		this.changeColor(Color.black);
		this.oldBusSize = 0;
	}
	
	public void selected()
	{
		this.address.removePin();
		this.data.removePin();
		this.notCE.removePin();
		this.notOE.removePin();
		
		this.changeColor(Color.green);
	}
	
	public void checkAfterSelected()
	{
		Wrapper.checkPin(this.address);
		Wrapper.checkPin(this.data);
		Wrapper.checkPin(this.notCE);
		Wrapper.checkPin(this.notOE);
	}
	
/* ==================================================================
	Simulation part
	================================================================= */
	public void evaluateOutput(double currentTime, Data[] currentInputs, EnginePeer peer)
	{	
		// check address
		boolean foundUndefined = false;
		int base = 1;
		int newValue = 0;
		
		for(int loop = 0; (loop < this.requiredAddress) && (!foundUndefined); loop++)
		{
			if(currentInputs[2 + loop].isUndefined())
			{
				foundUndefined = true;
				newValue = -1;
			}
			else if(currentInputs[2 + loop].getValue())
			{
				newValue = newValue + base;
			}
			
			base = 2 * base;
		}
		
		if(newValue != this.oldAddress)
		{
			this.addressChange = currentTime;
			this.oldAddress = newValue;
			this.addressHandled = false;
			
			if(this.oldAddress == -1)
			{
				this.addressToDraw = "-";
				this.dataToDraw = "-";
				
				for(newValue = 1; newValue < this.addressLenght; newValue++)
					this.addressToDraw = this.addressToDraw + "-";
				
				for(newValue = 1; newValue < this.wordLenght; newValue++)
					this.dataToDraw = this.dataToDraw + "-";
			}
			else
			{
				this.addressToDraw = Integer.toHexString(this.oldAddress);
				
				for(newValue = this.addressToDraw.length(); newValue < this.addressLenght; newValue++)
					this.addressToDraw = "0" + this.addressToDraw;
				
				this.dataToDraw = (new Character(this.memoryContent[this.oldAddress][this.wordLenght - 1])).toString();
				
				for(newValue = 1; newValue < this.wordLenght; newValue++)
					this.dataToDraw = this.dataToDraw + this.memoryContent[this.oldAddress][this.wordLenght - newValue - 1];
				
				this.addressToDraw = this.addressToDraw.toUpperCase();
				this.dataToDraw = this.dataToDraw.toUpperCase();
			}
			
			CentralPanel.ACTIVE_GRID.paintComponent(this);
		}
		
		// check notCE
		if(currentInputs[0].isUndefined() || currentInputs[0].getValue())
		{
			if(!this.pastNotCE)
				this.notCE_goesHigh = currentTime;
			
			this.pastNotCE = true;
		}
		else
		{
			if(this.pastNotCE)
				this.notCE_goesLow = currentTime;
			
			this.pastNotCE = false;
		}
		
		// check notOE
		if(currentInputs[1].isUndefined() || currentInputs[1].getValue())
		{
			if(!this.pastNotOE)
				this.notOE_goesHigh = currentTime;
			
			this.pastNotOE = true;
		}
		else
		{
			if(this.pastNotOE)
				this.notOE_goesLow = currentTime;
			
			this.pastNotOE = false;
		}
		
		// simulate
		if(!this.pastNotCE && !this.pastNotOE)
		{
			// handle start of reading
			if((this.notOE_goesLow == currentTime) && (this.notCE_goesLow == currentTime))
			{
				this.startPutting = currentTime + Math.max(this.oe, this.acs);
				this.addressHandled = false;
				this.undefineOutputs(currentTime + Math.min(this.olz, this.clz), peer);
				this.isReading = true;
			}
			else if(this.notOE_goesLow == currentTime)
			{
				this.startPutting = currentTime + this.oe;
				this.addressHandled = false;
				this.undefineOutputs(currentTime + this.olz, peer);
				this.isReading = true;
			}
			else if(this.notCE_goesLow == currentTime)
			{
				this.startPutting = currentTime + this.acs;
				this.addressHandled = false;
				this.undefineOutputs(currentTime + this.clz, peer);
				this.isReading = true;
			}
			
			// handle reading
			if(!this.addressHandled)
			{
				if(this.startPutting >= this.addressChange + this.oh)	// handle start of reading
				{
					this.setSignalsAt(this.oldAddress, this.startPutting, peer);
				}
				else
				{
					this.undefineOutputs(this.addressChange + this.oh, peer);
					this.setSignalsAt(this.oldAddress, this.addressChange + this.aa, peer);
				}
				
				this.addressHandled = true;
			}
		}
		else
		{
			// handle stop of reading
			if(this.isReading)
			{
				if((this.notOE_goesHigh == currentTime) && (this.notCE_goesHigh == currentTime))
				{
					this.startFloating = currentTime + Math.min(this.ohz, this.chz);
					this.floatOutputs(this.startFloating, peer);
				}
				else if(this.notOE_goesHigh == currentTime)
				{
					this.startFloating = currentTime + this.ohz;
					this.floatOutputs(this.startFloating, peer);
				}
				else if(this.notCE_goesHigh == currentTime)
				{
					this.startFloating = currentTime + this.chz;
					this.floatOutputs(this.startFloating, peer);
				}
				
				this.isReading = false;
			}
			
			// handle address change during stop
			if(!this.addressHandled && (this.startFloating > this.addressChange + this.oh))
			{
				if(this.startPutting >= this.addressChange + this.oh)	// handle start of reading
				{
					this.setSignalsAt(this.oldAddress, this.startPutting, peer);
				}
				else
				{
					this.undefineOutputs(this.addressChange + this.oh, peer);
					this.setSignalsAt(this.oldAddress, this.addressChange + this.aa, peer);
				}
				
				this.floatOutputs(this.startFloating, peer);
				this.addressHandled = true;
			}
		}
	}
	
	public void createEnginePeer(EnginePeerList epl)
	{
		int loop;
		EnginePeer ep = new EnginePeer(2 + this.requiredAddress, this.busSize, this);
		
		ep.setInputPin(0, this.notCE.getNodes().getItemAt(0));
		ep.setInputPin(1, this.notOE.getNodes().getItemAt(0));
		
		for(loop = 0; loop < this.busSize; loop++)
			ep.setOutputPin(loop, this.data.getNodes().getItemAt(loop));
		
		for(loop = 0; loop < this.requiredAddress; loop++)
			ep.setInputPin(loop + 2, this.address.getNodes().getItemAt(loop));
		
		this.notCE_goesLow = 0;
		this.notCE_goesHigh = 0;
		this.notOE_goesLow = 0;
		this.notOE_goesHigh = 0;
		
		this.pastNotCE = true;
		this.pastNotOE = true;
		
		this.oldAddress = -1;
		this.addressChange = 0;
		this.addressHandled = false;
		
		this.startPutting = 0;
		this.startFloating = 0;
		this.isReading = false;
		
		epl.insertItem(ep);
		
		if(this.editor != null)
			this.editor.prepareForSimulation();
	}
	
/* ==================================================================
	Storage Part
	================================================================= */
	public String getSpecificParameters()
	{
		String result = this.targetFile + Wrapper.SEPARATOR + this.busSize + Wrapper.SEPARATOR + this.addressSpace + Wrapper.SEPARATOR;
		
		result = result + this.aa + Wrapper.SEPARATOR + this.acs + Wrapper.SEPARATOR + this.clz + Wrapper.SEPARATOR + this.oe + Wrapper.SEPARATOR;
		result = result + this.olz + Wrapper.SEPARATOR + this.chz + Wrapper.SEPARATOR + this.ohz + Wrapper.SEPARATOR + this.oh + Wrapper.SEPARATOR;
		
		return result;
	}
	
	public void loadWrapper(String[] specificParameters) throws SimException
	{
		if(specificParameters.length == this.getNumberOfSpecificParameters())
		{
			try
			{
				this.targetFile = specificParameters[0];
				this.setBusSize(Integer.valueOf(specificParameters[1]).intValue());
				this.setAddressSpace(Integer.valueOf(specificParameters[2]).intValue());
				
				this.aa = Double.valueOf(specificParameters[3]).doubleValue();
				this.acs = Double.valueOf(specificParameters[4]).doubleValue();
				this.clz = Double.valueOf(specificParameters[5]).doubleValue();
				this.oe = Double.valueOf(specificParameters[6]).doubleValue();
				this.olz = Double.valueOf(specificParameters[7]).doubleValue();
				this.chz = Double.valueOf(specificParameters[8]).doubleValue();
				this.ohz = Double.valueOf(specificParameters[9]).doubleValue();
				this.oh = Double.valueOf(specificParameters[10]).doubleValue();
				
				this.initializeMemory();
			}
			catch(NumberFormatException e)
			{
				throw (new SimException("incorrect parameter type"));
			}
		}
		else
			throw (new SimException("incorrect number of parameters"));
	}
	
	public int getNumberOfSpecificParameters()
	{
		return 11;
	}
	
/* ==================================================================
	Popup Part
	================================================================= */
	private int oldAddressSpace;
	private int oldBusSize = 0;
	
	public boolean hasProperties()
	{
		return true;
	}
	
	public Component getPropertyWindow()
	{
		return (new RomProperties(this.targetFile, this.busSize, this.requiredAddress, this.aa, this.acs, this.clz, this.oe, this.olz, this.chz, this.ohz, this.oh));
	}
	
	public void respondToChanges(Component property)
	{
		try
		{
			CentralPanel.ACTIVE_GRID.eraseComponent(this, false);
			
			RomProperties x = (RomProperties)property;
			
			this.aa = x.getAA();
			this.acs = x.getACS();
			this.clz = x.getCLZ();
			this.oe = x.getOE();
			this.olz = x.getOLZ();
			this.chz = x.getCHZ();
			this.ohz = x.getOHZ();
			this.oh = x.getOH();
			
			if(this.oldBusSize == 0)
			{
				this.oldBusSize = this.busSize;
				this.oldAddressSpace = this.requiredAddress;
			}
			
			this.setBusSize(x.getBusSize());
			this.setAddressSpace((int)Math.pow(2, x.getAddressSize()));
			
			this.targetFile = x.getFileName();
			this.initializeMemory();
			
			CentralPanel.ACTIVE_GRID.paintComponent(this);
		}
		catch(Throwable err)
		{
			this.setBusSize(this.oldBusSize);
			this.setAddressSpace((int)Math.pow(2, this.oldAddressSpace));
			this.oldBusSize = 0;
			this.initializeMemory();
			
			CentralPanel.ACTIVE_GRID.paintComponent(this);
			
			MainWindow.OK_WINDOW.setDescription("Can not increase memory size");
			MainWindow.OK_WINDOW.setMessage("fail to allocate more memory");
			MainWindow.OK_WINDOW.show();
		}
			
		if(this.editor != null)
			this.editor.changeParameters(this.memoryContent, this.targetFile, this.busSize, this.addressSpace);
	}
	
	public void restoreOriginalProperties()
	{
		if(this.oldBusSize != 0)
		{
			this.setBusSize(this.oldBusSize);
			this.setAddressSpace((int)Math.pow(2, this.oldAddressSpace));
			
			this.initializeMemory();
			this.oldBusSize = 0;
			
			if(this.editor != null)
				this.editor.changeParameters(this.memoryContent, this.targetFile, this.busSize, this.addressSpace);
		}
	}
	
	private class RomProperties extends Container implements ActionListener, FocusListener
	{
		private DialogButton browse = new DialogButton("Browse...");
		
		private TextField editFileName = new TextField();
		private TextField editBusSize = new TextField(5);
		private TextField editAddressSize = new TextField(5);
		private TextField editAA = new TextField(5);
		private TextField editACS = new TextField(5);
		private TextField editCLZ = new TextField(5);
		private TextField editOE = new TextField(5);
		private TextField editOLZ = new TextField(5);
		private TextField editCHZ = new TextField(5);
		private TextField editOHZ = new TextField(5);
		private TextField editOH = new TextField(5);
		
		private Label content = new Label("Memory Content");
		private Label busSize = new Label("Bus Sizes");
		private Label delays = new Label("Propagation Delays");
		
		private String oldName;
		private int oldBusSize;
		private int oldAddressSize;
		
		private double oldAA;
		private double oldACS;
		private double oldCLZ;
		private double oldOE;
		private double oldOLZ;
		private double oldCHZ;
		private double oldOHZ;
		private double oldOH;
		
		private ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
		
		public RomProperties(String file, int bus, int address, double aa, double acs, double clz, double oe, double olz, double chz, double ohz, double oh)
		{
			super();
			this.setLayout(new GridBagLayout());
			
			if(MainWindow.MASTER != null)
			{
				this.editFileName.setEnabled(false);
				this.browse.setEnabled(false);
			}
			
			this.oldName = file;
			this.oldBusSize = bus;
			this.oldAddressSize = address;
			this.oldAA = aa;
			this.oldACS = acs;
			this.oldCLZ = clz;
			this.oldOE = oe;
			this.oldOLZ = olz;
			this.oldCHZ = chz;
			this.oldOHZ = ohz;
			this.oldOH = oh;
			
			this.editFileName.setText(this.oldName);
			this.editBusSize.setText(Integer.toString(this.oldBusSize));
			this.editAddressSize.setText(Integer.toString(this.oldAddressSize));
			this.editAA.setText(Double.toString(this.oldAA));
			this.editACS.setText(Double.toString(this.oldACS));
			this.editCLZ.setText(Double.toString(this.oldCLZ));
			this.editOE.setText(Double.toString(this.oldOE));
			this.editOLZ.setText(Double.toString(this.oldOLZ));
			this.editCHZ.setText(Double.toString(this.oldCHZ));
			this.editOHZ.setText(Double.toString(this.oldOHZ));
			this.editOH.setText(Double.toString(this.oldOH));
			
			this.browse.addActionListener(this);
			this.editFileName.addActionListener(this);
			this.editBusSize.addActionListener(this);
			this.editAddressSize.addActionListener(this);
			this.editAA.addActionListener(this);
			this.editACS.addActionListener(this);
			this.editCLZ.addActionListener(this);
			this.editOE.addActionListener(this);
			this.editOLZ.addActionListener(this);
			this.editCHZ.addActionListener(this);
			this.editOHZ.addActionListener(this);
			this.editOH.addActionListener(this);
			
			this.editFileName.addFocusListener(this);
			this.editBusSize.addFocusListener(this);
			this.editAddressSize.addFocusListener(this);
			this.editAA.addFocusListener(this);
			this.editACS.addFocusListener(this);
			this.editCLZ.addFocusListener(this);
			this.editOE.addFocusListener(this);
			this.editOLZ.addFocusListener(this);
			this.editCHZ.addFocusListener(this);
			this.editOHZ.addFocusListener(this);
			this.editOH.addFocusListener(this);
			
			// content
			Panel big = new Panel(new BorderLayout(0, 15));
			
			Panel p = new Panel(new BorderLayout());
			p.add(this.content, BorderLayout.WEST);
			p.add(new SimSeparator(), BorderLayout.CENTER);
			big.add(p, BorderLayout.NORTH);
			
			p = new Panel(new GridBagLayout());
			
			GridBagConstraints c = new GridBagConstraints();
			c.gridy = 0;
			c.gridwidth = 1;
			c.gridheight = 1;
			c.anchor = GridBagConstraints.WEST;
			c.weighty = 0;
			
			c.fill = GridBagConstraints.HORIZONTAL;
			c.weightx = 1;
			c.gridx = 0;
			
			p.add(this.editFileName, c);
			
			c.fill = GridBagConstraints.NONE;
			c.weightx = 0;
			c.gridx = 1;
			c.insets = new Insets(0, 10, 0, 0);
			
			p.add(this.browse, c);
			big.add(p, BorderLayout.CENTER);
			
			c.gridx = 0;
			c.insets = new Insets(0, 0, 0, 0);
			c.weightx = 1;
			c.fill = GridBagConstraints.HORIZONTAL;
			
			this.add(big, c);
			
			// bus size
			big = new Panel(new BorderLayout(0, 15));
			
			p = new Panel(new BorderLayout());
			p.add(this.busSize, BorderLayout.WEST);
			p.add(new SimSeparator(), BorderLayout.CENTER);
			big.add(p, BorderLayout.NORTH);
			
			p = new Panel(new GridBagLayout());
			
			Panel p2 = new Panel(new FlowLayout(FlowLayout.LEFT, 0, 0));
			p2.add(new Label("Data"));
			p2.add(this.editBusSize);
			
			c.fill = GridBagConstraints.NONE;
			p.add(p2, c);
			
			p2 = new Panel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
			p2.add(new Label("Address"));
			p2.add(this.editAddressSize);
			
			c.anchor = GridBagConstraints.EAST;
			c.gridx = 1;
			p.add(p2, c);
			
			big.add(p, BorderLayout.CENTER);
			
			c.gridx = 0;
			c.gridy = 1;
			c.insets = new Insets(15, 0, 15, 0);
			c.fill = GridBagConstraints.HORIZONTAL;
			this.add(big, c);
			
			// simulaion
			big = new Panel(new BorderLayout(0, 15));
			
			p = new Panel(new BorderLayout());
			p.add(this.delays, BorderLayout.WEST);
			p.add(new SimSeparator(), BorderLayout.CENTER);
			big.add(p, BorderLayout.NORTH);
			
			p = new Panel(new GridBagLayout());
			
			c.insets = new Insets(2, 5, 2, 0);
			
			c.gridy = 0;
			p.add(new Label("address access"), c);
			c.gridx = 1;
			p.add(this.editAA, c);
			
			c.gridy = 1;
			c.gridx = 0;
			p.add(new Label("chip select access"), c);
			c.gridx = 1;
			p.add(this.editACS, c);
			
			c.gridy = 2;
			c.gridx = 0;
			p.add(new Label("chip select to output"), c);
			c.gridx = 1;
			p.add(this.editCLZ, c);
			
			c.gridy = 3;
			c.gridx = 0;
			p.add(new Label("output ebable to output valid"), c);
			c.gridx = 1;
			p.add(this.editOE, c);
			
			c.gridy = 4;
			c.gridx = 0;
			p.add(new Label("output enable to output"), c);
			c.gridx = 1;
			p.add(this.editOLZ, c);
			
			c.gridy = 5;
			c.gridx = 0;
			p.add(new Label("chip deselection to output"), c);
			c.gridx = 1;
			p.add(this.editCHZ, c);
			
			c.gridy = 6;
			c.gridx = 0;
			p.add(new Label("chip disable to output"), c);
			c.gridx = 1;
			p.add(this.editOHZ, c);
			
			c.gridy = 7;
			c.gridx = 0;
			p.add(new Label("output hold from output change"), c);
			c.gridx = 1;
			p.add(this.editOH, c);
			
			this.scroller.getVAdjustable().setBlockIncrement(50);
			this.scroller.getVAdjustable().setUnitIncrement(25);
			
			p2 = new Panel(new BulletinLayout());
			p2.add(p);
			this.scroller.add(p2);
			big.add(this.scroller, BorderLayout.CENTER);
			
			c.gridx = 0;
			c.gridy = 2;
			c.insets = new Insets(0, 0, 0, 0);
			this.add(big, c);
		}
		
		public void addNotify()
		{
			super.addNotify();
			this.setSize(290, this.editBusSize.getPreferredSize().height * 2 + this.delays.getPreferredSize().height * 3 + 175);
			
			this.scroller.validate();
		}
		
		public void actionPerformed(ActionEvent e)
		{
			Component source = (Component)e.getSource();
			
			if(source == this.editFileName)
				this.getFileName();
			else if(source == this.editBusSize)
				this.getBusSize();
			else if(source == this.editAddressSize)
				this.getAddressSize();
			else if(source == this.editAA)
				this.getAA();
			else if(source == this.editACS)
				this.getACS();
			else if(source == this.editCLZ)
				this.getCLZ();
			else if(source == this.editOE)
				this.getOE();
			else if(source == this.editOLZ)
				this.getOLZ();
			else if(source == this.editCHZ)
				this.getCHZ();
			else if(source == this.editOHZ)
				this.getOHZ();
			else if(source == this.editOH)
				this.getOH();
			else if(source == this.browse)
			{
				SaveLoadShortcut.FILEDIALOG.setTitle("Open");
				SaveLoadShortcut.FILEDIALOG.setMode(FileDialog.LOAD);
				SaveLoadShortcut.FILEDIALOG.setFile("*.mem");
				SaveLoadShortcut.FILEDIALOG.show();
				
				String inFile = SaveLoadShortcut.FILEDIALOG.getFile();
					
				if(inFile != null)
				{
					this.oldName = SaveLoadShortcut.FILEDIALOG.getDirectory() + inFile;
					this.editFileName.setText(this.oldName);
				}
			}
		}
		
		public void focusGained(FocusEvent e)
		{
		}
		
		public void focusLost(FocusEvent e)
		{
			TextField source = (TextField)e.getSource();
			
			if(source == this.editFileName)
				this.getFileName();
			else if(source == this.editBusSize)
				this.getBusSize();
			else if(source == this.editAddressSize)
				this.getAddressSize();
			else if(source == this.editAA)
				this.getAA();
			else if(source == this.editACS)
				this.getACS();
			else if(source == this.editCLZ)
				this.getCLZ();
			else if(source == this.editOE)
				this.getOE();
			else if(source == this.editOLZ)
				this.getOLZ();
			else if(source == this.editCHZ)
				this.getCHZ();
			else if(source == this.editOHZ)
				this.getOHZ();
			else if(source == this.editOH)
				this.getOH();
			
			source.setText(source.getText());
		}
		
		public int getBusSize()
		{
			int newBus;
			
			try
			{
				newBus = Integer.valueOf(this.editBusSize.getText()).intValue();
				
				if((newBus > 1) && (newBus <= 32))
					this.oldBusSize = newBus;
				else
					this.editBusSize.setText(Integer.toString(this.oldBusSize));
			}
			catch(NumberFormatException nfe)
			{
				this.editBusSize.setText(Integer.toString(this.oldBusSize));
			}
			
			return this.oldBusSize;
		}
		
		public int getAddressSize()
		{
			int newAddress;
			
			try
			{
				newAddress = Integer.valueOf(this.editAddressSize.getText()).intValue();
				
				if((newAddress > 1) && (newAddress <= 8))
					this.oldAddressSize = newAddress;
				else
					this.editAddressSize.setText(Integer.toString(this.oldAddressSize));
			}
			catch(NumberFormatException nfe)
			{
				this.editAddressSize.setText(Integer.toString(this.oldAddressSize));
			}
			
			return this.oldAddressSize;
		}
		
		public String getFileName()
		{
			String newName = this.editFileName.getText();
			
			if(this.browse.isEnabled())
			{
				try
				{
					FileWriter f = new FileWriter(newName, true);
					f.close();
					
					this.oldName = newName;
				}
				catch(IOException ex)
				{
					this.editFileName.setText(this.oldName);
				}
			}
			
			return this.oldName;
		}
		
		public double getAA()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editAA.getText()).doubleValue();
				
				if(newValue >= 0)
					this.oldAA = newValue;
				else
					this.editAA.setText(Double.toString(this.oldAA));
			}
			catch(NumberFormatException nfe)
			{
				this.editAA.setText(Double.toString(this.oldAA));
			}
			
			return this.oldAA;
		}
		
		public double getACS()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editACS.getText()).doubleValue();
				
				if((newValue >= 0) && (newValue >= this.oldCLZ))
					this.oldACS = newValue;
				else
					this.editACS.setText(Double.toString(this.oldACS));
			}
			catch(NumberFormatException nfe)
			{
				this.editACS.setText(Double.toString(this.oldACS));
			}
			
			return this.oldACS;
		}
		
		public double getCLZ()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editCLZ.getText()).doubleValue();
				
				if((newValue >= 0) && (newValue <= this.oldACS))
					this.oldCLZ = newValue;
				else
					this.editCLZ.setText(Double.toString(this.oldCLZ));
			}
			catch(NumberFormatException nfe)
			{
				this.editCLZ.setText(Double.toString(this.oldCLZ));
			}
			
			return this.oldCLZ;
		}
		
		public double getOE()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editOE.getText()).doubleValue();
				
				if((newValue >= 0) && (newValue >= this.oldOLZ))
					this.oldOE = newValue;
				else
					this.editOE.setText(Double.toString(this.oldOE));
			}
			catch(NumberFormatException nfe)
			{
				this.editOE.setText(Double.toString(this.oldOE));
			}
			
			return this.oldOE;
		}
		
		public double getOLZ()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editOLZ.getText()).doubleValue();
				
				if((newValue >= 0) && (newValue <= this.oldOE))
					this.oldOLZ = newValue;
				else
					this.editOLZ.setText(Double.toString(this.oldOLZ));
			}
			catch(NumberFormatException nfe)
			{
				this.editOLZ.setText(Double.toString(this.oldOLZ));
			}
			
			return this.oldOLZ;
		}
		
		public double getCHZ()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editCHZ.getText()).doubleValue();
				
				if(newValue >= 0)
					this.oldCHZ = newValue;
				else
					this.editCHZ.setText(Double.toString(this.oldCHZ));
			}
			catch(NumberFormatException nfe)
			{
				this.editCHZ.setText(Double.toString(this.oldCHZ));
			}
			
			return this.oldCHZ;
		}
		
		public double getOHZ()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editOHZ.getText()).doubleValue();
				
				if(newValue >= 0)
					this.oldOHZ = newValue;
				else
					this.editOHZ.setText(Double.toString(this.oldOHZ));
			}
			catch(NumberFormatException nfe)
			{
				this.editOHZ.setText(Double.toString(this.oldOHZ));
			}
			
			return this.oldOHZ;
		}
		
		public double getOH()
		{
			double newValue;
			
			try
			{
				newValue = Double.valueOf(this.editOH.getText()).doubleValue();
				
				if(newValue >= 0)
					this.oldOH = newValue;
				else
					this.editOH.setText(Double.toString(this.oldOH));
			}
			catch(NumberFormatException nfe)
			{
				this.editOH.setText(Double.toString(this.oldOH));
			}
			
			return this.oldOH;
		}
		
		public Dimension getPreferredSize()
		{
			return this.getSize();
		}
		
		public Dimension getMinimumSize()
		{
			return this.getSize();
		}
	
		public Dimension getMaximumSize()
		{
			return this.getSize();
		}
	}
}