gt: 			for(int i=0; i<libs.length; i++)
context: /* -*- tab-width: 4 -*-
   *
   * Electric(tm) VLSI Design System
   *
   * File: Manipulate.java
   * Technology Editor, editing technology libraries
   * Written by Steven M. Rubin, Sun Microsystems.
   *
   * Copyright (c) 2005 Sun Microsystems and Static Free Software
   *
   * 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 Electric(tm); see the file COPYING.  If not, write to
   * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
   * Boston, Mass 02111-1307, USA.
   */
  package com.sun.electric.tool.user.tecEdit;
  
  import com.sun.electric.database.geometry.EGraphics;
  import com.sun.electric.database.geometry.ERectangle;
  import com.sun.electric.database.geometry.Poly;
  import com.sun.electric.database.hierarchy.Cell;
  import com.sun.electric.database.hierarchy.EDatabase;
  import com.sun.electric.database.hierarchy.Library;
  import com.sun.electric.database.id.CellId;
  import com.sun.electric.database.prototype.NodeProto;
  import com.sun.electric.database.prototype.PortProto;
  import com.sun.electric.database.text.TextUtils;
  import com.sun.electric.database.topology.ArcInst;
  import com.sun.electric.database.topology.Geometric;
  import com.sun.electric.database.topology.NodeInst;
  import com.sun.electric.database.variable.Variable;
  import com.sun.electric.technology.ArcProto;
  import com.sun.electric.technology.Layer;
  import com.sun.electric.technology.PrimitiveNode;
  import com.sun.electric.technology.PrimitivePort;
  import com.sun.electric.technology.Technology;
  import com.sun.electric.technology.Xml;
  import com.sun.electric.technology.technologies.Artwork;
  import com.sun.electric.technology.technologies.Generic;
  import com.sun.electric.tool.Job;
  import com.sun.electric.tool.JobException;
  import com.sun.electric.tool.extract.LayerCoverageTool;
  import com.sun.electric.tool.user.Highlighter;
  import com.sun.electric.tool.user.User;
  import com.sun.electric.tool.user.dialogs.ComponentMenu;
  import com.sun.electric.tool.user.dialogs.EDialog;
  import com.sun.electric.tool.user.dialogs.PromptAt;
  import com.sun.electric.tool.user.ui.EditWindow;
  import com.sun.electric.tool.user.ui.WindowFrame;
  
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.Graphics;
  import java.awt.GridBagConstraints;
  import java.awt.GridBagLayout;
  import java.awt.Insets;
  import java.awt.Point;
  import java.awt.Rectangle;
  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.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  import java.awt.geom.Point2D;
  import java.awt.geom.Rectangle2D;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.StringTokenizer;
  
  import javax.swing.DefaultListModel;
  import javax.swing.JButton;
  import javax.swing.JLabel;
  import javax.swing.JList;
  import javax.swing.JOptionPane;
  import javax.swing.JScrollPane;
  import javax.swing.JTextField;
  import javax.swing.ListCellRenderer;
  import javax.swing.ListSelectionModel;
  
  /**
   * This class manipulates technology libraries.
   */
  public class Manipulate
  {
  	/**
  	 * Method to update tables to reflect that cell "oldName" is now called "newName".
  	 * If "newName" is not valid, any rule that refers to "oldName" is removed.
  	 */
  	public static void renamedCell(String oldName, String newName)
  	{
  		// if this is a layer, rename the layer sequence array
  		if (oldName.startsWith("layer-") && newName.startsWith("layer-"))
  		{
  			renameSequence(Info.LAYERSEQUENCE_KEY, oldName.substring(6), newName.substring(6));
  		}
  
  		// if this is an arc, rename the arc sequence array
  		if (oldName.startsWith("arc-") && newName.startsWith("arc-"))
  		{
  			renameSequence(Info.ARCSEQUENCE_KEY, oldName.substring(4), newName.substring(4));
  		}
  
  		// if this is a node, rename the node sequence array
  		if (oldName.startsWith("node-") && newName.startsWith("node-"))
  		{
  			renameSequence(Info.NODESEQUENCE_KEY, oldName.substring(5), newName.substring(5));
  		}
  
  //		// see if there are design rules in the current library
  //		var = getval((INTBIG)el_curlib, VLIBRARY, VSTRING|VISARRAY, x_("EDTEC_DRC"));
  //		if (var == NOVARIABLE) return;
  //
  //		// examine the rules and convert the name
  //		len = getlength(var);
  //		sa = newstringarray(us_tool.cluster);
  //		for(i=0; i<len; i++)
  //		{
  //			// parse the DRC rule
  //			str = ((CHAR **)var.addr)[i];
  //			origstr = str;
  //			firstkeyword = getkeyword(&str, x_(" "));
  //			if (firstkeyword == NOSTRING) return;
  //
  //			// pass wide wire limitation through
  //			if (*firstkeyword == 'l')
  //			{
  //				addtostringarray(sa, origstr);
  //				continue;
  //			}
  //
  //			// rename nodes in the minimum node size rule
  //			if (*firstkeyword == 'n')
  //			{
  //				if (namesamen(oldName, x_("node-"), 5) == 0 &&
  //					namesame(&oldName[5], &firstkeyword[1]) == 0)
  //				{
  //					// substitute the new name
  //					if (namesamen(newName, x_("node-"), 5) == 0)
  //					{
  //						infstr = initinfstr();
  //						addstringtoinfstr(infstr, x_("n"));
  //						addstringtoinfstr(infstr, &newName[5]);
  //						addstringtoinfstr(infstr, str);
  //						addtostringarray(sa, returninfstr(infstr));
  //					}
  //					continue;
  //				}
  //				addtostringarray(sa, origstr);
  //				continue;
  //			}
  //
  //			// rename layers in the minimum layer size rule
  //			if (*firstkeyword == 's')
  //			{
  //				valid = TRUE;
  //				infstr = initinfstr();
  //				formatinfstr(infstr, x_("%s "), firstkeyword);
  //				keyword = getkeyword(&str, x_(" "));
  //				if (keyword == NOSTRING) return;
  //				if (namesamen(oldName, x_("layer-"), 6) == 0 &&
  //					namesame(&oldName[6], keyword) == 0)
  //				{
  //					if (namesamen(newName, x_("layer-"), 6) != 0) valid = FALSE; else
  //						addstringtoinfstr(infstr, &newName[6]);
  //				} else
  //					addstringtoinfstr(infstr, keyword);
  //				addstringtoinfstr(infstr, str);
  //				str = returninfstr(infstr);
  //				if (valid) addtostringarray(sa, str);
  //				continue;
  //			}
  //
  //			// layer width rule: substitute layer names
  //			infstr = initinfstr();
  //			formatinfstr(infstr, x_("%s "), firstkeyword);
  //			valid = TRUE;
  //
  //			// get the first layer name and convert it
  //			keyword = getkeyword(&str, x_(" "));
  //			if (keyword == NOSTRING) return;
  //			if (namesamen(oldName, x_("layer-"), 6) == 0 &&
  //				namesame(&oldName[6], keyword) == 0)
  //			{
  //				// substitute the new name
  //				if (namesamen(newName, x_("layer-"), 6) != 0) valid = FALSE; else
  //					addstringtoinfstr(infstr, &newName[6]);
  //			} else
  //				addstringtoinfstr(infstr, keyword);
  //			addtoinfstr(infstr, ' ');
  //
  //			// get the second layer name and convert it
  //			keyword = getkeyword(&str, x_(" "));
  //			if (keyword == NOSTRING) return;
  //			if (namesamen(oldName, x_("layer-"), 6) == 0 &&
  //				namesame(&oldName[6], keyword) == 0)
  //			{
  //				// substitute the new name
  //				if (namesamen(newName, x_("layer-"), 6) != 0) valid = FALSE; else
  //					addstringtoinfstr(infstr, &newName[6]);
  //			} else
  //				addstringtoinfstr(infstr, keyword);
  //
  //			addstringtoinfstr(infstr, str);
  //			str = returninfstr(infstr);
  //			if (valid) addtostringarray(sa, str);
  //		}
  //		strings = getstringarray(sa, &count);
  //		setval((INTBIG)el_curlib, VLIBRARY, x_("EDTEC_DRC"), (INTBIG)strings,
  //			VSTRING|VISARRAY|(count<<VLENGTHSH));
  //		killstringarray(sa);
  	}
  
  	/**
  	 * Method called when a cell has been deleted.
  	 */
  	public static void deletedCell(Cell np)
  	{
  		if (np.getName().startsWith("layer-"))
  		{
  			// may have deleted layer cell in technology library
  			String layerName = np.getName().substring(6);
  			StringBuffer warning = null;
  			for(Iterator<Cell> it = np.getLibrary().getCells(); it.hasNext(); )
  			{
  				Cell oNp = it.next();
  				boolean isNode = false;
  				if (oNp.getName().startsWith("node-")) isNode = true; else
  					if (!oNp.getName().startsWith("arc-")) continue;
  				for(Iterator<NodeInst> nIt = oNp.getNodes(); nIt.hasNext(); )
  				{
  					NodeInst ni = nIt.next();
  					Cell varCell = getLayerCell(ni);
  //					Variable var = ni.getVar(Info.LAYER_KEY);
  //					if (var == null) continue;
  //					CellId cID = (CellId)var.getObject();
  //					Cell varCell = EDatabase.serverDatabase().getCell(cID);
  					if (varCell == np)
  					{
  						if (warning != null) warning.append(","); else
  						{
  							warning = new StringBuffer();
  							warning.append("Warning: layer " + layerName + " is used in");
  						}
  						if (isNode) warning.append(" node " + oNp.getName().substring(5)); else
  							warning.append(" arc " + oNp.getName().substring(4));
  						break;
  					}
  				}
  			}
  			if (warning != null) System.out.println(warning.toString());
  
  			// see if this layer is mentioned in the design rules
  			renamedCell(np.getName(), "");
  		} else if (np.getName().startsWith("node-"))
  		{
  			// see if this node is mentioned in the design rules
  			renamedCell(np.getName(), "");
  		}
  	}
  
  	/**
  	 * Method to rename the layer/arc/node sequence arrays to account for a name change.
  	 * The sequence array is in variable "varName", and the item has changed from "oldName" to
  	 * "newName".
  	 */
  	private static void renameSequence(Variable.Key varName, String oldName, String newName)
  	{
  		Library lib = Library.getCurrent();
  		Variable var = lib.getVar(varName);
  		if (var == null) return;
  
  		String [] strings = (String [])var.getObject();
  		for(int i=0; i<strings.length; i++)
  			if (strings[i].equals(oldName)) strings[i] = newName;
  		lib.newVar(varName, strings);
  	}
  
  	/**
  	 * Method to determine whether it is legal to place an instance in a technology-edit cell.
  	 * @param np the type of node to create.
  	 * @param cell the cell in which to place it.
  	 * @return true if the creation is invalid (and prints an error message).
  	 */
  	public static boolean invalidCreation(NodeProto np, Cell cell)
  	{
  		// make sure the cell is right
  		if (!cell.getName().startsWith("node-") && !cell.getName().startsWith("arc-"))
  		{
  			System.out.println("Must be editing a node or arc to place geometry");
  			return true;
  		}
  		if (np == Generic.tech().portNode && !cell.getName().startsWith("node-"))
  		{
  			System.out.println("Can only place ports in node descriptions");
  			return true;
  		}
  		return false;
  	}
  
  	/**
  	 * Make a new technology-edit cell of a given type.
  	 * @param type 1=layer, 2=arc, 3=node, 4=factors
  	 */
  	public static void makeCell(int type)
  	{
  		Library lib = Library.getCurrent();
  		String cellName = null;
  		switch (type)
  		{
  			case 1:		// layer
  				String layerName = JOptionPane.showInputDialog("Name of new layer:", "");
  				if (layerName == null) return;
  				cellName = "layer-" + layerName + "{lay}";
  				break;
  			case 2:		// arc
  				String arcName = JOptionPane.showInputDialog("Name of new arc:", "");
  				if (arcName == null) return;
  				cellName = "arc-" + arcName + "{lay}";
  				break;
  			case 3:		// node
  				String nodeName = JOptionPane.showInputDialog("Name of new node:", "");
  				if (nodeName == null) return;
  				cellName = "node-" + nodeName + "{lay}";
  				break;
  			case 4:		// factors
  				cellName = "factors";
  				break;
  		}
  
  		// see if the cell exists
  		Cell cell = lib.findNodeProto(cellName);
  		if (cell != null)
  		{
  			// cell exists: put it in the current window
  			WindowFrame wf = WindowFrame.getCurrentWindowFrame();
  			if (wf != null) wf.setCellWindow(cell, null);
  			return;
  		}
  
  		// create the cell
  		new MakeOneCellJob(lib, cellName, type);
  	}
  
  	/**
  	 * Class to create a single cell in a technology-library.
  	 */
  	private static class MakeOneCellJob extends Job
  	{
  		private Library lib;
  		private String name;
  		private int type;
  		private Cell newCell;
  
  		private MakeOneCellJob(Library lib, String name, int type)
  		{
  			super("Make Cell in Technology-Library", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER);
  			this.lib = lib;
  			this.name = name;
  			this.type = type;
  			startJob();
  		}
  
  		public boolean doIt() throws JobException
  		{
  			newCell = Cell.makeInstance(lib, name);
  			if (newCell == null) return false;
  			newCell.setInTechnologyLibrary();
  			newCell.setTechnology(Artwork.tech());
  
  			// specialty initialization
  			switch (type)
  			{
  				case 1:
  					LayerInfo li = new LayerInfo();
  					li.generate(newCell);
  					break;
  				case 2:
  					ArcInfo aIn = new ArcInfo();
  					aIn.generate(newCell);
  					break;
  				case 3:
  					NodeInfo nIn = new NodeInfo();
  					nIn.generate(newCell);
  					break;
  			}
  
  			// show it
  			fieldVariableChanged("newCell");
  			return true;
  		}
  
          public void terminateOK()
          {
  			WindowFrame wf = WindowFrame.getCurrentWindowFrame();
  			if (wf != null && newCell != null) wf.setCellWindow(newCell, null);
          }
  	}
  
  	/**
  	 * Method to complete the creation of a new node in a technology edit cell.
  	 * @param newNi the node that was just created.
  	 */
  	public static void completeNodeCreation(NodeInst newNi, Variable v)
  	{
  		// postprocessing on the nodes
  		String portName = null;
  		if (newNi.getProto() == Generic.tech().portNode)
  		{
  			// a port layer
  			portName = JOptionPane.showInputDialog("Port name:", "");
  			if (portName == null) return;
  		}
  		boolean isHighlight = false;
  		if (v != null)
  		{
  			if (v.getObject() instanceof Integer &&
  				((Integer)v.getObject()).intValue() == Info.HIGHLIGHTOBJ)
  			{
  				isHighlight = true;
  			}
  		}
  		new AddTechEditMarks(newNi, isHighlight, portName);
  	}
  
  	/**
  	 * Class to prepare a NodeInst for technology editing.
  	 * Adds variables to the NodeInst which identify it to the technology editor.
  	 */
  	private static class AddTechEditMarks extends Job
  	{
  		private NodeInst newNi;
  		private boolean isHighlight;
  		private String portName;
  
  		private AddTechEditMarks(NodeInst newNi, boolean isHighlight, String portName)
  		{
  			super("Prepare node for technology editing", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER);
  			this.newNi = newNi;
  			this.isHighlight = isHighlight;
  			this.portName = portName;
  			startJob();
  		}
  
  		public boolean doIt() throws JobException
  		{
  			if (isHighlight)
  			{
  				newNi.newVar(Info.OPTION_KEY, new Integer(Info.HIGHLIGHTOBJ));
  				return true;
  			}
  
  			// set layer information
  			newNi.newVar(Info.OPTION_KEY, new Integer(Info.LAYERPATCH));
  
  			// postprocessing on the nodes
  			if (newNi.getProto() == Generic.tech().portNode)
  			{
  				// a port layer
  				newNi.newDisplayVar(Info.PORTNAME_KEY, portName);
  				return true;
  			}
  
  			// a real layer: default to the first one
  			String [] layerNames = getLayerNameList();
  			if (layerNames != null && layerNames.length > 0)
  			{
  				Cell cell = Library.getCurrent().findNodeProto(layerNames[0]);
  				if (cell != null)
  				{
  					newNi.newVar(Info.LAYER_KEY, cell.getId());
  					LayerInfo li = LayerInfo.parseCell(cell);
  					if (li != null)
  						setPatch(newNi, li.desc);
  				}
  			}
  			return true;
  		}
      }
  
  	/**
  	 * Method to reorganize the dependent libraries
  	 */
  	public static void editLibraryDependencies()
  	{
  		new EditDependentLibraries();
  	}
  
  	/**
  	 * Method to edit the component menu for the technology.
  	 */
  	public static void editComponentMenu()
  	{
  		// get information about arcs and nodes in the technology being edited
  		Library [] dependentlibs = Info.getDependentLibraries(Library.getCurrent());
  		Cell [] arcCells = Info.findCellSequence(dependentlibs, "arc-", Info.ARCSEQUENCE_KEY);
  		Cell [] nodeCells = Info.findCellSequence(dependentlibs, "node-", Info.NODESEQUENCE_KEY);
  
  		// get the XML string describing the component menu
  		String compMenuXML;
  		Variable var = Library.getCurrent().getVar(Info.COMPMENU_KEY);
  		if (var == null)
  		{
  			// construct a default component menu
  			List<Object> things = new ArrayList<Object>();
  
  			// add in arcs
  			for(int i=0; i<arcCells.length; i++)
  			{
  				String arcName = arcCells[i].getName().substring(4);
  				Xml.ArcProto curArc = new Xml.ArcProto();
                  curArc.name = arcName;
  				things.add(curArc);
  			}
  
  			// add in nodes
  			for(int i=0; i<nodeCells.length; i++)
  			{
  				Cell np = nodeCells[i];
  				NodeInfo nIn = NodeInfo.parseCell(np);
  				if (nIn.func == PrimitiveNode.Function.NODE) continue;
  				String nodeName = nodeCells[i].getName().substring(5);
  
  //				// see if there are custom overrides
  //				if (nIn.surroundOverrides != null)
  //				{
  //            		List<Object> tmp = new ArrayList<Object>();
  //            		for(int j=0; j<nIn.surroundOverrides.length; j++)
  //	            	{
  //            			int commaPos = nIn.surroundOverrides[j].indexOf(',');
  //            			if (commaPos < 0) continue;
  //            			Xml.MenuNodeInst xni = new MenuNodeInst();
  //            			xni.protoName = nodeName;
  //            			xni.function = nIn.func;
  //            			xni.text = nodeName + "-" + nIn.surroundOverrides[j].substring(0, commaPos);
  //            			xni.fontSize = 5;
  //            			tmp.add(xni);
  //            		}
  //    				things.add(tmp);
  //				} else
              	{
      				Xml.PrimitiveNode curNode = new Xml.PrimitiveNode();
                      curNode.name = nodeName;
                      curNode.function = nIn.func;
      				things.add(curNode);
              	}
  			}
  
  			// add in special menu entries
  			things.add(Technology.SPECIALMENUPURE);
  			things.add(Technology.SPECIALMENUMISC);
  			things.add(Technology.SPECIALMENUCELL);
  
  			// construct the menu information
  			int columns = (things.size()+13) / 14;
  			Xml.MenuPalette xmp = new Xml.MenuPalette();
  			xmp.numColumns = columns;
  			xmp.menuBoxes = new ArrayList<List<?>>();
  			for(Object item : things)
  			{
  				if (item instanceof List) xmp.menuBoxes.add((List)item); else
  				{
  					List<Object> subList = new ArrayList<Object>();
  					subList.add(item);
  					xmp.menuBoxes.add(subList);
  				}
  			}
  
  			compMenuXML = xmp.writeXml();
  		} else
  		{
  			compMenuXML = (String)var.getObject();
  		}
  	    List<Xml.PrimitiveNodeGroup> nodeGroups = new ArrayList<Xml.PrimitiveNodeGroup>();
  		for(int i=0; i<nodeCells.length; i++)
  		{
  			Xml.PrimitiveNodeGroup ng = new Xml.PrimitiveNodeGroup();
              Xml.PrimitiveNode n = new Xml.PrimitiveNode();
              ng.nodes.add(n);
  			n.name = nodeCells[i].getName().substring(5);
  			NodeInfo nIn = NodeInfo.parseCell(nodeCells[i]);
  			n.function = nIn.func;
  			nodeGroups.add(ng);
  		}
  	    List<Xml.ArcProto> arcs = new ArrayList<Xml.ArcProto>();
  		for(int i=0; i<arcCells.length; i++)
  		{
  			Xml.ArcProto xap = new Xml.ArcProto();
  			xap.name = arcCells[i].getName().substring(4);
  			arcs.add(xap);
  		}
  	    Xml.MenuPalette xmp = Xml.parseComponentMenuXMLTechEdit(compMenuXML, nodeGroups, arcs);
  	    ComponentMenu.showComponentMenuDialog(Library.getCurrent().getName(), xmp, nodeGroups, arcs);
  	}
  
  	/**
  	 * This class displays a dialog for editing library dependencies.
  	 */
  	private static class EditDependentLibraries extends EDialog
  	{
  		private JList allLibsList, depLibsList;
  		private DefaultListModel allLibsModel, depLibsModel;
  		private JTextField libToAdd;
  
  		/** Creates new form edit library dependencies */
  		private EditDependentLibraries()
  		{
  			super(null, true);
  			initComponents();
  			setVisible(true);
  		}
  
  		protected void escapePressed() { exit(false); }
  
  		// Call this method when the user clicks the OK button
  		private void exit(boolean goodButton)
  		{
  			if (goodButton)
  			{
  				int numDeps = depLibsModel.size();
  				String [] depLibs = new String[numDeps];
  				for(int i=0; i<numDeps; i++)
  					depLibs[i] = (String)depLibsModel.get(i);
  				new ModifyDependenciesJob(depLibs);
  			}
  			setVisible(false);
  			dispose();
  		}
  
  		/**
  		 * Class for saving library dependencies.
  		 */
  		private static class ModifyDependenciesJob extends Job
  		{
  			private String [] depLibs;
  
  			private ModifyDependenciesJob(String [] depLibs)
  			{
  				super("Modify Library Dependencies", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER);
  				this.depLibs = depLibs;
  				startJob();
  			}
  
  			public boolean doIt() throws JobException
  			{
  				Library lib = Library.getCurrent();
  				if (depLibs.length == 0)
  				{
  					if (lib.getVar(Info.DEPENDENTLIB_KEY) != null)
  						lib.delVar(Info.DEPENDENTLIB_KEY);
  				} else
  				{
  					lib.newVar(Info.DEPENDENTLIB_KEY, depLibs);
  				}
  				return true;
  			}
  		}
  
  		private void removeLib()
  		{
  			int index = depLibsList.getSelectedIndex();
  			if (index < 0) return;
  			depLibsModel.remove(index);
  		}
  
  		private void addLib()
  		{
  			String value = (String)allLibsList.getSelectedValue();
  			String specialLib = libToAdd.getText();
  			if (specialLib.length() > 0)
  			{
  				value = specialLib;
  				libToAdd.setText("");
  			}
  
  			if (value == null) return;
  			for(int i=0; i<depLibsModel.size(); i++)
  			{
  				String depLib = (String)depLibsModel.get(i);
  				if (depLib.equals(value)) return;
  			}
  			depLibsModel.addElement(value);
  		}
  
  		private void initComponents()
  		{
  			getContentPane().setLayout(new GridBagLayout());
  
  			setTitle("Dependent Library Selection");
  			setName("");
  			addWindowListener(new WindowAdapter()
  			{
  				public void windowClosing(WindowEvent evt) { exit(false); }
  			});
  
  			// left column
  			JLabel lab1 = new JLabel("Dependent Libraries:");
  			GridBagConstraints gbc = new GridBagConstraints();
  			gbc.gridx = 0;   gbc.gridy = 0;
  			gbc.anchor = GridBagConstraints.WEST;
  			gbc.insets = new Insets(4, 4, 4, 4);
  			getContentPane().add(lab1, gbc);
  
  			JScrollPane depLibsPane = new JScrollPane();
  			depLibsModel = new DefaultListModel();
  			depLibsList = new JList(depLibsModel);
  			depLibsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  			depLibsPane.setViewportView(depLibsList);
  			gbc = new GridBagConstraints();
  			gbc.gridx = 0;   gbc.gridy = 1;
  			gbc.gridheight = 4;
  			gbc.fill = GridBagConstraints.BOTH;
  			gbc.anchor = GridBagConstraints.WEST;
  			gbc.insets = new Insets(4, 4, 4, 4);
  			getContentPane().add(depLibsPane, gbc);
  			depLibsModel.clear();
  			Library [] libs = Info.getDependentLibraries(Library.getCurrent());
  