/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: AnnularRing.java * * Copyright (c) 2004, Oracle and/or its affiliates. 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 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.dialogs; import com.sun.electric.Main; import com.sun.electric.database.geometry.Dimension2D; import com.sun.electric.database.geometry.EPoint; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.Technology; import com.sun.electric.technology.technologies.Generic; import com.sun.electric.tool.Job; import com.sun.electric.tool.JobException; import com.sun.electric.tool.drc.DRC; import com.sun.electric.tool.user.User; import com.sun.electric.tool.user.ui.WindowFrame; import com.sun.electric.util.TextUtils; import com.sun.electric.util.math.DBMath; import java.awt.Frame; import java.awt.geom.Point2D; import java.util.Iterator; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.ListSelectionModel; /** * Class to handle the "Annular Ring" dialog. */ public class AnnularRing extends EDialog { private static double lastInner = 5; private static double lastOuter = 10; private static int lastSegments = 32; private static int lastDegrees = 360; private JList layerJList; private DefaultListModel layerModel; private Cell cell; // To have ability to store directly the PrimitiveNode and not // to depende on names to search the PrimitiveNode instance // and have ability to handle DRC Exclusion node private static class AnnularRingNode { public PrimitiveNode node; AnnularRingNode(PrimitiveNode t) { node = t; } // This avoids to call PrimitiveNode.toString() and get // extra text. public String toString() { return node.getName(); } } /** * Method to display the dialog for building annular rings. */ public static void showAnnularRingDialog() { Cell cell = WindowFrame.needCurCell(); if (cell == null) return; int total = 0; for(Iterator<PrimitiveNode> it = Technology.getCurrent().getNodes(); it.hasNext(); ) { PrimitiveNode np = it.next(); if (np.getFunction() == PrimitiveNode.Function.NODE) total++; } if (total == 0) { System.out.println("The " + Technology.getCurrent().getTechName() + " technology has no pure-layer nodes"); return; } AnnularRing dialog = new AnnularRing((Frame) Main.getCurrentJFrame(), cell); dialog.setVisible(true); } /** Creates new form AnnularRing */ private AnnularRing(Frame parent, Cell cell) { super(parent, true); this.cell = cell; initComponents(); getRootPane().setDefaultButton(ok); // make all text fields select-all when entered EDialog.makeTextFieldSelectAllOnTab(innerRadius); EDialog.makeTextFieldSelectAllOnTab(outerRadius); EDialog.makeTextFieldSelectAllOnTab(numSegments); EDialog.makeTextFieldSelectAllOnTab(numDegrees); Technology tech = Technology.getCurrent(); layerModel = new DefaultListModel(); layerJList = new JList(layerModel); layerJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); layerPane.setViewportView(layerJList); for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); ) { PrimitiveNode np = it.next(); if (np.getFunction() != PrimitiveNode.Function.NODE) continue; layerModel.addElement(new AnnularRingNode(np)); } layerModel.addElement(new AnnularRingNode(Generic.tech().drcNode)); layerModel.addElement(new AnnularRingNode(Generic.tech().afgNode)); layerJList.setSelectedIndex(0); innerRadius.setText(TextUtils.formatDistance(lastInner, tech)); outerRadius.setText(TextUtils.formatDistance(lastOuter, tech)); numSegments.setText(Integer.toString(lastSegments)); numDegrees.setText(Integer.toString(lastDegrees)); finishInitialization(); } protected void escapePressed() { cancelActionPerformed(null); } private void cacheValues() { Technology tech = Technology.getCurrent(); lastInner = TextUtils.atofDistance(innerRadius.getText(), tech); lastOuter = TextUtils.atofDistance(outerRadius.getText(), tech); lastSegments = TextUtils.atoi(numSegments.getText()); lastDegrees = TextUtils.atoi(numDegrees.getText()); } private void makeRing() { cacheValues(); if (lastSegments < 4) lastSegments = 4; if (lastDegrees <= 0) lastDegrees = 360; if (lastDegrees > 360) lastDegrees = 360; int degrees = lastDegrees * 10; // figure out what node to use PrimitiveNode np = ((AnnularRingNode)layerJList.getSelectedValue()).node; if (np == null) return; (new MakeAnnulus(cell, np, lastSegments, degrees, lastInner, lastOuter)).startJob(); } /** * This class finishes the Annular Ring command by creating the ring. */ public static class MakeAnnulus extends Job { private Cell cell; private PrimitiveNode np; private int segments, degrees; private double inner, outer; private NodeInst ni; private double snap; public MakeAnnulus(Cell cell, PrimitiveNode np, int segments, int degrees, double inner, double outer) { super("Make Annular Ring", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.np = np; this.segments = segments; this.degrees = degrees; this.inner = inner; this.outer = outer; this.ni = null; DRC.DRCPreferences dp = new DRC.DRCPreferences(false); snap = dp.getResolution(cell.getTechnology()); //startJob(); } public boolean doIt() throws JobException { Dimension2D dimSnap = new Dimension2D.Double(snap, snap); // allocate space for the trace int numSegments = segments + 1; if (inner == 0 && degrees < 3600) numSegments += 2; if (inner > 0) numSegments *= 2; EPoint [] points = new EPoint[numSegments]; int l = 0; if (inner > 0) { for(int i=0; i<=segments; i++) { int p = degrees * i / segments; double x = inner * DBMath.cos(p); double y = inner * DBMath.sin(p); Point2D pt = new Point2D.Double(x, y); DBMath.gridAlign(pt, dimSnap); points[l++] = new EPoint(pt.getX(), pt.getY()); } } if (inner == 0 && degrees < 3600) points[l++] = new EPoint(0, 0); for(int i=segments; i>=0; i--) { int p = degrees*i/segments; double x = outer * DBMath.cos(p); double y = outer * DBMath.sin(p); Point2D pt = new Point2D.Double(x, y); DBMath.gridAlign(pt, dimSnap); points[l++] = new EPoint(pt.getX(), pt.getY()); } if (inner == 0 && degrees < 3600) points[l++] = new EPoint(0, 0); double lX = points[0].getX(); double hX = lX; double lY = points[0].getY(); double hY = lY; for(int i=1; i<points.length; i++) { if (points[i].getX() < lX) lX = points[i].getX(); if (points[i].getX() > hX) hX = points[i].getX(); if (points[i].getY() < lY) lY = points[i].getY(); if (points[i].getY() > hY) hY = points[i].getY(); } double cX = (lX + hX) / 2; double cY = (lY + hY) / 2; for(int i=0; i<points.length; i++) { Point2D pt = new Point2D.Double(points[i].getX() - cX, points[i].getY() - cY); DBMath.gridAlign(pt, dimSnap); points[i] = new EPoint(pt.getX(), pt.getY()); } double sX = hX - lX; double sY = hY - lY; Point2D center = new Point2D.Double(0, 0); ni = NodeInst.makeInstance(np, center, sX, sY, cell); ni.setTrace(points); return true; } public NodeInst getNodeInst() { return ni; } } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { java.awt.GridBagConstraints gridBagConstraints; layerPane = new javax.swing.JScrollPane(); cancel = new javax.swing.JButton(); ok = new javax.swing.JButton(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); innerRadius = new javax.swing.JTextField(); outerRadius = new javax.swing.JTextField(); numSegments = new javax.swing.JTextField(); numDegrees = new javax.swing.JTextField(); getContentPane().setLayout(new java.awt.GridBagLayout()); setTitle("Annulus Construction"); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { closeDialog(evt); } }); layerPane.setMinimumSize(new java.awt.Dimension(200, 200)); layerPane.setPreferredSize(new java.awt.Dimension(200, 200)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(layerPane, gridBagConstraints); cancel.setText("Cancel"); cancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 6; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(cancel, gridBagConstraints); ok.setText("OK"); ok.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { okActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 6; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(ok, gridBagConstraints); jLabel1.setText("Layer to use for ring:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(jLabel1, gridBagConstraints); jLabel2.setText("Inner Radius:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(jLabel2, gridBagConstraints); jLabel3.setText("Outer Radius:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(jLabel3, gridBagConstraints); jLabel4.setText("Number of segments:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(jLabel4, gridBagConstraints); jLabel5.setText("Number of degrees:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 5; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(jLabel5, gridBagConstraints); innerRadius.setColumns(6); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; getContentPane().add(innerRadius, gridBagConstraints); outerRadius.setColumns(6); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; getContentPane().add(outerRadius, gridBagConstraints); numSegments.setColumns(6); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 4; getContentPane().add(numSegments, gridBagConstraints); numDegrees.setColumns(6); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 5; getContentPane().add(numDegrees, gridBagConstraints); pack(); }//GEN-END:initComponents private void okActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_okActionPerformed {//GEN-HEADEREND:event_okActionPerformed makeRing(); closeDialog(null); }//GEN-LAST:event_okActionPerformed private void cancelActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cancelActionPerformed {//GEN-HEADEREND:event_cancelActionPerformed cacheValues(); closeDialog(null); }//GEN-LAST:event_cancelActionPerformed /** Closes the dialog */ private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog setVisible(false); dispose(); }//GEN-LAST:event_closeDialog // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton cancel; private javax.swing.JTextField innerRadius; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JScrollPane layerPane; private javax.swing.JTextField numDegrees; private javax.swing.JTextField numSegments; private javax.swing.JButton ok; private javax.swing.JTextField outerRadius; // End of variables declaration//GEN-END:variables }