📄 export.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Export.java * * Copyright (c) 2003 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.database.hierarchy;import com.sun.electric.database.EObjectInputStream;import com.sun.electric.database.EObjectOutputStream;import com.sun.electric.database.ImmutableExport;import com.sun.electric.database.constraint.Constraints;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.id.ExportId;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.Name;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.Connection;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.DisplayedText;import com.sun.electric.database.variable.ElectricObject;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.PrimitivePort;import com.sun.electric.technology.technologies.Schematics;import com.sun.electric.tool.Job;import com.sun.electric.tool.user.ErrorLogger;import com.sun.electric.tool.user.User;import com.sun.electric.tool.user.ViewChanges;import com.sun.electric.tool.user.dialogs.BusParameters;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.IOException;import java.io.InvalidObjectException;import java.io.NotSerializableException;import java.util.Collections;import java.util.Iterator;/** * An Export is a PortProto at the Cell level. It points to the * PortInst that got exported, which identifies a NodeInst and a PortProto on that NodeInst. * <P> * An Export takes a PortInst on a NodeInst and makes it available as a PortInst * on instances of this NodeInst, farther up the hierarchy. * An Export therefore belongs to the NodeInst that is its source and also to the Cell * that the NodeInst belongs to. * The data structures look like this: * <P> * <CENTER><IMG SRC="doc-files/Export-1.gif"></CENTER> */public class Export extends ElectricObject implements PortProto, Comparable<Export>{ /** Empty Export array for initialization. */ public static final Export[] NULL_ARRAY = {}; /** Key of text descriptor of export name */ public static final Variable.Key EXPORT_NAME = Variable.newKey("EXPORT_name"); /** Key of Varible holding reference name. */ public static final Variable.Key EXPORT_REFERENCE_NAME = Variable.newKey("EXPORT_reference_name"); // -------------------------- private data --------------------------- /** persistent data of this Export. */ private ImmutableExport d; /** The parent Cell of this Export. */ private final Cell parent; /** Index of this Export in Cell ports. */ private int portIndex; /** the PortInst that the exported port belongs to */ private PortInst originalPort; // -------------------- protected and private methods -------------- /** * The constructor of Export. Use the factory "newInstance" instead. * @param d persistent data of this Export. * @param parent the Cell in which this Export will reside. */ Export(ImmutableExport d, Cell parent) { this.parent = parent; this.d = d; assert d.exportId.parentId == parent.getId(); originalPort = parent.getPortInst(d.originalNodeId, d.originalPortId); } private Object writeReplace() { return new ExportKey(this); } private static class ExportKey extends EObjectInputStream.Key<Export> { public ExportKey() {} private ExportKey(Export export) { super(export); } @Override public void writeExternal(EObjectOutputStream out, Export export) throws IOException { ExportId exportId = export.getId(); if (export.getDatabase() != out.getDatabase() || !export.isLinked()) throw new NotSerializableException(export + " not linked"); out.writeObject(exportId); } @Override public Export readExternal(EObjectInputStream in) throws IOException, ClassNotFoundException { ExportId exportId = (ExportId)in.readObject(); Export export = exportId.inDatabase(in.getDatabase()); if (export == null) throw new InvalidObjectException(exportId + " not linked"); return export; } } /****************************** CREATE, DELETE, MODIFY ******************************/ /** * Method to create an Export with the specified values. * @param parent the Cell in which this Export resides. * @param portInst the PortInst to export * @param protoName the name of this Export. * It may not have unprintable characters, spaces, or tabs in it. * @return the newly created Export. */ public static Export newInstance(Cell parent, PortInst portInst, String protoName) { return newInstance(parent, portInst, protoName, null, true); } /** * Method to create an Export with the specified values. * @param parent the Cell in which this Export resides. * @param portInst the PortInst to export * @param protoName the name of this Export. * It may not have unprintable characters, spaces, or tabs in it. * @param characteristic the characteristic (input, output) of this Export. * @return the newly created Export. */ public static Export newInstance(Cell parent, PortInst portInst, String protoName, PortCharacteristic characteristic) { return newInstance(parent, portInst, protoName, characteristic, true); } /** * Method to create an Export with the specified values. * @param parent the Cell in which this Export resides. * @param portInst the PortInst to export * @param protoName the name of this Export. * It may not have unprintable characters, spaces, or tabs in it. * @param characteristic the characteristic (input, output) of this Export. * @param createOnIcon true to create an equivalent export on any associated icon. * @return the newly created Export. */ public static Export newInstance(Cell parent, PortInst portInst, String protoName, PortCharacteristic characteristic, boolean createOnIcon) { if (protoName == null) return null; boolean busNamesAllowed = parent.busNamesAllowed(); Name protoNameKey = ImmutableExport.validExportName(protoName, busNamesAllowed); if (protoNameKey == null) { // hack: try removing offending characters protoName = protoName.replace(':', '_'); protoNameKey = ImmutableExport.validExportName(protoName, busNamesAllowed); if (protoNameKey == null) { System.out.println("Bad export name " + protoName + " : " + Name.checkName(protoName)); return null; } } if (parent.findExport(protoName) != null) { String oldName = protoName; protoName = ElectricObject.uniqueObjectName(protoName, parent, PortProto.class, false); if (protoName == null) { System.out.println(parent + " already has an export named " + oldName + ", export was not created"); return null; } System.out.println(parent + " already has an export named " + oldName + ", making new export named "+protoName); assert(parent.findExport(protoName) == null); } ExportId exportId = parent.getD().cellId.newPortId(protoName); if (exportId.inDatabase(parent.getDatabase()) != null) exportId = parent.getD().cellId.randomExportId(protoName); PortProto originalProto = portInst.getPortProto(); boolean alwaysDrawn = false; boolean bodyOnly = false; if (originalProto instanceof Export) { Export e = (Export)originalProto; alwaysDrawn = e.isAlwaysDrawn(); bodyOnly = e.isBodyOnly(); } PortCharacteristic newCharacteristic = characteristic; if (newCharacteristic == null) newCharacteristic = originalProto.getCharacteristic(); Export pp = newInstance(parent, exportId, protoName, smartPlacement(portInst), portInst, alwaysDrawn, bodyOnly, newCharacteristic, null); if (createOnIcon) { // if this was made on a schematic, and an icon exists, make the export on the icon as well Cell icon = parent.iconView(); if (icon != null && icon.findExport(protoName) == null) { // find analagous point to create export Rectangle2D bounds = parent.getBounds(); double locX = portInst.getPoly().getCenterX(); double locY = portInst.getPoly().getCenterY(); Rectangle2D iconBounds = icon.getBounds(); double newlocX = (locX - bounds.getMinX()) / bounds.getWidth() * iconBounds.getWidth() + iconBounds.getMinX(); newlocX = DBMath.toNearest(newlocX, Job.getUserInterface().getGridAlignment().getWidth()); double bodyDX = User.getIconGenLeadLength(); double distToXEdge = locX - bounds.getMinX(); if (locX >= bounds.getCenterX()) { bodyDX = -bodyDX; distToXEdge = bounds.getMaxX() - locX; } double newlocY = (locY - bounds.getMinY()) / bounds.getHeight() * iconBounds.getHeight() + iconBounds.getMinY(); newlocY = DBMath.toNearest(newlocY, Job.getUserInterface().getGridAlignment().getHeight()); double bodyDY = User.getIconGenLeadLength(); double distToYEdge = locY - bounds.getMinY(); if (locY >= bounds.getCenterY()) { bodyDY = -bodyDY; distToYEdge = bounds.getMaxY() - locY; } if (distToXEdge > distToYEdge) bodyDX = 0; else bodyDY = 0; // round Point2D point = new Point2D.Double(newlocX, newlocY); Job.getUserInterface().alignToGrid(point); newlocX = point.getX(); newlocY = point.getY(); // create export in icon int exportTech = User.getIconGenExportTech(); boolean drawLeads = User.isIconGenDrawLeads(); int exportStyle = User.getIconGenExportStyle(); int exportLocation = User.getIconGenExportLocation(); boolean ad = User.isIconsAlwaysDrawn(); int rotation = ViewChanges.iconTextRotation(pp, User.getIconGenInputRot(), User.getIconGenOutputRot(), User.getIconGenBidirRot(), User.getIconGenPowerRot(), User.getIconGenGroundRot(), User.getIconGenClockRot()); if (!ViewChanges.makeIconExport(pp, 0, newlocX, newlocY, newlocX+bodyDX, newlocY+bodyDY, icon, exportTech, drawLeads, exportStyle, exportLocation, rotation, ad)) { System.out.println("Warning: Failed to create associated export in icon "+icon.describe(true)); } } } return pp; } /** * Factory method to create an Export * @param parent the Cell in which this Export resides. * @param exportId ExportId of this Export * @param name the user name of this Export. if null then the same as id. * It may not have unprintable characters, spaces, or tabs in it. * @param nameTextDescriptor text descriptor of this Export * @param originalPort the PortInst that is being exported. * @param alwaysDrawn true if this Export is always drawn. * @param bodyOnly true to exclude this Export from icon. * @param characteristic PortCharacteristic of this Export. * @param errorLogger error logger to report errors. * @return created Export or null on error. */ public static Export newInstance(Cell parent, ExportId exportId, String name, TextDescriptor nameTextDescriptor, PortInst originalPort, boolean alwaysDrawn, boolean bodyOnly, PortCharacteristic characteristic, ErrorLogger errorLogger) { assert parent.isLinked(); String errorMsg = null; if (exportId.inDatabase(parent.getDatabase()) != null) { errorMsg = parent + " already has exportId " + exportId.externalId; System.out.println(errorMsg); errorLogger.logError(errorMsg, parent, 1); return null; } if (name == null) name = exportId.externalId; // initialize this object if (originalPort == null || !originalPort.isLinked()) { System.out.println("Null port on Export " + name + " in " + parent); return null; } NodeInst originalNode = originalPort.getNodeInst(); PortProto subpp = originalPort.getPortProto(); if (originalNode.getParent() != parent || subpp.getParent() != originalNode.getProto()) { System.out.println("Bad port on Export " + name + " in " + parent); return null; } if (ImmutableExport.validExportName(name, parent.busNamesAllowed()) == null) { errorMsg = parent + " has bad export name " + name + " "; String newName = repairExportName(parent, name); if (newName == null) newName = repairExportName(parent, "X"); if (newName == null) { errorMsg += " removed "; System.out.println(errorMsg); errorLogger.logError(errorMsg, parent, 1); return null; } errorMsg += " renamed to " + newName; name = newName; } if (nameTextDescriptor == null) nameTextDescriptor = TextDescriptor.getExportTextDescriptor(); ImmutableExport d = ImmutableExport.newInstance(exportId, Name.findName(name), nameTextDescriptor, originalNode.getD().nodeId, subpp.getId(), alwaysDrawn, bodyOnly, characteristic); Export e = new Export(d, parent); assert e.originalPort == originalPort; originalNode.redoGeometric(); parent.addExport(e); if (errorMsg != null) { System.out.println(errorMsg); if (errorLogger != null) errorLogger.logError(errorMsg, e, 1); } // handle change control, constraint, and broadcast Constraints.getCurrent().newObject(e); return e; } /** * Method to unlink this Export from its Cell. */ public void kill() { parent.killExports(Collections.singleton(this)); } /** * Method to rename this Export. * @param newName the new name of this Export. */ public void rename(String newName) { checkChanging(); // get unique name Cell cell = originalPort.getNodeInst().getParent(); // special case: if changing case only, allow it// if (!getName().equalsIgnoreCase(newName) || getName().equals(newName))// { // not changing case String dupName = ElectricObject.uniqueObjectName(newName, cell, PortProto.class, false); if (!dupName.equals(newName)) { System.out.println(cell + " already has an export named " + newName + ", making new export named "+dupName); newName = dupName; }// } Name newNameKey = ImmutableExport.validExportName(newName, cell.busNamesAllowed()); if (newNameKey == null) { System.out.println("Bad export name " + newName + " : " + Name.checkName(newName)); return; } // do the rename Name oldName = getNameKey(); parent.moveExport(portIndex, newName); setD(d.withName(newNameKey), true); // parent.notifyRename(false); // rename associated export in icon, if any Cell iconCell = cell.iconView(); if ((iconCell != null) && (iconCell != cell)) { for (Iterator<Export> it = iconCell.getExports(); it.hasNext(); ) { Export pp = it.next(); if (pp.getName().equals(oldName.toString())) { pp.rename(newName); break; } } } } /** * Method to move this Export to a different PortInst in the Cell. * The method expects both ports to be in the same place and simply shifts * the arcs without re-constraining them.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -