📄 exportchanges.java
字号:
public static class ExportsByNumber implements Comparator<Export> { /** * Method to sort Exports by their name. */ public int compare(Export e1, Export e2) { String s1 = e1.getName(); String s2 = e2.getName(); return TextUtils.STRING_NUMBER_ORDER.compare(s1, s2); } } /****************************** EXPORT HIGHLIGHTING ******************************/ private static class ShownPorts { Point2D loc; PortProto pp; int angle; } /** * Method to show all exports in the current cell. */ public static void showExports() { showPortsAndExports(null); } /** * Method to show all ports on the selected nodes in the current cell. */ public static void showPorts() { EditWindow wnd = EditWindow.getCurrent(); List<Geometric> nodes = wnd.getHighlighter().getHighlightedEObjs(true, false); if (nodes == null || nodes.size() == 0) { System.out.println("No nodes are highlighted"); return; } showPortsAndExports(nodes); } private static void showPortsAndExports(List<Geometric> nodes) { EditWindow wnd = EditWindow.needCurrent(); if (wnd == null) return; Cell cell = wnd.getCell(); if (cell == null) { System.out.println("No cell in this window"); return; } // determine the maximum number of ports to show int total = cell.getNumPorts(); if (nodes != null) { total = 0; for(Geometric geom : nodes) { NodeInst ni = (NodeInst)geom; total += ni.getNumPortInsts(); } } // associate ports with display locations (and compute the true number of ports to show) Rectangle2D displayable = wnd.displayableBounds(); ShownPorts [] portList = new ShownPorts[total]; total = 0; int ignored = 0; if (nodes == null) { // handle exports on the cell for(Iterator<PortProto> it = cell.getPorts(); it.hasNext(); ) { Export pp = (Export)it.next(); Poly poly = pp.getOriginalPort().getPoly(); Point2D ptOut = new Point2D.Double(poly.getCenterX(), poly.getCenterY()); if (ptOut.getX() < displayable.getMinX() || ptOut.getX() > displayable.getMaxX() || ptOut.getY() < displayable.getMinY() || ptOut.getY() > displayable.getMaxY()) { ignored++; continue; } portList[total] = new ShownPorts(); portList[total].loc = new Point2D.Double(poly.getCenterX(), poly.getCenterY()); portList[total].pp = pp; total++; } } else { // handle ports on the selected nodes for(Geometric geom : nodes) { NodeInst ni = (NodeInst)geom; for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); ) { PortInst pi = pIt.next(); Poly poly = pi.getPoly(); Point2D ptOut = new Point2D.Double(poly.getCenterX(), poly.getCenterY()); if (ptOut.getX() < displayable.getMinX() || ptOut.getX() > displayable.getMaxX() || ptOut.getY() < displayable.getMinY() || ptOut.getY() > displayable.getMaxY()) { ignored++; continue; } portList[total] = new ShownPorts(); portList[total].loc = new Point2D.Double(poly.getCenterX(), poly.getCenterY()); portList[total].pp = pi.getPortProto(); total++; } } } // determine the height of text in screen space int fontSize = EditWindow.getDefaultFontSize(); Point screenOrigin = wnd.databaseToScreen(0, 0); Point2D thPoint = wnd.screenToDatabase(screenOrigin.x, screenOrigin.y + fontSize); double textHeight = Math.abs(thPoint.getY()); // determine the location of the port labels Point2D [] labelLocs = new Point2D.Double[total]; double digitIndentX = displayable.getWidth() / 20; double digitIndentY = displayable.getHeight() / 20; int numPerSide = (total + 3) / 4; int leftSideCount, topSideCount, rightSideCount, botSideCount; leftSideCount = topSideCount = rightSideCount = botSideCount = numPerSide; if (leftSideCount + topSideCount + rightSideCount + botSideCount > total) botSideCount--; if (leftSideCount + topSideCount + rightSideCount + botSideCount > total) topSideCount--; if (leftSideCount + topSideCount + rightSideCount + botSideCount > total) rightSideCount--; int fill = 0; for(int i=0; i<leftSideCount; i++) { labelLocs[fill++] = new Point2D.Double(displayable.getMinX() + digitIndentX, displayable.getHeight() / (leftSideCount+1) * (i+1) + displayable.getMinY()); } for(int i=0; i<topSideCount; i++) { double shift = (i % 3) * textHeight - textHeight; labelLocs[fill++] = new Point2D.Double(displayable.getWidth() / (topSideCount+1) * (i+1) + displayable.getMinX(), displayable.getMaxY() - digitIndentY - shift); } for(int i=0; i<rightSideCount; i++) { labelLocs[fill++] = new Point2D.Double(displayable.getMaxX() - digitIndentX, displayable.getMaxY() - displayable.getHeight() / (rightSideCount+1) * (i+1)); } for(int i=0; i<botSideCount; i++) { double shift = (i % 3) * textHeight - textHeight; labelLocs[fill++] = new Point2D.Double(displayable.getMaxX() - displayable.getWidth() / (botSideCount+1) * (i+1), displayable.getMinY() + digitIndentY - shift); } // build a sorted list of ports around the center double x = 0, y = 0; for(int i=0; i<total; i++) { x += portList[i].loc.getX(); y += portList[i].loc.getY(); } Point2D center = new Point2D.Double(x / total, y / total); for(int i=0; i<total; i++) { if (center.getX() == portList[i].loc.getX() && center.getY() == portList[i].loc.getY()) portList[i].angle = 0; else portList[i].angle = -DBMath.figureAngle(center, portList[i].loc); } List<ShownPorts> portLabels = new ArrayList<ShownPorts>(); for(int i=0; i<total; i++) portLabels.add(portList[i]); Collections.sort(portLabels, new SortPortAngle()); total = 0; for(ShownPorts sp : portLabels) portList[total++] = sp; // figure out the best rotation offset double bestDist = 0; int bestOff = 0; for(int i=0; i<total; i++) { double dist = 0; for(int j=0; j<total; j++) dist += labelLocs[j].distance(portList[(j+i)%total].loc); if (dist < bestDist || i == 0) { bestOff = i; bestDist = dist; } } // show the ports Highlighter highlighter = wnd.getHighlighter(); Font font = wnd.getFont(null); FontRenderContext frc = new FontRenderContext(null, true, true); LineMetrics lm = font.getLineMetrics("hy", frc); double baselineVer = wnd.getTextUnitSize(lm.getDescent()); double baselineHor = wnd.getTextUnitSize(2); for(int i=0; i<total; i++) { int index = (bestOff + i) % total; Point2D loc = labelLocs[i]; String msg = portList[index].pp.getName(); // get the connecting-line coordinates in screen space Point locationLabel = wnd.databaseToScreen(loc.getX(), loc.getY()); Point locationPort = wnd.databaseToScreen(portList[index].loc.getX(), portList[index].loc.getY()); // determine the opposite corner of the text GlyphVector v = font.createGlyphVector(frc, msg); Rectangle2D glyphBounds = v.getLogicalBounds(); int otherX = locationLabel.x + (int)glyphBounds.getWidth(); int otherY = locationLabel.y - (int)glyphBounds.getHeight(); Point2D locOther = wnd.screenToDatabase(otherX, otherY); // if the text is off-screen, adjust it if (otherX > wnd.getSize().width) { int offDist = otherX - wnd.getSize().width; locationLabel.x -= offDist; otherX -= offDist; loc = wnd.screenToDatabase(locationLabel.x, locationLabel.y); } // change the attachment point on the label to be closest to the port if (Math.abs(locationPort.x-locationLabel.x) > Math.abs(locationPort.x-otherX)) locationLabel.x = otherX; if (Math.abs(locationPort.y-locationLabel.y) > Math.abs(locationPort.y-otherY)) locationLabel.y = otherY; // convert this shift back to database units for the highlight Point2D locLineEnd = wnd.screenToDatabase(locationLabel.x, locationLabel.y); // draw the port name highlighter.addMessage(cell, msg, new Point2D.Double(loc.getX()+baselineHor, loc.getY()+baselineVer)); // draw a box around the text Point2D odd1 = new Point2D.Double(loc.getX(), locOther.getY()); Point2D odd2 = new Point2D.Double(locOther.getX(), loc.getY()); highlighter.addLine(loc, odd1, cell); highlighter.addLine(odd1, locOther, cell); highlighter.addLine(locOther, odd2, cell); highlighter.addLine(odd2, loc, cell); // draw a line from the text to the port highlighter.addLine(locLineEnd, portList[index].loc, cell); } highlighter.finished(); System.out.println(total + " exported ports to show"); if (ignored > 0) System.out.println("Could not display " + ignored + " ports (outside of the window)"); } private static class SortPortAngle implements Comparator<ShownPorts> { public int compare(ShownPorts s1, ShownPorts s2) { return s1.angle - s2.angle; } } /****************************** EXPORT MATCHING BETWEEN LIBRARIES ******************************/ /** * Method to synchronize the exports in two libraries. * The user is prompted for another library (other than the current one) * and all exports in that library are copied to the current one. */ public static void synchronizeLibrary() { List<Library> libs = Library.getVisibleLibraries(); Library curLib = Library.getCurrent(); int otherLibraries = libs.size() - 1; if (otherLibraries < 1) { System.out.println("There must be an other library (not the current one) from which to copy exports."); return; } String [] libNames = new String[otherLibraries]; int i=0; for (Library oLib : libs) { if (oLib == curLib) continue; libNames[i++] = oLib.getName(); } String chosen = (String)JOptionPane.showInputDialog(TopLevel.getCurrentJFrame(), "Choose another library from which to copy exports", "Choose a Library", JOptionPane.QUESTION_MESSAGE, null, libNames, libNames[0]); if (chosen == null) return; Library oLib = Library.findLibrary(chosen); if (oLib == null) return; // now run the synchronization new SynchronizeExports(oLib); } /** * Class to synchronize exports in a separate Job. */ private static class SynchronizeExports extends Job { private Library oLib; private SynchronizeExports(Library oLib) { super("Synchronize exports", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.oLib = oLib; startJob(); } public boolean doIt() throws JobException { // merge the two libraries int newPorts = 0; boolean noCells = false; Library curLib = Library.getCurrent(); for(Iterator<Cell> cIt = curLib.getCells(); cIt.hasNext(); ) { Cell np = cIt.next(); // find this cell in the other library for(Iterator<Cell> oCIt = oLib.getCells(); oCIt.hasNext(); ) { Cell oNp = oCIt.next(); if (!np.getName().equals(oNp.getName())) continue; // synchronize the ports for(Iterator<PortProto> pIt = oNp.getPorts(); pIt.hasNext(); ) { Export oPp = (Export)pIt.next(); // see if that other cell's port is in this one Export pp = (Export)np.findPortProto(oPp.getName()); if (pp != null) continue; // must add port "oPp" to cell "np" NodeInst oNi = oPp.getOriginalPort().getNodeInst(); if (oNi.isCellInstance()) { if (!noCells) System.out.println("Cannot yet make exports that come from other cell instances (i.e. export " + oPp.getName() + " in " + oNp + ")"); noCells = true; continue; } // presume that the cells have the same coordinate system NodeInst ni = NodeInst.makeInstance(oNi.getProto(), oNi.getAnchorCenter(), oNi.getXSize(), oNi.getYSize(), np, oNi.getOrient(), oNi.getName(), oNi.getTechSpecific()); if (ni == null) continue; PortInst pi = ni.findPortInstFromProto(oPp.getOriginalPort().getPortProto()); pp = Export.newInstance(np, pi, oPp.getName(), oPp.getCharacteristic()); if (pp == null) continue; pp.copyTextDescriptorFrom(oPp, Export.EXPORT_NAME); pp.copyVarsFrom(oPp); newPorts++; } } } System.out.println("Created " + newPorts + " new exports in current " + curLib); return true; } } /****************************** REPLACING CELL INSTANCES FROM ANOTHER LIBRARY ******************************/ /** * Method to replace all cell instances in the current cell with like-named * ones from another library. */ public static void replaceFromOtherLibrary() { Cell curCell = WindowFrame.needCurCell(); if (curCell == null) return; List<Library> libs = Library.getVisibleLibraries(); Library curLib = Library.getCurrent(); int otherLibraries = libs.size() - 1; if (otherLibraries < 1) { System.out.println("There must be an other library (not the current one) from which to replace cells."); return; } String [] libNames = new String[otherLibraries]; int i=0; for (Library oLib : libs) { if (oLib == curLib) continue; libNames[i++] = oLib.getName(); } String chosen = (String)JOptionPane.showInputDialog(TopLevel.getCurrentJFrame(), "Choose another library from which to replace cell instances", "Choose a Library", JOptionPane.QUESTION_MESSAGE, null, libNames, libNames[0]); if (chosen == null) return; Library oLib = Library.findLibrary(chosen); if (oLib == null) return; // now run the replacement new ReplaceFromOtherLibrary(curCell, oLib); } /** * Class to replace all cell instances in the current cell with like-named * ones from another library. */ private static class ReplaceFromOtherLibrary extends Job { private Cell cell; private Library oLib; private ReplaceFromOtherLibrary(Cell cell, Library oLib) { super("Replace Cell Instances From Another Library", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.oLib = oLib; startJob(); } public boolean doIt() throws JobException { Map<NodeInst,Cell> cellsToReplace = new HashMap<NodeInst,Cell>(); for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (!ni.isCellInstance()) continue; if (ni.getXSize() != 0 || ni.getYSize() != 0) continue; Cell oldType = (Cell)ni.getProto(); if (oldType.getLibrary() == oLib) continue; String nameToFind = oldType.getName(); if (oldType.getView() != View.UNKNOWN) nameToFind += oldType.getView().getAbbreviationExtension(); Cell newType = oLib.findNodeProto(nameToFind); if (newType != null) { cellsToReplace.put(ni, newType); } } System.out.println("Changing " + cellsToReplace.size() + " cell instances..."); int replacements = 0; for(Iterator <NodeInst> it = cellsToReplace.keySet().iterator(); it.hasNext(); ) { NodeInst ni = it.next(); Cell newType = cellsToReplace.get(ni); ni.replace(newType, true, true); replacements++; } System.out.println("Changed " + replacements + " cell instances"); return true; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -