📄 clipboard.java
字号:
// delete all exports in the clipboard Set<Export> exportsToDelete = new HashSet<Export>(); for(Iterator<Export> it = clipCell.getExports(); it.hasNext(); ) exportsToDelete.add(it.next()); clipCell.killExports(exportsToDelete); // delete all nodes in the clipboard Set<NodeInst> nodesToDelete = new HashSet<NodeInst>(); for(Iterator<NodeInst> it = clipCell.getNodes(); it.hasNext(); ) nodesToDelete.add(it.next()); clipCell.killNodes(nodesToDelete); // Delete all variables for(Iterator<Variable> it = clipCell.getParameters(); it.hasNext(); ) { Variable var = it.next(); clipCell.getCellGroup().delParam((Variable.AttrKey)var.getKey()); } for(Iterator<Variable> it = clipCell.getVariables(); it.hasNext(); ) { Variable var = it.next(); clipCell.delVar(var.getKey()); } } public static void copyListToClipboard(List<Geometric> geomList, List<DisplayedText> textList, Dimension2D alignment, AffineTransform inPlace, Orientation inPlaceOrient) { copyListToCell(clipCell, geomList, textList, null, null, new Point2D.Double(), User.isDupCopiesExports(), User.isArcsAutoIncremented(), alignment, inPlace, inPlaceOrient); } /** * Method to copy the list of Geometrics to a new Cell. * @param toCell the destination cell of the Geometrics. * @param geomList the list of Geometrics to copy. * @param textList the list of text to copy. * @param newGeomList the list of Geometrics that were created. * @param newTextList the list of text objects that were created. * @param delta an offset for all of the copied Geometrics. * @param copyExports true to copy exports. * @param uniqueArcs true to generate unique arc names. * @param alignment the grid alignment to use (0 for none). * @param inPlace the transformation to use which accounts for "down in place" editing. * @param inPlaceOrient the orientation to use which accounts for "down in place" editing. * @return the last NodeInst that was created. */ public static NodeInst copyListToCell(Cell toCell, List<Geometric> geomList, List<DisplayedText> textList, List<Geometric> newGeomList, List<DisplayedText> newTextList, Point2D delta, boolean copyExports, boolean uniqueArcs, Dimension2D alignment, AffineTransform inPlace, Orientation inPlaceOrient) { // make a list of all objects to be copied (includes end points of arcs) List<NodeInst> theNodes = new ArrayList<NodeInst>(); List<ArcInst> theArcs = new ArrayList<ArcInst>(); for (Geometric geom : geomList) { if (geom instanceof NodeInst) { if (!theNodes.contains(geom)) theNodes.add((NodeInst)geom); } if (geom instanceof ArcInst) { ArcInst ai = (ArcInst)geom; theArcs.add(ai); NodeInst head = ai.getHeadPortInst().getNodeInst(); NodeInst tail = ai.getTailPortInst().getNodeInst(); if (!theNodes.contains(head)) theNodes.add(head); if (!theNodes.contains(tail)) theNodes.add(tail); } } if (theNodes.size() == 0 && textList.size() == 0) return null; // check for recursion for(NodeInst ni : theNodes) { if (!ni.isCellInstance()) continue; Cell niCell = (Cell)ni.getProto(); if (Cell.isInstantiationRecursive(niCell, toCell)) { System.out.println("Cannot: that would be recursive (" + toCell + " is beneath " + ni.getProto() + ")"); return null; } } DBMath.gridAlign(delta, alignment); double dX = delta.getX(); double dY = delta.getY(); // sort the nodes by name Collections.sort(theNodes); // create the new nodes NodeInst lastCreatedNode = null; Map<NodeInst,NodeInst> newNodes = new HashMap<NodeInst,NodeInst>(); List<Export> reExports = new ArrayList<Export>(); for(NodeInst ni : theNodes) { if (ni.getProto() == Generic.tech().cellCenterNode && toCell.alreadyCellCenter()) continue; double width = ni.getXSize(); double height = ni.getYSize(); String name = null; if (ni.isUsernamed()) name = ElectricObject.uniqueObjectName(ni.getName(), toCell, NodeInst.class, false); EPoint point = new EPoint(ni.getAnchorCenterX()+dX, ni.getAnchorCenterY()+dY); Orientation orient = ni.getOrient(); if (inPlace != null) { Point2D dst = new Point2D.Double(0, 0); inPlace.transform(new Point2D.Double(ni.getAnchorCenterX(), ni.getAnchorCenterY()), dst); point = new EPoint(dst.getX()+dX, dst.getY()+dY); orient = orient.concatenate(inPlaceOrient); } NodeInst newNi = NodeInst.newInstance(ni.getProto(), point, width, height, toCell, orient, name, ni.getTechSpecific()); if (newNi == null) { System.out.println("Cannot create node"); return lastCreatedNode; } newNi.copyStateBits(ni); newNi.copyTextDescriptorFrom(ni, NodeInst.NODE_PROTO); newNi.copyTextDescriptorFrom(ni, NodeInst.NODE_NAME); newNi.copyVarsFrom(ni); newNodes.put(ni, newNi); if (newGeomList != null) newGeomList.add(newNi); lastCreatedNode = newNi; // copy the ports, too if (copyExports) { for(Iterator<Export> eit = ni.getExports(); eit.hasNext(); ) reExports.add(eit.next()); } } if (copyExports) { // sort list of original Exports and make list of PortInsts on new nodes Map<PortInst,Export> originalExports = new HashMap<PortInst,Export>(); Collections.sort(reExports, new ExportChanges.ExportSortedByBusIndex()); List<PortInst> reExpThese = new ArrayList<PortInst>(); for(Export e : reExports) { PortInst pi = e.getOriginalPort(); NodeInst newNi = newNodes.get(pi.getNodeInst()); PortInst newPi = newNi.findPortInstFromProto(pi.getPortProto()); reExpThese.add(newPi); originalExports.put(newPi, e); } ExportChanges.reExportPorts(toCell, reExpThese, false, true, true, false, originalExports); } Map<ArcInst,ArcInst> newArcs = new HashMap<ArcInst,ArcInst>(); if (theArcs.size() > 0) { // sort the arcs by name Collections.sort(theArcs); // for associating old names with new names Map<String,String> newArcNames = new HashMap<String,String>(); AffineTransform fixOffset = null; if (inPlaceOrient != null) fixOffset = inPlaceOrient.pureRotate(); // create the new arcs for(ArcInst ai : theArcs) { PortInst oldHeadPi = ai.getHeadPortInst(); NodeInst headNi = newNodes.get(oldHeadPi.getNodeInst()); PortInst headPi = headNi.findPortInstFromProto(oldHeadPi.getPortProto()); EPoint headP = oldHeadPi.getCenter(); double headDX = ai.getHeadLocation().getX() - headP.getX(); double headDY = ai.getHeadLocation().getY() - headP.getY(); PortInst oldTailPi = ai.getTailPortInst(); NodeInst tailNi = newNodes.get(oldTailPi.getNodeInst()); PortInst tailPi = tailNi.findPortInstFromProto(oldTailPi.getPortProto()); EPoint tailP = oldTailPi.getCenter(); double tailDX = ai.getTailLocation().getX() - tailP.getX(); double tailDY = ai.getTailLocation().getY() - tailP.getY(); // adjust offset if down-in-place if (fixOffset != null) { Point2D result = new Point2D.Double(0, 0); fixOffset.transform(new Point2D.Double(headDX, headDY), result); headDX = result.getX(); headDY = result.getY(); fixOffset.transform(new Point2D.Double(tailDX, tailDY), result); tailDX = result.getX(); tailDY = result.getY(); } String name = null; if (ai.isUsernamed()) { name = ai.getName(); if (uniqueArcs) { String newName = newArcNames.get(name); if (newName == null) { newName = ElectricObject.uniqueObjectName(name, toCell, ArcInst.class, false); newArcNames.put(name, newName); } name = newName; } } headP = new EPoint(headPi.getCenter().getX() + headDX, headPi.getCenter().getY() + headDY); tailP = new EPoint(tailPi.getCenter().getX() + tailDX, tailPi.getCenter().getY() + tailDY); ArcInst newAr = ArcInst.newInstanceBase(ai.getProto(), ai.getLambdaBaseWidth(), headPi, tailPi, headP, tailP, name, ai.getAngle()); if (newAr == null) { System.out.println("Cannot create arc"); return lastCreatedNode; } newAr.copyPropertiesFrom(ai); newArcs.put(ai, newAr); if (newGeomList != null) newGeomList.add(newAr); } } // copy variables on cells for(DisplayedText dt : textList) { ElectricObject eObj = dt.getElectricObject(); if (!(eObj instanceof Cell)) continue; Variable.Key varKey = dt.getVariableKey(); Variable var = eObj.getParameterOrVariable(varKey); double xP = var.getTextDescriptor().getXOff(); double yP = var.getTextDescriptor().getYOff(); Variable newVar = Variable.newInstance(varKey, var.getObject(), var.getTextDescriptor().withOff(xP+dX, yP+dY)); if (var.getTextDescriptor().isParam()) toCell.getCellGroup().addParam(newVar); else toCell.addVar(newVar); if (newTextList != null) newTextList.add(new DisplayedText(toCell, varKey)); } return lastCreatedNode; } private static void showCopiedObjects(List<Geometric> newGeomList, List<DisplayedText> newTextList) { EditWindow wnd = EditWindow.needCurrent(); if (wnd != null) { Cell cell = wnd.getCell(); Highlighter highlighter = wnd.getHighlighter(); highlighter.clear(); for(Geometric geom : newGeomList) { if (geom instanceof NodeInst) { NodeInst ni = (NodeInst)geom; // special case for displayable text on invisible pins if (ni.isInvisiblePinWithText()) { for(Iterator<Variable> vIt = ni.getVariables(); vIt.hasNext(); ) { Variable var = vIt.next(); if (!var.isDisplay()) continue; highlighter.addText(ni, cell, var.getKey()); } continue; } } highlighter.addElectricObject(geom, cell); } for(DisplayedText dt : newTextList) { highlighter.addText(dt.getElectricObject(), cell, dt.getVariableKey()); } highlighter.finished(); } } /** * Method to "paste" node "srcnode" onto node "destnode", making them the same. * Returns the address of the destination node (null on error). */ private static NodeInst pasteNodeToNode(NodeInst destNode, NodeInst srcNode) { destNode = CircuitChangeJobs.replaceNodeInst(destNode, srcNode.getProto(), true, false); if (destNode == null) return null; destNode.clearExpanded(); if (srcNode.isExpanded()) destNode.setExpanded(); if (!destNode.isCellInstance() && !srcNode.isCellInstance()) { if (srcNode.getProto().getTechnology() == destNode.getProto().getTechnology()) { Technology tech = srcNode.getProto().getTechnology(); tech.setPrimitiveFunction(destNode, srcNode.getFunction()); } } // make the sizes the same if they are primitives if (!destNode.isCellInstance()) { double dX = srcNode.getXSize() - destNode.getXSize(); double dY = srcNode.getYSize() - destNode.getYSize(); if (dX != 0 || dY != 0) { destNode.resize(dX, dY); } } // remove parameters that are not on the pasted object for(Iterator<Variable> it = destNode.getDefinedParameters(); it.hasNext(); ) { Variable destParam = it.next(); Variable.Key key = destParam.getKey(); if (!srcNode.isDefinedParameter(key)) destNode.delParameter(key); } // remove variables that are not on the pasted object boolean checkAgain = true; while (checkAgain) { checkAgain = false; for(Iterator<Variable> it = destNode.getVariables(); it.hasNext(); ) { Variable destVar = it.next(); Variable.Key key = destVar.getKey(); Variable srcVar = srcNode.getVar(key); if (srcVar != null) continue; destNode.delVar(key); checkAgain = true; break; } } // make sure all variables are on the node destNode.copyVarsFrom(srcNode); // copy any special user bits destNode.copyStateBits(srcNode); destNode.clearExpanded(); destNode.clearLocked(); return(destNode); } /** * Method to paste one arc onto another. * @param destArc the destination arc that will be replaced. * @param srcArc the source arc that will replace it. * @return the replaced arc (null on error). */ private static ArcInst pasteArcToArc(ArcInst destArc, ArcInst srcArc) { // make sure they have the same type if (destArc.getProto() != srcArc.getProto()) { destArc = destArc.replace(srcArc.getProto()); if (destArc == null) return null; } // make the widths the same destArc.setLambdaBaseWidth(srcArc.getLambdaBaseWidth()); // remove variables that are not on the pasted object boolean checkAgain = true; while (checkAgain) { checkAgain = false; for(Iterator<Variable> it = destArc.getVariables(); it.hasNext(); ) { Variable destVar = it.next(); Variable.Key key = destVar.getKey(); Variable srcVar = srcArc.getVar(key); if (srcVar != null) continue; destArc.delVar(key); checkAgain = true; break; } } // make sure all variables are on the arc for(Iterator<Variable> it = srcArc.getVariables(); it.hasNext(); ) { Variable srcVar = it.next(); Variable.Key key = srcVar.getKey(); destArc.newVar(key, srcVar.getObject(), srcVar.getTextDescriptor()); } // make sure the constraints and other userbits are the same destArc.copyPropertiesFrom(srcArc); return destArc; } /** * Gets a boundary representing the paste bounds of the list of objects. * The corners and center point of the bounds can be used as anchors * when pasting the objects interactively. This is all done in database units. * Note: you will likely want to grid align any points before using them. * @param pasteList a list of Geometrics to paste * @return a Rectangle2D that is the paste bounds. */ private static Rectangle2D getPasteBounds(List<Geometric> geomList, List<DisplayedText> textList, EditWindow wnd) { Point2D llcorner = null; Point2D urcorner = null; // figure out lower-left corner and upper-rigth corner of this collection of objects for(DisplayedText dt : textList) {// Poly poly = clipCell.computeTextPoly(wnd, dt.getVariableKey()); Poly poly = dt.getElectricObject().computeTextPoly(wnd, dt.getVariableKey()); Rectangle2D bounds = poly.getBounds2D(); if (llcorner == null) { llcorner = new Point2D.Double(bounds.getMinX(), bounds.getMinY());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -