📄 highlighter.java
字号:
} boolean areaMustEnclose = User.isDraggingMustEncloseObjects(); if (exclusively) { // special case: only review what is already highlighted for(Highlight2 h : highlighter.getHighlights()) { if (!(h instanceof HighlightEOBJ)) continue; ElectricObject eobj = h.getElectricObject(); if (eobj instanceof PortInst) eobj = ((PortInst)eobj).getNodeInst(); if (eobj instanceof NodeInst) { h = checkOutObject((Geometric)eobj, findPort, findPoint, findSpecial, bounds, wnd, Double.MAX_VALUE, areaMustEnclose); if (h != null) list.add(h); } } Job.releaseExamineLock(); return list; } // determine proper area to search Rectangle2D searchArea = new Rectangle2D.Double(bounds.getMinX() - directHitDist, bounds.getMinY() - directHitDist, bounds.getWidth()+directHitDist*2, bounds.getHeight()+directHitDist*2); // now do 3 phases of examination: cells, arcs, then primitive nodes for(int phase=0; phase<3; phase++) { // examine everything in the area for(Iterator<RTBounds> it = cell.searchIterator(searchArea); it.hasNext(); ) { Geometric geom = (Geometric)it.next(); Highlight2 h; switch (phase) { case 0: // check primitive nodes if (!(geom instanceof NodeInst)) break; if (((NodeInst)geom).isCellInstance()) break; h = checkOutObject(geom, findPort, findPoint, findSpecial, bounds, wnd, directHitDist, areaMustEnclose); if (h != null) list.add(h); break; case 1: // check Cell instances if (!findSpecial && !User.isEasySelectionOfCellInstances()) break; // ignore cells if requested if (!(geom instanceof NodeInst)) break; if (!((NodeInst)geom).isCellInstance()) break; h = checkOutObject(geom, findPort, findPoint, findSpecial, bounds, wnd, directHitDist, areaMustEnclose); if (h != null) list.add(h); break; case 2: // check arcs if (!(geom instanceof ArcInst)) break; h = checkOutObject(geom, findPort, findPoint, findSpecial, bounds, wnd, directHitDist, areaMustEnclose); if (h != null) list.add(h); break; } } } Job.releaseExamineLock(); } catch (Error e) { Job.releaseExamineLock(); throw e; } return list; } /** * Class to define an R-Tree leaf node for cell text. */ private static class TextHighlightBound implements RTBounds { private Rectangle2D bound; private ElectricObject obj; private Variable.Key key; TextHighlightBound(Rectangle2D bound, ElectricObject obj, Variable.Key key) { this.bound = new Rectangle2D.Double(bound.getMinX(), bound.getMinY(), bound.getWidth(), bound.getHeight()); this.obj = obj; this.key = key; } public Rectangle2D getBounds() { return bound; } public ElectricObject getElectricObject() { return obj; } public Variable.Key getKey() { return key; } public String toString() { return "TextBound"; } } /** * Method to locate text in an area, using the window's cache of text locations. * @param cell the Cell to examine. * @param wnd the EditWindow that the cell is displayed in. * @param directHitDist the distance to consider a direct hit. * @param bounds the area to search (all text in this bound will be returned in "list"). * @param findSpecial true to find "hard-to-select" text. * @param list the place to add selected text. */ private static void findTextNow(Cell cell, EditWindow wnd, double directHitDist, Rectangle2D bounds, boolean findSpecial, List<Highlight2> list) { // get the window's cache of text locations RTNode rtn = wnd.getTextInCell(); if (rtn == null) { // must rebuild the RTree of text in this cell rtn = RTNode.makeTopLevel(); // create temporary Rectangle Rectangle2D textBounds = new Rectangle2D.Double(); // start by examining all text on this Cell if (User.isTextVisibilityOnCell()) { Poly [] polys = cell.getAllText(findSpecial, wnd); if (polys != null) { for(int i=0; i<polys.length; i++) { Poly poly = polys[i]; if (poly == null) continue; if (poly.setExactTextBounds(wnd, cell)) continue; // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(poly.getBounds2D(), cell, poly.getDisplayedText().getVariableKey())); } } } // next examine all text on nodes in the cell for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni == null) { if (Job.getDebug()) System.out.println("Something is wrong in Highlighter:findAllInArea"); continue; } // check out node text if (User.isTextVisibilityOnNode()) { // first see if cell name text is selectable if (ni.isCellInstance() && !ni.isExpanded() && findSpecial && User.isTextVisibilityOnInstance()) { Poly.Type style = getHighlightTextStyleBounds(wnd, ni, NodeInst.NODE_PROTO, textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, ni, NodeInst.NODE_PROTO)); } } // now see if node is named if (ni.isUsernamed()) { Poly.Type style = getHighlightTextStyleBounds(wnd, ni, NodeInst.NODE_NAME, textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, ni, NodeInst.NODE_NAME)); } } // look at all variables on the node if (ni.getProto() != Generic.tech().invisiblePinNode || User.isTextVisibilityOnAnnotation()) { for(Iterator<Variable> vIt = ni.getParametersAndVariables(); vIt.hasNext(); ) { Variable var = vIt.next(); if (!var.isDisplay()) continue; Poly.Type style = getHighlightTextStyleBounds(wnd, ni, var.getKey(), textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, ni, var.getKey())); } } } // look at variables on ports on the node if (User.isTextVisibilityOnPort()) { for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); ) { PortInst pi = pIt.next(); for(Iterator<Variable> vIt = pi.getVariables(); vIt.hasNext(); ) { Variable var = vIt.next(); if (!var.isDisplay()) continue; Poly.Type style = getHighlightTextStyleBounds(wnd, pi, var.getKey(), textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, pi, var.getKey())); } } } } } // add export text if (User.isTextVisibilityOnExport()) { NodeProto np = ni.getProto(); if (!(np instanceof PrimitiveNode) || ((PrimitiveNode)np).isVisible()) { for(Iterator<Export> eIt = ni.getExports(); eIt.hasNext(); ) { Export pp = eIt.next(); if (pp == null) continue; // in case of massive delete -> Swing accesses objects that are currently being modified Poly.Type style = getHighlightTextStyleBounds(wnd, pp, Export.EXPORT_NAME, textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, pp, Export.EXPORT_NAME)); } // add in variables on the exports for(Iterator<Variable> vIt = pp.getVariables(); vIt.hasNext(); ) { Variable var = vIt.next(); if (!var.isDisplay()) continue; style = getHighlightTextStyleBounds(wnd, pp, var.getKey(), textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, pp, var.getKey())); } } } } } } // next examine all text on arcs in the cell if (User.isTextVisibilityOnArc()) { for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); // now see if arc is named if (ai.isUsernamed()) { Poly.Type style = getHighlightTextStyleBounds(wnd, ai, ArcInst.ARC_NAME, textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, ai, ArcInst.ARC_NAME)); } } // look at all variables on the arc for(Iterator<Variable> vIt = ai.getVariables(); vIt.hasNext(); ) { Variable var = vIt.next(); if (!var.isDisplay()) continue; Poly.Type style = getHighlightTextStyleBounds(wnd, ai, var.getKey(), textBounds); if (style != null) { // save text area in cache rtn = RTNode.linkGeom(null, rtn, new TextHighlightBound(textBounds, ai, var.getKey())); } } } } // save this R-Tree as the window's current cache wnd.setTextInCell(rtn); } // look through the R-Tree cache to find the proper highlight Rectangle2D searchArea = new Rectangle2D.Double(bounds.getMinX()-directHitDist, bounds.getMinY()-directHitDist, bounds.getWidth()+directHitDist*2, bounds.getHeight()+directHitDist*2); for(RTNode.Search sea = new RTNode.Search(searchArea, rtn, true); sea.hasNext(); ) { TextHighlightBound thb = (TextHighlightBound)sea.next(); if (boundsIsHit(thb.getBounds(), bounds, directHitDist)) list.add(new HighlightText(thb.getElectricObject(), cell, thb.getKey())); } } /** * Method to see if a bound is within a given distance of a selection. * @param bounds the bounds being tested. * @param selection the selection area/point. * @param directHitDist the required distance. * @return true if the bound is close enough to the selection. */ private static boolean boundsIsHit(Rectangle2D bounds, Rectangle2D selection, double directHitDist) { // ignore areaMustEnclose if bounds is size 0,0 boolean areaMustEnclose = User.isDraggingMustEncloseObjects(); if (areaMustEnclose && (selection.getHeight() > 0 || selection.getWidth() > 0)) { if (bounds.getMaxX() > selection.getMaxX()) return false; if (bounds.getMinX() < selection.getMinX()) return false; if (bounds.getMaxY() > selection.getMaxY()) return false; if (bounds.getMinY() < selection.getMinY()) return false; } else { double dist1 = selection.getMinX() - bounds.getMaxX(); double dist2 = bounds.getMinX() - selection.getMaxX(); double dist3 = selection.getMinY() - bounds.getMaxY(); double dist4 = bounds.getMinY() - selection.getMaxY(); double worstDist = Math.max(Math.max(dist1, dist2), Math.max(dist3, dist4)); if (worstDist > directHitDist) return false; } return true; } /** * Method to determine whether an object is in a bounds. * @param geom the Geometric being tested for selection. * @param findPort true if a port should be selected with a NodeInst. * @param findPoint true if a point should be selected with an outline NodeInst. * @param findSpecial true if hard-to-select and other special selection is being done. * @param bounds the selected area or point. * @param wnd the window being examined (null to ignore window scaling). * @param directHitDist the slop area to forgive when searching (a few pixels in screen space, transformed to database units). * @param areaMustEnclose true if the object must be completely inside of the selection area. * @return a Highlight that defines the object, or null if the point is not over any part of this object. */ public static Highlight2 checkOutObject(Geometric geom, boolean findPort, boolean findPoint, boolean findSpecial, Rectangle2D bounds, EditWindow wnd, double directHitDist, boolean areaMustEnclose) { if (geom instanceof NodeInst) { // examine a node object NodeInst ni = (NodeInst)geom; // do not "find" hard-to-find nodes if "findSpecial" is not set boolean hardToSelect = ni.isHardSelect(); if (ni.isCellInstance()) { if (!User.isEasySelectionOfCellInstances()) hardToSelect = true; } else { // do not include primitives that have all layers invisible if (!User.isHighlightInvisibleObjects()) { PrimitiveNode np = (PrimitiveNode)ni.getProto(); if (np.isNodeInvisible()) return null; } } if (!findSpecial && hardToSelect) return null; // do not "find" Invisible-Pins if they have text or exports if (ni.isInvisiblePinWithText()) retu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -