/* -*- tab-width: 4 -*-
 *
 * Electric(tm) VLSI Design System
 *
 * File: Metal.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.Job;
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.*;

/**
 * Class to handle the "Metal" tab of the Numeric Technology Editor dialog.
 */
public class Metal extends TechEditWizardPanel
{
    private JPanel metal;
    private JScrollPane metalPane;
    private MetalContainer[] metalContainers;
    private int numMetals;
    private TechEditWizard parent;

    private class MetalContainer
    {
        JLabel widthLabel, spacingLabel;
        JTextField spacing, spacingRule;
        JTextField width, widthRule;
    }

    /** Creates new form Metal */
	public Metal(TechEditWizard parent, boolean modal)
	{
		super(parent, modal);
		this.parent = parent;

        setTitle("Metal");
        setName("");

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

        metalPane = new javax.swing.JScrollPane();

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

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

        JButton addMetal = new JButton("Add Metal");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;   gbc.gridy = 2;
        gbc.insets = new Insets(4, 4, 4, 4);
        addMetal.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt) { addMetal(); }
        });
        metal.add(addMetal, gbc);

        JButton removeMetal = new JButton("Remove Metal");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;   gbc.gridy = 2;
        gbc.insets = new Insets(4, 4, 4, 4);
        removeMetal.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt) { removeMetal(); }
        });
        metal.add(removeMetal, gbc);

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

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

        metalPane.setViewportView(metal);

        getContentPane().setLayout(new java.awt.GridBagLayout());
        getContentPane().add(metalPane, new java.awt.GridBagConstraints());

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

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

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

	/**
	 * Method called at the start of the dialog.
	 * Caches current values and displays them in the Metal tab.
	 */
	public void init()
	{
		TechEditWizardData data = wizard.getTechEditData();
        numMetals = data.getNumMetalLayers();
        metalContainers = new MetalContainer[numMetals];
        for(int i=0; i<numMetals; i++)
        {
        	metalContainers[i] = addMetalLayer(i, data);
        }
	}

	/**
	 * Method to create the dialog fields for a metal layer.
	 * @param i the metal layer to fill-in.
	 */
	private MetalContainer addMetalLayer(int i, TechEditWizardData data)
	{
        MetalContainer mc = new MetalContainer();
        mc.widthLabel = new JLabel("Metal-" + (i+1) + " width (A):");
    	GridBagConstraints gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 4+i*2;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(4, 4, 1, 0);
        metal.add(mc.widthLabel, gbc);

        mc.width = new JTextField();
        mc.width.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 4+i*2;
        gbc.insets = new Insets(4, 0, 1, 2);
        metal.add(mc.width, gbc);

        mc.widthRule = new JTextField();
        mc.widthRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 4+i*2;
        gbc.insets = new Insets(4, 0, 1, 2);
        metal.add(mc.widthRule, gbc);

        mc.spacingLabel = new JLabel("Metal-" + (i+1) + " spacing (B):");
    	gbc = new GridBagConstraints();
    	gbc.gridx = 0;   gbc.gridy = 5+i*2;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(1, 4, 4, 0);
        metal.add(mc.spacingLabel, gbc);

        mc.spacing = new JTextField();
        mc.spacing.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 1;   gbc.gridy = 5+i*2;
        gbc.insets = new Insets(1, 0, 4, 2);
        metal.add(mc.spacing, gbc);

        mc.spacingRule = new JTextField();
        mc.spacingRule.setColumns(8);
    	gbc = new GridBagConstraints();
    	gbc.gridx = 2;   gbc.gridy = 5+i*2;
        gbc.insets = new Insets(1, 0, 4, 2);
        metal.add(mc.spacingRule, gbc);

        if (data != null)
        {
        	WizardField w = data.getMetalWidth(i);
            mc.width.setText(TextUtils.formatDouble(w.value));
            mc.widthRule.setText(w.rule);
            WizardField s = data.getMetalSpacing(i);
            mc.spacing.setText(TextUtils.formatDouble(s.value));
            mc.spacingRule.setText(s.rule);
        }

        return mc;
    }

	/**
	 * Method called when the user clicks "Add Metal"
	 */
	private void addMetal()
	{
        numMetals++;
        MetalContainer[] newMetalContainers = new MetalContainer[numMetals];
        System.arraycopy(metalContainers, 0, newMetalContainers, 0, numMetals-1);
        metalContainers = newMetalContainers;
	    metalContainers[numMetals-1] = addMetalLayer(numMetals-1, null);
		parent.pack();
	}

	/**
	 * Method called when the user clicks "Remove Metal"
	 */
	private void removeMetal()
	{
		if (numMetals <= 1)
		{
			Job.getUserInterface().showErrorMessage("Cannot delete the last metal layer: must be at least one",
				"Illegal Operation");
			return;
		}
        numMetals--;
        MetalContainer mc = metalContainers[numMetals];
        metalContainers[numMetals] = null;
        metal.remove(mc.widthLabel);
        metal.remove(mc.width);
        metal.remove(mc.widthRule);
        metal.remove(mc.spacingLabel);
        metal.remove(mc.spacing);
        metal.remove(mc.spacingRule);
		parent.pack();
	}

	/**
	 * Method called when the "OK" panel is hit.
	 * Updates any changed fields in the Metal tab.
	 */
	public void term()
	{
		TechEditWizardData data = wizard.getTechEditData();
		data.setNumMetalLayers(numMetals);
        for(int i=0; i<numMetals; i++)
        {
            MetalContainer mc = metalContainers[i];
        	data.setMetalWidth(i, new WizardField(TextUtils.atof(mc.width.getText()), mc.widthRule.getText()));
        	data.setMetalSpacing(i, new WizardField(TextUtils.atof(mc.spacing.getText()), mc.spacingRule.getText()));
        }
	}
}
