/* -*- tab-width: 4 -*-
 *
 * Electric(tm) VLSI Design System
 *
 * File: Via.java
 *
 * Copyright (c) 2008, Static Free Software. All rights reserved.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.sun.electric.tool.user.tecEditWizard;

import com.sun.electric.tool.user.Resources;
import com.sun.electric.util.TextUtils;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 * Class to handle the "Via" tab of the Numeric Technology Editor dialog.
 */
public class Via extends TechEditWizardPanel
{
    private JPanel via;
    private JComboBox whichVia;
    private JTextField size, spacing, arraySpacing, overhangInline;
    private JTextField sizeRule, spacingRule, arraySpacingRule, overhangInlineRule;
    private double [] vSize, vSpacing, vArraySpacing, vOverhangInline;
    private String [] vSizeRule, vSpacingRule, vArraySpacingRule, vOverhangInlineRule;
    private boolean dataChanging;

    /** Creates new form Via */
	public Via(TechEditWizard parent, boolean modal)
	{
		super(parent, modal);
        setTitle("Via");
        setName("");

        via = new JPanel();
        via.setLayout(new GridBagLayout());

        JLabel heading = new JLabel("Via Parameters");
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;   gbc.gridy = 0;
        gbc.gridwidth = 3;
        gbc.insets = new Insets(4, 4, 4, 4);
        via.add(heading, gbc);

        JLabel image = new JLabel();
		image.setIcon(Resources.getResource(getClass(), "Via.png"));
        gbc = new GridBagConstraints();
        gbc.gridx = 0;   gbc.gridy = 1;
        gbc.gridwidth = 3;
        gbc.insets = new Insets(4, 4, 4, 4);
        via.add(image, gbc);

        JLabel whichViaLabel = new JLabel("Which via:");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 2;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(4, 4, 1, 0);
        via.add(whichViaLabel, gbc);

        whichVia = new JComboBox();
		whichVia.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt) { viaChanged(); }
		});
        gbc = new GridBagConstraints();
        gbc.gridx = 1;   gbc.gridy = 2;
        gbc.insets = new Insets(4, 0, 4, 2);
        via.add(whichVia, gbc);

        JLabel l1 = new JLabel("Distance");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 3;
        via.add(l1, gbc);

        JLabel l2 = new JLabel("Rule Name");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 3;
        via.add(l2, gbc);

        JLabel sizeLabel = new JLabel("Via size (A):");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(4, 4, 1, 0);
        via.add(sizeLabel, gbc);

        size = new JTextField();
        size.getDocument().addDocumentListener(new ViaDocumentListener());
        size.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 4;
        gbc.insets = new Insets(4, 0, 1, 2);
        via.add(size, gbc);

        sizeRule = new JTextField();
        sizeRule.getDocument().addDocumentListener(new ViaDocumentListener());
        sizeRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 4;
        gbc.insets = new Insets(4, 0, 1, 2);
        via.add(sizeRule, gbc);

        JLabel spacingLabel = new JLabel("Via inline spacing (B):");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 5;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(1, 4, 1, 0);
        via.add(spacingLabel, gbc);

        spacing = new JTextField();
        spacing.getDocument().addDocumentListener(new ViaDocumentListener());
        spacing.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 5;
        gbc.insets = new Insets(1, 0, 1, 2);
        via.add(spacing, gbc);

        spacingRule = new JTextField();
        spacingRule.getDocument().addDocumentListener(new ViaDocumentListener());
        spacingRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 5;
        gbc.insets = new Insets(1, 0, 1, 2);
        via.add(spacingRule, gbc);

        JLabel arraySpacingLabel = new JLabel("Via array spacing (C):");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 6;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(1, 4, 1, 0);
        via.add(arraySpacingLabel, gbc);

        arraySpacing = new JTextField();
        arraySpacing.getDocument().addDocumentListener(new ViaDocumentListener());
        arraySpacing.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 6;
        gbc.insets = new Insets(1, 0, 1, 2);
        via.add(arraySpacing, gbc);

        arraySpacingRule = new JTextField();
        arraySpacingRule.getDocument().addDocumentListener(new ViaDocumentListener());
        arraySpacingRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 6;
        gbc.insets = new Insets(1, 0, 1, 2);
        via.add(arraySpacingRule, gbc);

        JLabel overhangInlineLabel = new JLabel("Via inline overhang (D):");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 7;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(1, 4, 4, 0);
        via.add(overhangInlineLabel, gbc);

        overhangInline = new JTextField();
        overhangInline.getDocument().addDocumentListener(new ViaDocumentListener());
        overhangInline.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 7;
        gbc.insets = new Insets(1, 0, 4, 2);
        via.add(overhangInline, gbc);

        overhangInlineRule = new JTextField();
        overhangInlineRule.getDocument().addDocumentListener(new ViaDocumentListener());
        overhangInlineRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 7;
        gbc.insets = new Insets(1, 0, 4, 2);
        via.add(overhangInlineRule, gbc);

        JLabel nano = new JLabel("Distances are in nanometers");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;   gbc.gridy = 8;
        gbc.gridwidth = 3;
        gbc.insets = new Insets(4, 4, 4, 4);
        via.add(nano, gbc);
	}

	/** return the panel to use for this Numeric Technology Editor tab. */
	public Component getComponent() { return via; }

	/** return the name of this Numeric Technology Editor tab. */
	public String getName() { return "Via"; }

	/**
	 * Method called at the start of the dialog.
	 * Caches current values and displays them in the Via tab.
	 */
	public void init()
	{
		// add appropriate number of via layers
		TechEditWizardData data = wizard.getTechEditData();
		int numVias = data.getNumMetalLayers() - 1;
		whichVia.removeAllItems();
        for(int i=0; i<numVias; i++)
	        whichVia.addItem((i+1) + " to " + (i+2));
		if (numVias > 0)
		{
		    vSize = new double[numVias];
		    vSizeRule = new String[numVias];
		    vSpacing = new double[numVias];
		    vSpacingRule = new String[numVias];
		    vArraySpacing = new double[numVias];
		    vArraySpacingRule = new String[numVias];
		    vOverhangInline = new double[numVias];
		    vOverhangInlineRule = new String[numVias];
	        for(int i=0; i<numVias; i++)
	        {
	        	WizardField tmp = data.getViaSize(i);
	        	vSize[i] = tmp.value;
	        	vSizeRule[i] = tmp.rule;
	        	tmp = data.getViaSpacing(i);
	        	vSpacing[i] = tmp.value;
	        	vSpacingRule[i] = tmp.rule;
	        	tmp = data.getViaArraySpacing(i);
	        	vArraySpacing[i] = tmp.value;
	        	vArraySpacingRule[i] = tmp.rule;
	        	tmp = data.getViaOverhangInline(i);
	        	vOverhangInline[i] = tmp.value;
	        	vOverhangInlineRule[i] = tmp.rule;
	        }
			whichVia.setSelectedIndex(0);
		}
	}

	/**
	 * Method called when the "OK" panel is hit.
	 * Updates any changed fields in the Via tab.
	 */
	public void term()
	{
		TechEditWizardData data = wizard.getTechEditData();
		int numVias = data.getNumMetalLayers() - 1;
        for(int i=0; i<numVias; i++)
        {
        	data.setViaSize(i, new WizardField(vSize[i], vSizeRule[i]));
        	data.setViaSpacing(i, new WizardField(vSpacing[i], vSpacingRule[i]));
        	data.setViaArraySpacing(i, new WizardField(vArraySpacing[i], vArraySpacingRule[i]));
        	data.setViaOverhangInline(i, new WizardField(vOverhangInline[i], vOverhangInlineRule[i]));
		}
	}

	private void viaChanged()
	{
		dataChanging = true;
		int which = whichVia.getSelectedIndex();
		if (which < 0 || vSize == null || which >= vSize.length)
		{
		    size.setText("");
		    sizeRule.setText("");
		    spacing.setText("");
		    spacingRule.setText("");
		    arraySpacing.setText("");
		    arraySpacingRule.setText("");
		    overhangInline.setText("");
		    overhangInlineRule.setText("");
		} else
		{
		    size.setText(TextUtils.formatDouble(vSize[which]));
		    sizeRule.setText(vSizeRule[which]);
		    spacing.setText(TextUtils.formatDouble(vSpacing[which]));
		    spacingRule.setText(vSpacingRule[which]);
		    arraySpacing.setText(TextUtils.formatDouble(vArraySpacing[which]));
		    arraySpacingRule.setText(vArraySpacingRule[which]);
		    overhangInline.setText(TextUtils.formatDouble(vOverhangInline[which]));
		    overhangInlineRule.setText(vOverhangInlineRule[which]);
		}
		dataChanging = false;
	}

	private void viaDataChanged()
	{
		if (dataChanging) return;
		int which = whichVia.getSelectedIndex();
		if (which < 0 || vSize == null || which >= vSize.length) return;
		vSize[which] = TextUtils.atof(size.getText());
		vSizeRule[which] = sizeRule.getText();
		vSpacing[which] = TextUtils.atof(spacing.getText());
		vSpacingRule[which] = spacingRule.getText();
		vArraySpacing[which] = TextUtils.atof(arraySpacing.getText());
		vArraySpacingRule[which] = arraySpacingRule.getText();
		vOverhangInline[which] = TextUtils.atof(overhangInline.getText());
		vOverhangInlineRule[which] = overhangInlineRule.getText();
	}

	/**
	 * Class to handle special changes to changes to a via size data.
	 */
	private class ViaDocumentListener implements DocumentListener
	{
		public void changedUpdate(DocumentEvent e) { viaDataChanged(); }
		public void insertUpdate(DocumentEvent e) { viaDataChanged(); }
		public void removeUpdate(DocumentEvent e) { viaDataChanged(); }
	}
}
