📄 manipulate.java
字号:
// OK and Cancel JButton cancel = new JButton("Cancel"); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 6; gbc.insets = new Insets(4, 4, 4, 4); getContentPane().add(cancel, gbc); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exit(false); } }); JButton ok = new JButton("OK"); getRootPane().setDefaultButton(ok); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 6; gbc.insets = new Insets(4, 4, 4, 4); getContentPane().add(ok, gbc); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exit(true); } }); pack(); } } /** * Method to highlight information about all layers (or ports if "doPorts" is true) */ public static void identifyLayers(boolean doPorts) { EditWindow wnd = EditWindow.getCurrent(); Cell np = WindowFrame.needCurCell(); if (wnd == null || np == null) return; if (doPorts) { if (!np.getName().startsWith("node-")) { System.out.println("Must be editing a node to identify ports"); return; } } else { if (!np.getName().startsWith("node-") && !np.getName().startsWith("arc-")) { System.out.println("Must be editing a node or arc to identify layers"); return; } } // get examples List<Example> neList = null; TechConversionResult tcr = new TechConversionResult(); if (np.getName().startsWith("node-")) neList = Example.getExamples(np, true, tcr); else neList = Example.getExamples(np, false, tcr); if (tcr.failed()) tcr.showError(); if (neList == null || neList.size() == 0) return; Example firstEx = neList.get(0); // count the number of appropriate samples in the main example int total = 0; for(Sample ns : firstEx.samples) { if (!doPorts) { if (ns.layer != Generic.tech().portNode) total++; } else { if (ns.layer == Generic.tech().portNode) total++; } } if (total == 0) { System.out.println("There are no " + (doPorts ? "ports" : "layers") + " to identify"); return; } // make arrays for position and association double [] xPos = new double[total]; double [] yPos = new double[total]; Poly.Type [] style = new Poly.Type[total]; Sample [] whichSam = new Sample[total]; // fill in label positions int qTotal = (total+3) / 4; Rectangle2D screen = wnd.getBoundsInWindow(); double ySep = screen.getHeight() / qTotal; double xSep = screen.getWidth() / qTotal; double indent = screen.getHeight() / 15; for(int i=0; i<qTotal; i++) { // label on the left side xPos[i] = screen.getMinX() + indent; yPos[i] = screen.getMinY() + ySep * i + ySep/2; style[i] = Poly.Type.TEXTLEFT; if (i+qTotal < total) { // label on the top side xPos[i+qTotal] = screen.getMinX() + xSep * i + xSep/2; yPos[i+qTotal] = screen.getMaxY() - indent; style[i+qTotal] = Poly.Type.TEXTTOP; } if (i+qTotal*2 < total) { // label on the right side xPos[i+qTotal*2] = screen.getMaxX() - indent; yPos[i+qTotal*2] = screen.getMinY() + ySep * i + ySep/2; style[i+qTotal*2] = Poly.Type.TEXTRIGHT; } if (i+qTotal*3 < total) { // label on the bottom side xPos[i+qTotal*3] = screen.getMinX() + xSep * i + xSep/2; yPos[i+qTotal*3] = screen.getMinY() + indent; style[i+qTotal*3] = Poly.Type.TEXTBOT; } } // fill in sample associations int k = 0; for(Sample ns : firstEx.samples) { if (!doPorts) { if (ns.layer != Generic.tech().portNode) whichSam[k++] = ns; } else { if (ns.layer == Generic.tech().portNode) whichSam[k++] = ns; } } // rotate through all configurations, finding least distance double bestDist = Double.MAX_VALUE; int bestRot = 0; for(int i=0; i<total; i++) { // find distance from each label to its sample center double dist = 0; for(int j=0; j<total; j++) dist += new Point2D.Double(xPos[j], yPos[j]).distance(new Point2D.Double(whichSam[j].xPos, whichSam[j].yPos)); if (dist < bestDist) { bestDist = dist; bestRot = i; } // rotate the samples Sample ns = whichSam[0]; for(int j=1; j<total; j++) whichSam[j-1] = whichSam[j]; whichSam[total-1] = ns; } // rotate back to the best orientation for(int i=0; i<bestRot; i++) { Sample ns = whichSam[0]; for(int j=1; j<total; j++) whichSam[j-1] = whichSam[j]; whichSam[total-1] = ns; } // draw the highlighting Highlighter highlighter = wnd.getHighlighter(); highlighter.clear(); for(int i=0; i<total; i++) { Sample ns = whichSam[i]; String msg = null; if (ns.layer == null) { msg = "HIGHLIGHT"; } else if (ns.layer == Generic.tech().cellCenterNode) { msg = "GRAB"; } else if (ns.layer == Generic.tech().portNode) { msg = Info.getPortName(ns.node); if (msg == null) msg = "?"; } else msg = ns.layer.getName().substring(6); Point2D curPt = new Point2D.Double(xPos[i], yPos[i]); highlighter.addMessage(np, msg, curPt); Rectangle2D nodeBounds = ns.node.getBaseShape().getBounds2D(); Point2D other = null; if (style[i] == Poly.Type.TEXTLEFT) { other = new Point2D.Double(nodeBounds.getMinX(), nodeBounds.getCenterY()); } else if (style[i] == Poly.Type.TEXTRIGHT) { other = new Point2D.Double(nodeBounds.getMaxX(), nodeBounds.getCenterY()); } else if (style[i] == Poly.Type.TEXTTOP) { other = new Point2D.Double(nodeBounds.getCenterX(), nodeBounds.getMaxY()); } else if (style[i] == Poly.Type.TEXTBOT) { other = new Point2D.Double(nodeBounds.getCenterX(), nodeBounds.getMinY()); } highlighter.addLine(curPt, other, np); } highlighter.finished(); } /** * Method to return information about a given object. */ public static String describeNodeMeaning(Geometric geom) { if (geom instanceof ArcInst) { // describe currently highlighted arc ArcInst ai = (ArcInst)geom; if (ai.getProto() != Generic.tech().universal_arc) return "This is an unimportant " + ai.getProto(); if (ai.getHeadPortInst().getNodeInst().getProto() != Generic.tech().portNode || ai.getTailPortInst().getNodeInst().getProto() != Generic.tech().portNode) return "This arc makes an unimportant connection"; String pt1 = Info.getPortName(ai.getHeadPortInst().getNodeInst()); String pt2 = Info.getPortName(ai.getTailPortInst().getNodeInst()); if (pt1 == null || pt2 == null) return "This arc connects two port objects"; return "This arc connects ports '" + pt1 + "' and '" + pt2 + "'"; } NodeInst ni = (NodeInst)geom; Cell cell = ni.getParent(); int opt = getOptionOnNode(ni); if (opt < 0) return "No relevance"; switch (opt) { case Info.TECHSHORTNAME: return "The technology name"; case Info.TECHSCALE: return "The technology scale"; case Info.TECHFOUNDRY: return "The technology's foundry"; case Info.TECHDEFMETALS: return "The number of metal layers in the technology"; case Info.TECHDESCRIPT: return "The technology description"; case Info.TECHSPICEMINRES: return "Minimum resistance of SPICE elements"; case Info.TECHSPICEMINCAP: return "Minimum capacitance of SPICE elements"; case Info.TECHMAXSERIESRES: return "Maximum series resistance of SPICE elements"; case Info.TECHGATESHRINK: return "The shrinkage of gates, in um"; case Info.TECHGATEINCLUDED: return "Whether gates are included in resistance"; case Info.TECHGROUNDINCLUDED: return "Whether to include the ground network in parasitics"; case Info.TECHTRANSPCOLORS: return "The transparent colors"; case Info.LAYER3DHEIGHT: return "The 3D height of " + cell; case Info.LAYER3DTHICK: return "The 3D thickness of " + cell; case Info.LAYERTRANSPARENCY: return "The transparency layer of " + cell; case Info.LAYERCIF: return "The CIF name of " + cell; case Info.LAYERCOLOR: return "The color of " + cell; case Info.LAYERLETTERS: return "The unique letter for " + cell + " (obsolete)"; case Info.LAYERDXF: return "The DXF name(s) of " + cell + " (obsolete)"; case Info.LAYERDRCMINWID: return "DRC minimum width " + cell + " (obsolete)"; case Info.LAYERFUNCTION: return "The function of " + cell; case Info.LAYERGDS: return "The Calma GDS-II number of " + cell; case Info.LAYERPATCONT: return "A stipple-pattern controller"; case Info.LAYERPATTERN: return "One of the bitmap squares in " + cell; case Info.LAYERSPICAP: return "The SPICE capacitance of " + cell; case Info.LAYERSPIECAP: return "The SPICE edge capacitance of " + cell; case Info.LAYERSPIRES: return "The SPICE resistance of " + cell; case Info.LAYERSTYLE: return "The style of " + cell; case Info.LAYERCOVERAGE: return "The desired coverage percentage for " + cell; case Info.ARCFIXANG: return "Whether " + cell + " is fixed-angle"; case Info.ARCFUNCTION: return "The function of " + cell; case Info.ARCINC: return "The prefered angle increment of " + cell; case Info.ARCNOEXTEND: return "The arc extension of " + cell; case Info.ARCWIPESPINS: return "Thie arc coverage of " + cell; case Info.ARCANTENNARATIO: return "The maximum antenna ratio for " + cell; case Info.ARCWIDTHOFFSET: return "The ELIB width offset for " + cell; case Info.NODEFUNCTION: return "The function of " + cell; case Info.NODELOCKABLE: return "Whether " + cell + " can be locked (used in array technologies)"; case Info.NODEMULTICUT: return "The separation between multiple contact cuts in " + cell + " (obsolete)"; case Info.NODESERPENTINE: return "Whether " + cell + " is a serpentine transistor"; case Info.NODESQUARE: return "Whether " + cell + " is square"; case Info.NODEWIPES: return "Whether " + cell + " disappears when conencted to one or two arcs"; case Info.NODESPICETEMPLATE: return "Spice template for " + cell; case Info.CENTEROBJ: return "The grab point of " + cell; case Info.LAYERPATCH: case Info.HIGHLIGHTOBJ: Cell np = getLayerCell(ni); if (np == null) return "Highlight box"; String msg = "Layer '" + np.getName().substring(6) + "'"; Variable var = ni.getVar(Info.MINSIZEBOX_KEY); if (var != null) msg += " (at minimum size)"; return msg; case Info.PORTOBJ: String pt = Info.getPortName(ni); if (pt == null) return "Unnamed port"; return "Port '" + pt + "'"; } return "Unknown information"; } /** * Method to obtain the layer associated with node "ni". Returns 0 if the layer is not * there or invalid. Returns null if this is the highlight layer. */ static Cell getLayerCell(NodeInst ni) { Variable var = ni.getVar(Info.LAYER_KEY); if (var == null) return null; CellId cID = (CellId)var.getObject(); Cell cell = EDatabase.serverDatabase().getCell(cID); if (cell != null) { // validate the reference for(Iterator<Cell> it = ni.getParent().getLibrary().getCells(); it.hasNext(); ) { Cell oCell = it.next(); if (oCell == cell) return cell; } } System.out.println("Layer " + cID.cellName + " not found"); return null; } /** * Method for modifying the selected object. If two are selected, connect them. */ public static void modifyObject(EditWindow wnd, NodeInst ni, int opt) { // handle other cases switch (opt) { case Info.TECHSHORTNAME: modTechShortName(wnd, ni); break; case Info.TECHSCALE: modTechScale(wnd, ni); break; case Info.TECHFOUNDRY: modTechFoundry(wnd, ni); break; case Info.TECHDEFMETALS: modTechNumMetals(wnd, ni); break; case Info.TECHDESCRIPT: modTechDescription(wnd, ni); break; case Info.TECHSPICEMINRES: modTechMinResistance(wnd, ni); break; case Info.TECHSPICEMINCAP: modTechMinCapacitance(wnd, ni); break; case Info.TECHMAXSERIESRES: modTechMaxSeriesResistance(wnd, ni);break; case Info.TECHGATESHRINK: modTechGateShrinkage(wnd, ni); break; case Info.TECHGATEINCLUDED: modTechGateIncluded(wnd, ni); break; case Info.TECHGROUNDINCLUDED:modTechGroundIncluded(wnd, ni); break; case Info.TECHTRANSPCOLORS: modTechTransparentColors(wnd, ni); break; case Info.LAYERFUNCTION: modLayerFunction(wnd, ni); break; case Info.LAYERCOLOR: modLayerColor(wnd, ni); break; case Info.LAYERTRANSPARENCY: modLayerTransparency(wnd, ni); break; case Info.LAYERSTYLE: modLayerStyle(wnd, ni); break; case Info.LAYERCIF: modLayerCIF(wnd, ni); break; case Info.LAYERGDS: modLayerGDS(wnd, ni); break; case Info.LAYERSPIRES: modLayerResistance(wnd, ni); break; case Info.LAYERSPICAP: modLayerCapacitance(wnd, ni); break; case Info.LAYERSPIECAP: modLayerEdgeCapacitance(wnd, ni); break; case Info.LAYER3DHEIGHT: modLayerHeight(wnd, ni); break; case Info.LAYER3DTHICK: modLayerThickness(wnd, ni); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -