package chrono;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.util.ArrayList;
import javax.swing.JCheckBox;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.Timer;

import chronoDivers.Arrow;
import chronoDivers.VertLines;
import signals.Signals;
import chrono.Main;


public class ChronoPanel  extends JPanel  implements MouseListener, MouseMotionListener
{
	private static final long serialVersionUID = 1L;
	public File openedFile;
	public String fileName = "New";
	public boolean saveFileOk = false;
	public boolean modifToSave = false;
	public ArrayList<Signals> signals = new ArrayList();
	public int selected;
	public boolean elmt_to_edit = false;
	public int selected_bus;
	public int selected_signal;
	public int bus_offset;
	public int[][] timeLapse = new int[5][4];
	public int nbrTimeLapse = 0;
	public boolean setTimeLapse = false;
	public boolean getTimeLapseWidth = false;
	public boolean displayBackLines = false;
	public boolean antialiasing = true;
	public ArrayList<Arrow> arrows = new ArrayList();
	public boolean placeAssertionFrom = false;
	public boolean placeAssertionTo = false;
	public int assertionIndex = -1;
	private Cursor normalCursor = new Cursor(0);
	private Cursor handCursor = new Cursor(12);
	private Cursor moveCursor = new Cursor(13);
	private JPopupMenu busMenu = new JPopupMenu();
	private JMenuItem bus_name = new JMenuItem("Set Name");
	private JMenuItem bus_fill = new JMenuItem("Fill");
	private JMenuItem bus_clean = new JMenuItem("Clean");
	private JPopupMenu signalMenu = new JPopupMenu();
	private JMenu signal_style = new JMenu("Style");
	private JCheckBox signal_style_bold = new JCheckBox("Bold");
	private JMenu signal_style_color = new JMenu("Color");
	private JMenuItem signal_style_color_red = new JMenuItem("Red");
	private JMenuItem signal_style_color_blue = new JMenuItem("Blue");
	private JMenuItem signal_style_color_green = new JMenuItem("Green");
	private JMenuItem signal_style_color_orange = new JMenuItem("Orange");
	private JMenuItem signal_style_color_black = new JMenuItem("Black");
	private JMenuItem signal_properties = new JMenuItem("Properties");
	private JMenuItem signal_set_values = new JMenuItem("Set wave values");
	private JMenuItem signal_traceDFT = new JMenuItem("Trace DFT");
	private JMenuItem signal_delete = new JMenuItem("Delete");
	private boolean doubleClic = false;
	private boolean moveSelection = false;
	public static Font myFont = new Font("Arial", 0, 12);
	public static Font myBoldFont = new Font("Arial", 1, 12);
	public static FontMetrics metrics;
  
	public ChronoPanel()
	{
		addMouseListener(this);
		addMouseMotionListener(this);
    
	    this.busMenu.add(this.bus_name);
	    this.busMenu.add(this.bus_fill);
	    this.busMenu.add(this.bus_clean);
	    
	    this.signal_style.add(this.signal_style_bold);
	    
	    this.signal_style_color.add(this.signal_style_color_black);
	    this.signal_style_color.addSeparator();
	    this.signal_style_color.add(this.signal_style_color_blue);
	    this.signal_style_color.add(this.signal_style_color_green);
	    this.signal_style_color.add(this.signal_style_color_orange);
	    this.signal_style_color.add(this.signal_style_color_red);
	    this.signal_style.add(this.signal_style_color);
	    
	    this.signalMenu.add(this.signal_style);
	    this.signalMenu.add(this.signal_properties);
	    this.signalMenu.add(this.signal_set_values);
	    //this.signalMenu.addSeparator();
	    //this.signalMenu.add(this.signal_traceDFT);
	    //this.signalMenu.addSeparator();
	    this.signalMenu.add(this.signal_delete);
	    
	    popUpMenuInit();
	}
  
	public void reinit()
	{
		this.signals.clear();
		Signals.resetIdBank();
		this.elmt_to_edit = false;
		this.timeLapse = new int[5][4];
		this.nbrTimeLapse = 0;
		this.setTimeLapse = false;
		this.getTimeLapseWidth = false;
	}
  
	public void paintComponent(Graphics g)
	{
		ArrayList<VertLines> verts = new ArrayList();
		metrics = g.getFontMetrics(myFont);
		updateLeftSpace();
		if (this.antialiasing)
		{
			Graphics2D g2 = (Graphics2D)g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		}
		
		g.setColor(Color.white);
		g.fillRect(0, 0, getWidth(), getHeight());
		if (this.displayBackLines)
		{
			g.setColor(new Color(230, 230, 230));
			for (int i = 1; i < this.signals.size(); i += 2) 
			{
				g.fillRect(0, i * (Signals.heightUnit + Signals.Yspace) + Signals.Yspace / 2, ChronoFrame.WIDTH, Signals.heightUnit + Signals.Yspace);
			}
		}
		g.setColor(new Color(100, 100, 220));
    
		if (this.setTimeLapse) 
		{
			g.fillRect(this.timeLapse[this.nbrTimeLapse][0], 0, this.timeLapse[this.nbrTimeLapse][3] - this.timeLapse[this.nbrTimeLapse][0], ChronoFrame.HEIGHT);
		}
		g.setColor(Color.black);
    
		for (int i = 0; i < this.signals.size(); i++)
		{
			((Signals)this.signals.get(i)).draw(g, this, i, ChronoFrame.WIDTH, signals.get(i).type);
			
			if (((Signals)this.signals.get(i)).displayRisingEdges) 
			{
				verts.add(new VertLines((Signals)this.signals.get(i), ((Signals)this.signals.get(i)).widthUnit + Signals.leftSpace, ChronoFrame.WIDTH - 15, i, this.signals.size()));
			}
		}
    
		for (int i = 0; i < verts.size(); i++) 
		{
			((VertLines)verts.get(i)).draw(g, this);
		}
		
		for (int i = 0; i < this.arrows.size(); i++) 
		{
			((Arrow)this.arrows.get(i)).draw(g);
		}
	
	/////////////////////	Main.window.checkModifToSave();
	}
  
	
	public void add(Signals s)
	{
		changeClockDomain(s);
		this.signals.add(s);
		updateLeftSpace();
		this.modifToSave = true;
		repaint();
	}
  
	public void changeSelClockDomain(int id)
	{
		if ((this.elmt_to_edit) && (((Signals)this.signals.get(this.selected)).dependsOnClk))
		{
			((Signals)this.signals.get(this.selected)).clockDomainId = id;
			changeClockDomain((Signals)this.signals.get(this.selected));
		}
	}
  
	public void changeClockDomain(Signals s)
	{
		int period = 20;
		if ((s.id != s.clockDomainId) && (s.dependsOnClk))
		{
			for (int i = 0; i < this.signals.size(); i++) 
			{
				if ((((Signals)this.signals.get(i)).clock) && (((Signals)this.signals.get(i)).id == s.clockDomainId)) 
				{
					period = ((Signals)this.signals.get(i)).widthUnit;
				}
			}
			s.widthUnit = ((int)(period * s.ratio));
		}
	}
  
	public void updateClockDomain()
	{
		for (int i = 0; i < this.signals.size(); i++) 
		{
			changeClockDomain((Signals)this.signals.get(i));
		}
	}
  
	public void changeClockDomainName(int prevId, int newId)
	{
		for (int i = 0; i < this.signals.size(); i++) 
		{
			if (((Signals)this.signals.get(i)).clockDomainId == prevId)
			{
				((Signals)this.signals.get(i)).clockDomainId = newId;
				changeClockDomain((Signals)this.signals.get(i));
			}
		}
	}
  
	public void updateLeftSpace()
	{
		int lengthMax = 0;
		for (int i = 0; i < this.signals.size(); i++) 
		{
			if (metrics.stringWidth(((Signals)this.signals.get(i)).name) > lengthMax) 
			{
				lengthMax = metrics.stringWidth(((Signals)this.signals.get(i)).name);
			}
		}
		Signals.leftSpace = Math.max(lengthMax + 13, 30);
	}
  
	public void moveTo(int offset)
	{
		if ((this.elmt_to_edit) && (this.selected + offset >= 0) && (this.selected + offset < this.signals.size()))
		{
			Signals temp = (Signals)this.signals.get(this.selected);
			this.signals.remove(this.selected);
			this.signals.add(this.selected + offset, temp);
		}
	}
  
	public void removeSelected()
	{
		String warning = "";
		String toErase = "";
		if (this.assertionIndex > -1) 
		{
			toErase = "arrow assertion";
		} 
		else if (this.elmt_to_edit) 
		{
			toErase = ((Signals)this.signals.get(this.selected)).name + " signal";
		}
    
		int n = JOptionPane.showConfirmDialog(null, "Erase " + toErase + "?", "Confirmation", 0, 3);

		if (n == 0) 
		{
			if (this.assertionIndex > -1)
			{
				this.arrows.remove(this.assertionIndex);
			}
			else if (this.elmt_to_edit)
			{
				for (int i = 0; i < this.signals.size(); i++) 
				{
					if ((i != this.selected) && (((Signals)this.signals.get(i)).clockDomainId == ((Signals)this.signals.get(this.selected)).id)) 
					{
						warning = warning + "- " + ((Signals)this.signals.get(i)).name + "\n";
					}
				}
				if ((warning == "") || (!((Signals)this.signals.get(this.selected)).clock))
				{
					this.signals.remove(this.selected);
					this.selected = 0;
					this.elmt_to_edit = false;
				}
				else
				{
					JOptionPane.showMessageDialog(null, "These signals/bus are depending on " + ((Signals)this.signals.get(this.selected)).name + ":\n" + warning, "Warning", 2);
				}
			}
		}
	}
  
	public void changePeriod(int p)
	{
		if ((this.elmt_to_edit) && (((Signals)this.signals.get(this.selected)).clockDomainId == ((Signals)this.signals.get(this.selected)).id))
		{
			int clkId = ((Signals)this.signals.get(this.selected)).id;
      
			for (int i = 0; i < this.signals.size(); i++) 
			{
				if (((Signals)this.signals.get(i)).clockDomainId == clkId) 
				{
					((Signals)this.signals.get(i)).widthUnit = ((int)(p * ((Signals)this.signals.get(i)).ratio));
				}
			}
		}
	}
  
	public boolean checkIfSignalIndependent(int id)
	{
		boolean res = true;
		
		for (int i = 0; i < this.signals.size(); i++) 
		{
			if ((((Signals)this.signals.get(i)).id != id) && (((Signals)this.signals.get(i)).clock) && (((Signals)this.signals.get(i)).clockDomainId == id) && (((Signals)this.signals.get(i)).dependsOnClk)) 
			{
				res = false;
			}
		}
		return res;
	}
  
	public void addTimeLapse()
	{
		this.timeLapse[this.nbrTimeLapse][0] = 0;
		this.timeLapse[this.nbrTimeLapse][1] = 0;
		this.timeLapse[this.nbrTimeLapse][2] = 0;
		this.timeLapse[this.nbrTimeLapse][3] = 0;
		this.getTimeLapseWidth = false;
		this.setTimeLapse = true;
	}
  
	public void removeTimeLapse()
	{
		this.timeLapse = new int[5][4];
		this.nbrTimeLapse = 0;
	}
  
	public void newAssertion()
	{
		this.arrows.add(new Arrow(this));
		this.placeAssertionFrom = true;
	}
  
	public int getPosFromId(int id)
	{
		for (int i = 0; i < this.signals.size(); i++) 
		{
			if (((Signals)this.signals.get(i)).id == id) 
			{
				return i;
			}
		}
		return 0;
	}
  
	public void removeAssertions()
	{
		this.arrows.clear();
	}
  
	public void releaseSelection()
	{
		((Signals)this.signals.get(this.selected)).selected = false;
		if (this.assertionIndex >= 0) 
		{
			((Arrow)this.arrows.get(this.assertionIndex)).selected = false;
		}
		repaint();
	}
  
	/********************************/
	
	public void mouseClicked(MouseEvent e)
	{
		if (e.getX() < Signals.leftSpace) 
		{
			if (!this.doubleClic)
			{
				this.doubleClic = true;
				ActionListener taskPerformer = new ActionListener()
				{
					public void actionPerformed(ActionEvent evt)
					{
						ChronoPanel.this.doubleClic = false;
					}
				};
       
				Timer t = new Timer(500, taskPerformer);
				t.setRepeats(false);
				t.start();
			}
			else
			{
				this.doubleClic = false;
        
				editSignalProperties();
			}
		}
	}
  
	/********************************/
		
	public void mouseEntered(MouseEvent e) {}
  
	/********************************/
		
	public void mouseExited(MouseEvent e)
	{
		if ((this.selected >= 0) && (this.selected < this.signals.size())) 
		{
			((Signals)this.signals.get(this.selected)).selected = false;
		}
		this.moveSelection = false;
		repaint();
	}
  
	/********************************/
		
	public void mousePressed(MouseEvent e)
	{
		int nbr = (int)((e.getY() - Signals.Yspace / 2.0F) / (Signals.heightUnit + Signals.Yspace));
    
		if ((nbr >= 0) && (nbr < this.signals.size()) && (!this.setTimeLapse))
		{
			if ((!this.placeAssertionFrom) && (!this.placeAssertionTo))
			{
				if (e.getX() >= Signals.leftSpace)
				{
					this.modifToSave = true;
					if (e.getButton() == 1) 
					{
						((Signals)this.signals.get(nbr)).setWave(e.getX(), ((Signals)this.signals.get(nbr)).bus);
					}
					if (e.getButton() == 3)
					{
						if (!((Signals)this.signals.get(nbr)).bus) 
						{
							((Signals)this.signals.get(nbr)).setWave(e.getX(), true);
						}
						if (((Signals)this.signals.get(nbr)).bus)
						{
							this.selected_bus = nbr;
							this.bus_offset = e.getX();
							this.busMenu.show(this, e.getX(), e.getY());
						}
					}
				}
				else if (e.getX() < Signals.leftSpace)
				{
					if (e.getButton() == 1) 
					{
						this.moveSelection = true;
					}
					if (e.getButton() == 3)
					{
						this.modifToSave = true;
						this.selected_signal = nbr;
						this.signal_style_bold.setSelected(((Signals)this.signals.get(nbr)).bold);
						this.signal_set_values.setEnabled(true);
						this.signal_traceDFT.setEnabled(true);
						if ((((Signals)this.signals.get(nbr)).clock) || (((Signals)this.signals.get(nbr)).bus)) 
						{
							this.signal_set_values.setEnabled(false);
						}
						if (((Signals)this.signals.get(nbr)).bus)
						{
							this.signal_traceDFT.setEnabled(false);
						}
						this.signalMenu.show(this, e.getX(), e.getY());
					}
				}
			}
			else if (this.placeAssertionFrom)
			{
				this.placeAssertionFrom = false;
				this.placeAssertionTo = true;
			}
			else if (this.placeAssertionTo)
			{
				this.placeAssertionTo = false;
				((Arrow)this.arrows.get(this.arrows.size() - 1)).done();
			}
			repaint();
		}
		
		if (this.setTimeLapse) 
		{
			this.getTimeLapseWidth = true;
		}
	}
  
	/********************************/
		
	public void mouseReleased(MouseEvent e)
	{
		if (this.moveSelection)
		{
			this.moveSelection = false;
			setCursor(this.normalCursor);
			int nbr = (int)((e.getY() - Signals.Yspace) / (Signals.heightUnit + Signals.Yspace));
			if ((nbr >= 0) && (nbr < this.signals.size()))
			{
				moveTo(nbr - this.selected);
				repaint();
			}
		}
		if (this.getTimeLapseWidth)
		{
			this.getTimeLapseWidth = false;
			this.setTimeLapse = false;
      
			this.timeLapse[this.nbrTimeLapse][1] = (this.timeLapse[this.nbrTimeLapse][0] + (this.timeLapse[this.nbrTimeLapse][3] - this.timeLapse[this.nbrTimeLapse][0]) / 4);
      
			this.timeLapse[this.nbrTimeLapse][2] = (this.timeLapse[this.nbrTimeLapse][0] + 3 * (this.timeLapse[this.nbrTimeLapse][3] - this.timeLapse[this.nbrTimeLapse][0]) / 4);
      
			this.timeLapse[this.nbrTimeLapse][0] -= Signals.leftSpace;
			this.timeLapse[this.nbrTimeLapse][1] -= Signals.leftSpace;
			this.timeLapse[this.nbrTimeLapse][2] -= Signals.leftSpace;
			this.timeLapse[this.nbrTimeLapse][3] -= Signals.leftSpace;
      
			this.nbrTimeLapse += 1;
			sortTimeLapseArray();
      
			repaint();
		}
	}
  
	/********************************/
		
	public void mouseDragged(MouseEvent e)
	{
		if (this.moveSelection)
		{
			this.modifToSave = true;
			setCursor(this.moveCursor);
			int nbr = (int)((e.getY() - Signals.Yspace) / (Signals.heightUnit + Signals.Yspace));
			if ((nbr >= 0) && (nbr < this.signals.size()))
			{
				moveTo(nbr - this.selected);
				this.selected = nbr;
				repaint();
			}
		}
		if (this.getTimeLapseWidth)
		{
			this.modifToSave = true;
			this.timeLapse[this.nbrTimeLapse][3] = e.getX();
			repaint();
		}
	}
  
	/********************************/
		
	public void mouseMoved(MouseEvent e)
	{
		System.out.println("+++");
		
		setCursor(this.normalCursor);
    
		int nbr = (int)((e.getY() - Signals.Yspace / 2.0F) / (Signals.heightUnit + Signals.Yspace));
    
		if ((nbr >= 0) && (nbr < this.signals.size()) && (!this.setTimeLapse))
		{
			((Signals)this.signals.get(this.selected)).selected = false;
			((Signals)this.signals.get(nbr)).selected = true;
			this.elmt_to_edit = true;
			this.selected = nbr;
      
			if (e.getX() < Signals.leftSpace) 
			{
				setCursor(this.handCursor);
			}
			if (this.placeAssertionFrom) 
			{
				((Arrow)this.arrows.get(this.arrows.size() - 1)).setStart((Signals)this.signals.get(nbr), e.getX());
			}
			if (this.placeAssertionTo) 
			{
				((Arrow)this.arrows.get(this.arrows.size() - 1)).setEnd((Signals)this.signals.get(nbr), e.getX());
			}
			repaint();
		}
		else if ((this.selected >= 0) && (this.selected < this.signals.size()))
		{
			((Signals)this.signals.get(this.selected)).selected = false;
			repaint();
		}
		if ((this.setTimeLapse) && (!this.getTimeLapseWidth))
		{
			this.timeLapse[this.nbrTimeLapse][0] = e.getX();
			this.timeLapse[this.nbrTimeLapse][3] = (e.getX() + 1);
		}
    
		int dMin = 8;
		this.assertionIndex = -1;
		for (int i = 0; i < this.arrows.size(); i++)
		{
			((Arrow)this.arrows.get(i)).selected = false;
			if (((Arrow)this.arrows.get(i)).getDistance(e.getX(), e.getY()) < dMin)
			{
				dMin = ((Arrow)this.arrows.get(i)).getDistance(e.getX(), e.getY());
				this.assertionIndex = i;
			}
		}
    
		if (this.assertionIndex != -1) 
		{
			((Arrow)this.arrows.get(this.assertionIndex)).selected = true;
		}
	}
  
	/********************************/
		
	public void popUpMenuInit()
	{
		this.bus_name.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				DialogBox db = new DialogBox(null, "Set bus data name");
				db.showDialog();
				
				if (db.name != null)
				{
					((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_bus)).setBusName(ChronoPanel.this.bus_offset, db.name);
				}
				ChronoPanel.this.repaint();
			}
		});
		
		this.bus_fill.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_bus)).setBusFill(ChronoPanel.this.bus_offset, false);
				ChronoPanel.this.repaint();
			}
		});
    
		this.bus_clean.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_bus)).setBusName(ChronoPanel.this.bus_offset, null);
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_bus)).setBusFill(ChronoPanel.this.bus_offset, true);
				ChronoPanel.this.repaint();
			}
		});
		
		this.signal_style_bold.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).bold = ChronoPanel.this.signal_style_bold.isSelected();
				ChronoPanel.this.signalMenu.setVisible(false);
				ChronoPanel.this.repaint();
			}
		});
		
		this.signal_style_color_red.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).color = new Color(180, 0, 0);
				ChronoPanel.this.repaint();
			}
		});
    
		this.signal_style_color_blue.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).color = new Color(0, 0, 180);
				ChronoPanel.this.repaint();
			}
		});

		this.signal_style_color_orange.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).color = new Color(255, 102, 50);
				ChronoPanel.this.repaint();
			}
		});
    
		this.signal_style_color_green.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).color = new Color(0, 180, 0);
				ChronoPanel.this.repaint();
			}
		});
		
		this.signal_style_color_black.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal)).color = Color.black;
				ChronoPanel.this.repaint();
			}
		});
    
		this.signal_properties.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				ChronoPanel.this.editSignalProperties();
				ChronoPanel.this.repaint();
			}
		});
    
/*		
		this.signal_traceDFT.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				new TraceDFT((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected_signal), ChronoFrame.WIDTH);
				ChronoPanel.this.repaint();
			}
		});
*/		
		this.signal_set_values.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				DialogBox db = new DialogBox(null, "Set Wave Values", (Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected), true);
				db.showDialog();
				if (db.valid) 
				{
					for (int i = 0; i < ((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected)).wave.length; i++) 
					{
						((Signals)ChronoPanel.this.signals.get(ChronoPanel.this.selected)).wave[i] = db.waveSet[i];
					}
				}
				ChronoPanel.this.repaint();
			}
		});
    
		this.signal_delete.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				ChronoPanel.this.removeSelected();
				ChronoPanel.this.repaint();
			}
		});
	}
  
	public void editSignalProperties()
	{
		if (this.elmt_to_edit)
		{
			DialogBox db = new DialogBox(null, "Properties", (Signals)this.signals.get(this.selected));
			db.showDialog();
			if (db.valid)
			{
				this.modifToSave = true;
				if (db.name != null) 
				{
					((Signals)this.signals.get(this.selected)).name = db.name;
				}
				repaint();
        
				if (db.freq != -1)
				{
					changePeriod(db.freq);
				}
				repaint();
        
				if ((!((Signals)this.signals.get(this.selected)).clock) && (db.clockDomain != -1)) 
				{
					changeSelClockDomain(db.clockDomain);
				}
				repaint();
				
				if (((Signals)this.signals.get(this.selected)).clock)
				{
					((Signals)this.signals.get(this.selected)).displayRisingEdges = db.displayRisingEdges;
					((Signals)this.signals.get(this.selected)).generate(db.beginOnRisingEdge);
					if ((db.clockDomain != -1) && (db.clkDependency))
					{
						if (checkIfSignalIndependent(((Signals)this.signals.get(this.selected)).id))
						{
							((Signals)this.signals.get(this.selected)).ratio = db.ratio;
							((Signals)this.signals.get(this.selected)).dependsOnClk = true;
							changeSelClockDomain(db.clockDomain);
						}
						else
						{
							JOptionPane.showMessageDialog(null, ((Signals)this.signals.get(this.selected)).name + " can not depend on " + ((Signals)this.signals.get(db.clockDomain)).name + " as other clocks depend on " + ((Signals)this.signals.get(this.selected)).name, "Warning", 2);
						}
					}
					else
					{
						((Signals)this.signals.get(this.selected)).ratio = 1.0F;
						changeSelClockDomain(((Signals)this.signals.get(this.selected)).id);
						((Signals)this.signals.get(this.selected)).dependsOnClk = false;
						if (db.freq != -1) 
						{
							changePeriod(db.freq);
						}
					}
					updateClockDomain();
				}
				
				((Signals)this.signals.get(this.selected)).clkToQdelay = db.clkToQdelay;
				repaint();
        
				if (!((Signals)this.signals.get(this.selected)).bus)
				{
					if (!db.setUp) 
					{
						((Signals)this.signals.get(this.selected)).setUpTime = 0;
					}
					if (db.setUp) 
					{
						((Signals)this.signals.get(this.selected)).setUpTime = 8;
					}
					repaint();
				}
			}
		}
	}
  
	public void sortTimeLapseArray()
	{
	    int[][] temp = new int[9][4];
	    int[] rank = new int[this.nbrTimeLapse];
	    for (int i = 0; i < this.nbrTimeLapse; i++)
	    {
	      temp[i][0] = this.timeLapse[i][0];
	      temp[i][1] = this.timeLapse[i][1];
	      temp[i][2] = this.timeLapse[i][2];
	      temp[i][3] = this.timeLapse[i][3];
	    }
	    
	    for (int i = 0; i < this.nbrTimeLapse; i++)
	    {
	      rank[i] = i;
	      for (int j = 0; j < i; j++) {
	        if (this.timeLapse[i][0] < this.timeLapse[j][0])
	        {
	          rank[i] -= 1;
	          rank[j] += 1;
	        }
	      }
	    }
	    for (int i = 0; i < this.nbrTimeLapse; i++)
	    {
	      this.timeLapse[rank[i]][0] = temp[i][0];
	      this.timeLapse[rank[i]][1] = temp[i][1];
	      this.timeLapse[rank[i]][2] = temp[i][2];
	      this.timeLapse[rank[i]][3] = temp[i][3];
	    }
	}
}
