📄 circuitchangejobs.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: CircuitChangeJobs.java * * Copyright (c) 2006 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.tool.user;import com.sun.electric.database.IdMapper;import com.sun.electric.database.constraint.Layout;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.Dimension2D;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.geometry.ERectangle;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.geometry.PolyBase;import com.sun.electric.database.geometry.PolyMerge;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.EDatabase;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.network.Netlist;import com.sun.electric.database.network.Network;import com.sun.electric.database.prototype.NodeProto;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.Geometric;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.CodeExpression;import com.sun.electric.database.variable.DisplayedText;import com.sun.electric.database.variable.EditWindow_;import com.sun.electric.database.variable.ElectricObject;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.UserInterface;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.Layer;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Schematics;import com.sun.electric.tool.Job;import com.sun.electric.tool.JobException;import com.sun.electric.tool.io.FileType;import com.sun.electric.tool.io.input.LibraryFiles;import com.sun.electric.tool.user.dialogs.OpenFile;import com.sun.electric.tool.user.ui.EditWindow;import com.sun.electric.tool.user.ui.SizeListener;import com.sun.electric.tool.user.ui.StatusBar;import com.sun.electric.tool.user.ui.TopLevel;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.Serializable;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.swing.JOptionPane;/** * Class for Jobs that make changes to the circuit. */public class CircuitChangeJobs{ // constructor, never used CircuitChangeJobs() {} /****************************** NODE TRANSFORMATION ******************************/ public static class RotateSelected extends Job { private Cell cell; private int amount; private boolean mirror; private boolean mirrorH; private List<Geometric> highs; /** * @param cell * @param highs the highlighted objects (list of highlights) * @param amount angle in tenth degrees to rotate * @param mirror whether or not to mirror. if true, amount is ignored, and mirrorH is used. * @param mirrorH if true, mirror horizontally (flip over X-axis), otherwise mirror * vertically (flip over Y-axis). Ignored if mirror is false. */ public RotateSelected(Cell cell, List<Geometric> highs, int amount, boolean mirror, boolean mirrorH) { super("Rotate selected objects", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.amount = amount; this.mirror = mirror; this.mirrorH = mirrorH; this.highs = highs; startJob(); } public boolean doIt() throws JobException { // disallow rotating if lock is on if (cantEdit(cell, null, true, false, true) != 0) return false; // figure out which nodes get rotated/mirrored Set<Geometric> markObj = new HashSet<Geometric>(); int nicount = 0; NodeInst theNi = null; Rectangle2D selectedBounds = new Rectangle2D.Double(); for(Geometric geom : highs) { if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; if (cantEdit(cell, ni, true, false, true) != 0) { return false; } markObj.add(ni); if (nicount == 0) { selectedBounds.setRect(ni.getBounds()); } else { Rectangle2D.union(selectedBounds, ni.getBounds(), selectedBounds); } theNi = ni; nicount++; } // must be at least 1 node if (nicount <= 0) { System.out.println("Must select at least 1 node for rotation"); return false; } // if multiple nodes, find the center one if (nicount > 1) { Point2D center = new Point2D.Double(selectedBounds.getCenterX(), selectedBounds.getCenterY()); theNi = null; double bestdist = Integer.MAX_VALUE; for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (!markObj.contains(ni)) continue; double dist = center.distance(ni.getTrueCenter()); // LINTED "bestdist" used in proper order if (theNi == null || dist < bestdist) { theNi = ni; bestdist = dist; } } } // see which nodes already connect to the main rotation/mirror node (theNi) markObj.clear(); for(Geometric geom : highs) { if (!(geom instanceof ArcInst)) continue; ArcInst ai = (ArcInst)geom; markObj.add(ai); } spreadRotateConnection(theNi, markObj); // now make sure that it is all connected for(Geometric geom : highs) { if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; spreadRotateConnection(ni, markObj); } // do the rotation/mirror Orientation dOrient; if (mirror) { // do mirroring dOrient = mirrorH ? Orientation.Y : Orientation.X; } else { // do rotation dOrient = Orientation.fromAngle(amount); } AffineTransform trans = dOrient.rotateAbout(theNi.getAnchorCenter()); Point2D.Double tmpPt1 = new Point2D.Double(), tmpPt2 = new Point2D.Double(); // Rotate nodes in markObj for (Geometric geom : markObj) { if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; trans.transform(ni.getAnchorCenter(), tmpPt1); ni.rotate(dOrient); ni.move(tmpPt1.getX() - ni.getAnchorCenterX(), tmpPt1.getY() - ni.getAnchorCenterY()); } // Rotate arcs in markObj for (Geometric geom : markObj) { if (!(geom instanceof ArcInst)) continue; ArcInst ai = (ArcInst)geom; if (markObj.contains(ai.getHeadPortInst().getNodeInst())) trans.transform(ai.getHeadLocation(), tmpPt1); else tmpPt1.setLocation(ai.getHeadLocation()); if (markObj.contains(ai.getTailPortInst().getNodeInst())) trans.transform(ai.getTailLocation(), tmpPt2); else tmpPt2.setLocation(ai.getTailLocation()); ai.modify(tmpPt1.getX() - ai.getHeadLocation().getX(), tmpPt1.getY() - ai.getHeadLocation().getY(), tmpPt2.getX() - ai.getTailLocation().getX(), tmpPt2.getY() - ai.getTailLocation().getY()); } return true; } } /** * Helper method for rotation to mark selected nodes that need not be * connected with an invisible arc. */ private static void spreadRotateConnection(NodeInst theNi, Set<Geometric> markObj) { if (markObj.contains(theNi)) return; markObj.add(theNi); for(Iterator<Connection> it = theNi.getConnections(); it.hasNext(); ) { Connection con = it.next(); ArcInst ai = con.getArc(); if (!markObj.contains(ai)) continue; int otherEnd = 1 - con.getEndIndex(); NodeInst ni = ai.getPortInst(otherEnd).getNodeInst(); if (markObj.contains(ni)) continue; markObj.add(ni); spreadRotateConnection(ni, markObj); } } /****************************** NODE ALIGNMENT ******************************/ /** * This class implement the command to align objects to the grid. */ public static class AlignObjects extends Job { private List<Geometric> list; // list of highlighted objects to align private Dimension2D alignment; public AlignObjects(List<Geometric> highs, Dimension2D alignment) { super("Align Objects", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.list = highs; this.alignment = alignment; startJob(); } public boolean doIt() throws JobException { if (list.size() == 0) { System.out.println("Must select something before aligning it to the grid"); return false; } if (alignment.getWidth() <= 0 || alignment.getHeight() <= 0) { System.out.println("No alignment given: set Alignment Options first"); return false; } // first adjust the nodes int adjustedNodes = 0; for(Geometric geom : list) { if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; Point2D [] points = ni.getTrace(); if (points != null) { AffineTransform transOut = ni.pureRotateOut(); Point2D [] newPoints = new Point2D[points.length]; boolean changed = false; for(int i=0; i<points.length; i++) { if (points[i] == null) continue; Point2D newPoint = new Point2D.Double(points[i].getX() + ni.getAnchorCenterX(), points[i].getY() + ni.getAnchorCenterY()); transOut.transform(newPoint, newPoint); double oldX = newPoint.getX(); double oldY = newPoint.getY(); DBMath.gridAlign(newPoint, alignment); if (oldX != newPoint.getX() || oldY != newPoint.getY()) changed = true; newPoints[i] = newPoint; } if (changed) { adjustedNodes++; ni.setTrace(newPoints); } continue; } Point2D center = new Point2D.Double(ni.getAnchorCenterX(), ni.getAnchorCenterY()); DBMath.gridAlign(center, alignment); double bodyXOffset = center.getX() - ni.getAnchorCenterX(); double bodyYOffset = center.getY() - ni.getAnchorCenterY(); double portXOffset = bodyXOffset; double portYOffset = bodyYOffset; boolean mixedportpos = false; boolean firstPort = true; for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); ) { PortInst pi = pIt.next(); Poly poly = pi.getPoly(); Point2D portCenter = new Point2D.Double(poly.getCenterX(), poly.getCenterY()); DBMath.gridAlign(portCenter, alignment); double pXO = portCenter.getX() - poly.getCenterX(); double pYO = portCenter.getY() - poly.getCenterY(); if (firstPort) { firstPort = false; portXOffset = pXO; portYOffset = pYO; } else { if (portXOffset != pXO || portYOffset != pYO) mixedportpos = true; } } if (!mixedportpos) { bodyXOffset = portXOffset; bodyYOffset = portYOffset; } // if a primitive has an offset, see if the node edges are aligned if (bodyXOffset != 0 || bodyYOffset != 0) { if (!ni.isCellInstance()) { AffineTransform transr = ni.rotateOut(); Technology tech = ni.getProto().getTechnology(); Poly [] polyList = tech.getShapeOfNode(ni); for(int j=0; j<polyList.length; j++) { Poly poly = polyList[j]; poly.transform(transr); Rectangle2D bounds = poly.getBox(); if (bounds == null) continue; Point2D polyPoint1 = new Point2D.Double(bounds.getMinX(), bounds.getMinY()); Point2D polyPoint2 = new Point2D.Double(bounds.getMaxX(), bounds.getMaxY()); DBMath.gridAlign(polyPoint1, alignment); DBMath.gridAlign(polyPoint2, alignment); if (polyPoint1.getX() == bounds.getMinX() && polyPoint2.getX() == bounds.getMaxX()) bodyXOffset = 0; if (polyPoint1.getY() == bounds.getMinY() && polyPoint2.getY() == bounds.getMaxY()) bodyYOffset = 0; if (bodyXOffset == 0 && bodyYOffset == 0) break; } } } // move the node if (bodyXOffset != 0 || bodyYOffset != 0) { // turn off all constraints on arcs Map<ArcInst,Integer> constraints = new HashMap<ArcInst,Integer>(); for(Iterator<Connection> aIt = ni.getConnections(); aIt.hasNext(); ) { Connection con = aIt.next(); ArcInst ai = con.getArc(); int constr = 0; if (ai.isRigid()) constr |= 1; if (ai.isFixedAngle()) constr |= 2; constraints.put(ai, new Integer(constr)); } ni.move(bodyXOffset, bodyYOffset); adjustedNodes++; // restore arc constraints for(Iterator<Connection> aIt = ni.getConnections(); aIt.hasNext(); ) { Connection con = aIt.next(); ArcInst ai = con.getArc(); Integer constr = constraints.get(ai); if (constr == null) continue; if ((constr.intValue() & 1) != 0) ai.setRigid(true); if ((constr.intValue() & 2) != 0) ai.setFixedAngle(true); } } } // now adjust the arcs int adjustedArcs = 0; for(Geometric geom : list) { if (!(geom instanceof ArcInst)) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -