📄 techpalette.java
字号:
List list; List subList; PlacePopupListListener(TechPalette panel, Object obj, List list, List subList) { super(panel, obj); this.list = list; this.subList = subList; } public void actionPerformed(ActionEvent evt) { if (obj instanceof ArcProto) User.getUserTool().setCurrentArcProto((ArcProto)obj); else PaletteFrame.placeInstance(obj, panel, false); // No first element -> make it default if (subList == null) Collections.swap(list, 0, list.indexOf(obj)); else { Collections.swap(list, 0, list.indexOf(subList)); Collections.swap(subList, 0, subList.indexOf(obj)); } panel.paletteImageStale = true; } } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} public void mouseDragged(MouseEvent e) {} /** * Method to figure out which palette entry the cursor is over. * @return an Object that is in the selected palette entry. */ private Object getObjectUnderCursor(int xp, int yp) { int x = xp / (entrySize+1); int y = menuY - (yp / (entrySize+1)) - 1; if (y < 0) y = 0; int index = x * menuY + y; if (index < 0 || index >= inPalette.size()) return null; Object obj = inPalette.get(index); return obj; } /** * Method to figure out which palette entry the cursor is over. * @return true if mouse is over bottom right corner */ private boolean isCursorOnCorner(MouseEvent e) { int entryS = (entrySize+1); int x = e.getX() / (entryS); int y = menuY - (e.getY() / (entryS)) - 1; if (y < 0) y = 0; double deltaX = (e.getX() - x*entryS)/(double)entryS; double deltaY = (e.getY() - (menuY-y-1)*entryS)/(double)entryS; return (deltaX > 0.75 && deltaY > 0.75); } /** * Method called when the mouse hovers over a palette entry. * Updates the status area to indicate what the palette will do. */ public void mouseMoved(MouseEvent e) { Object obj = getObjectUnderCursor(e.getX(), e.getY()); if (obj instanceof List) { obj = ((List)obj).get(0); if (obj instanceof List) obj = ((List)obj).get(0); } if (obj instanceof PrimitiveNode) { StatusBar.setSelectionOverride("CREATE NODE: " + ((PrimitiveNode)obj).describe(false)); } else if (obj instanceof NodeInst) { StatusBar.setSelectionOverride("CREATE NODE: " + ((NodeInst)obj).describe(false)); } else if (obj instanceof NodeProto) { StatusBar.setSelectionOverride("CREATE NODE: " + ((NodeProto)obj).describe(false)); } else if (obj instanceof ArcProto) { ArcProto ap = (ArcProto)obj; StatusBar.setSelectionOverride("USE ARC: " + ap.describe()); } else if (obj instanceof String) { String str = (String)obj; if (str.startsWith("LOADCELL ")) StatusBar.setSelectionOverride("CREATE CELL: " + str.substring(9)); else StatusBar.setSelectionOverride(null); } } public void mouseExited(MouseEvent e) { StatusBar.setSelectionOverride(null); } public void mouseWheelMoved(MouseWheelEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentMoved(ComponentEvent e) {} public void componentShown(ComponentEvent e) {} public void componentResized(ComponentEvent e) { paletteImageStale = true; } public void paint(Graphics g) { // stop now if not initialized if (menuX < 0 || menuY < 0) return; // recompute size of an entry from current window size Dimension size = getSize(); int wid = (int)size.getWidth(); int hei = (int)size.getHeight(); entrySize = Math.min(wid / menuX - 1, hei / menuY - 1); if (wid <= 0 || hei <= 0) return; // show the image // copying from the image (here, gScreen is the Graphics object for the onscreen window) do { int returnCode; if (paletteImage == null) { paletteImage = createVolatileImage(getWidth(), getHeight()); returnCode = VolatileImage.IMAGE_RESTORED; } else { returnCode = paletteImage.validate(getGraphicsConfiguration()); if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE || paletteImage.getWidth() != wid || paletteImage.getHeight() != hei) { returnCode = VolatileImage.IMAGE_INCOMPATIBLE; // old paletteImage doesn't work with new GraphicsConfig; re-create it paletteImage.flush(); paletteImage = createVolatileImage(getWidth(), getHeight()); } } if (returnCode != VolatileImage.IMAGE_OK || paletteImageStale) renderPaletteImage(); g.drawImage(paletteImage, 0, 0, this); } while (paletteImage.contentsLost()); paletteImageStale = false; // highlight node that user selected if (highlightedNode != null) { // draw highlights around cell with highlighted node int index = inPalette.indexOf(highlightedNode); if (index >= 0) { // put the Image in the proper place int x = index / menuY; int y = index % menuY; int imgX = x * (entrySize+1)+1; int imgY = (menuY-y-1) * (entrySize+1)+1; g.setColor(Color.BLUE); g.drawRect(imgX+1, imgY+1, entrySize-3, entrySize-3); g.drawRect(imgX+2, imgY+2, entrySize-5, entrySize-5); } } // highlight current arc Object arcObj = User.getUserTool().getCurrentArcProto(); int index = -1; for (int i = 0; i < inPalette.size(); i++) { Object obj = inPalette.get(i); if (obj == null) continue; if (obj instanceof List) obj = ((List)obj).get(0); if (obj == arcObj) { index = i; break; } } if (index >= 0) { int x = index / menuY; int y = index % menuY; int imgX = x * (entrySize+1)+1; int imgY = (menuY-y-1) * (entrySize+1)+1; g.setColor(Color.RED); g.drawRect(imgX+1, imgY+1, entrySize-3, entrySize-3); g.drawRect(imgX+2, imgY+2, entrySize-5, entrySize-5); } } private final static double menuArcLength = 8; private void renderPaletteImage() { // draw the menu entries if (entrySize < 2) return; entryRect = new Rectangle(new Dimension(entrySize-2, entrySize-2)); offscreen = new PixelDrawing(new Dimension(entrySize, entrySize)); Graphics2D g = (Graphics2D)paletteImage.getGraphics(); g.setBackground(new Color(User.getColor(User.ColorPrefType.BACKGROUND))); g.clearRect(0, 0, getWidth(), getHeight()); for(int x=0; x<menuX; x++) { for(int y=0; y<menuY; y++) { // render the entry into an Image int index = x * menuY + y; if (index >= inPalette.size()) continue; Object toDraw = inPalette.get(index); boolean drawArrow = false;//System.out.print("ENTRY "+x+","+y+" IS "+toDraw);//if (toDraw != null) System.out.print(" (TYPE="+toDraw.getClass()+")");//System.out.println(); if (toDraw instanceof List) { List list = ((List)toDraw); toDraw = list.get(0); if (toDraw instanceof List) toDraw = ((List)toDraw).get(0); drawArrow = list.size() > 1; } // put the Image in the proper place int imgX = x * (entrySize+1)+1; int imgY = (menuY-y-1) * (entrySize+1)+1; if (toDraw instanceof ArcProto) { // rendering an arc: create the temporary arc ArcProto ap = (ArcProto)toDraw; // determine scale for rendering double largest = 0; for(Iterator<ArcProto> it = ap.getTechnology().getArcs(); it.hasNext(); ) { ArcProto otherAp = it.next(); if (otherAp.isSpecialArc()) continue; // these are not drawn in palette if (otherAp.isSkipSizeInPalette()) continue; double wid = DBMath.gridToLambda(2*(otherAp.getDefaultGridExtendOverMin() + otherAp.getMaxLayerGridExtend())); if (wid+menuArcLength > largest) largest = wid+menuArcLength; } // render the arc double scalex = entrySize/largest * 0.8; double scaley = entrySize/largest * 0.8; double scale = Math.min(scalex, scaley); // draw the arc VectorCache.VectorBase[] shapes = VectorCache.drawPolys(ap.getShapeOfDummyArc(menuArcLength)); drawShapes(g, imgX, imgY, scale, shapes); g.setColor(Color.RED); g.drawRect(imgX, imgY, entrySize-1, entrySize-1); } if (toDraw instanceof NodeProto || toDraw instanceof NodeInst) { NodeInst ni; if (toDraw instanceof NodeInst) { ni = (NodeInst)toDraw; if (ni.getFunction() == PrimitiveNode.Function.TRAPNP || ni.getFunction() == PrimitiveNode.Function.TRA4PNP) drawArrow = true; } else { // rendering a node: create the temporary node NodeProto np = (NodeProto)toDraw; ni = NodeInst.makeDummyInstance(np); if (np == Schematics.tech().diodeNode || np == Schematics.tech().capacitorNode || np == Schematics.tech().flipflopNode) drawArrow = true; } // determine scale for rendering if (ni.isCellInstance()) { String str = ni.getProto().getName(); int defSize = 12; Font f = new Font(User.getDefaultFont(), Font.BOLD, defSize); FontMetrics fm = g.getFontMetrics(f); float width = fm.stringWidth(str); if (width > entryRect.width) { defSize = (int)(defSize * entryRect.width / width); f = new Font(User.getDefaultFont(), Font.BOLD, defSize); fm = g.getFontMetrics(f); width = fm.stringWidth(str); } g.setFont(f); g.setColor(new Color(User.getColor(User.ColorPrefType.TEXT))); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.drawString(str, imgX + (entryRect.width - width)/2, imgY + (entryRect.height + (float)fm.getAscent())/2); } else { PrimitiveNode np = (PrimitiveNode)ni.getProto(); double largest = 0; PrimitiveNode.Function groupFunction = np.getGroupFunction(); for(Iterator<PrimitiveNode> it = np.getTechnology().getNodes(); it.hasNext(); ) { PrimitiveNode otherNp = it.next(); if (otherNp.getGroupFunction() != groupFunction) continue; if (otherNp.isSkipSizeInPalette()) continue; if (otherNp.getDefHeight() > largest) largest = otherNp.getDefHeight(); if (otherNp.getDefWidth() > largest) largest = otherNp.getDefWidth(); } // for pins, make them the same scale as the arcs if (groupFunction == PrimitiveNode.Function.PIN) { largest = 0; for(Iterator<ArcProto> it = np.getTechnology().getArcs(); it.hasNext(); ) { ArcProto otherAp = it.next(); if (otherAp.isSpecialArc()) continue; // ignore arc for sizing if (otherAp.isSkipSizeInPalette()) continue; double wid = DBMath.gridToLambda(2*(otherAp.getDefaultGridExtendOverMin() + otherAp.getMaxLayerGridExtend())); if (wid+8 > largest) largest = wid+8; } } // render it if (largest == 0) largest = 1; double scalex = entrySize/largest * 0.8; double scaley = entrySize/largest * 0.8; double scale = Math.min(scalex, scaley); // make sure the text is at the bottom of the entry Variable var = ni.getVar(Technology.TECH_TMPVAR); if (var != null) ni.setTextDescriptor(Technology.TECH_TMPVAR, var.getTextDescriptor().withOff(0, -largest/2/0.8)); VectorCache.VectorBase[] shapes = VectorCache.drawNode(ni); drawShapes(g, imgX, imgY, scale, shapes); } g.setColor(Color.BLUE); g.drawRect(imgX, imgY, entrySize-1, entrySize-1); } if (toDraw instanceof String) { String str = (String)toDraw; if (str.equals(Technology.SPECIALMENUCELL) || str.equals(Technology.SPECIALMENUSPICE) || str.equals(Technology.SPECIALMENUMISC) || str.equals(Technology.SPECIALMENUPURE)) drawArrow = true; if (str.startsWith("LOADCELL ")) { int colonPos = str.indexOf(':'); if (colonPos < 0) str = str.substring(9); else str = str.substring(colonPos+1); g.setColor(Color.BLUE); g.drawRect(imgX, imgY, entrySize-1, entrySize-1); } int defSize = 18; Font f = new Font(User.getDefaultFont(), Font.BOLD, defSize); FontMetrics fm = g.getFontMetrics(f); float width = fm.stringWidth(str); if (width > entryRect.width) { defSize = (int)(defSize * entryRect.width / width); f = new Font(User.getDefaultFont(), Font.BOLD, defSize); fm = g.getFontMetrics(f); width = fm.stringWidth(str); } g.setFont(f); g.setColor(new Color(User.getColor(User.ColorPrefType.TEXT))); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.drawString(str, imgX + (entryRect.width - width)/2, imgY + (entryRect.height + (float)fm.getAscent())/2); } if (drawArrow) drawArrow(g, x, y); } } offscreen = null; // show dividing lines g.setColor(new Color(User.getColor(User.ColorPrefType.GRID))); for(int i=0; i<=menuX; i++) { int xPos = (entrySize+1) * i; g.drawLine(xPos, 0, xPos, menuY*(entrySize+1)); } for(int i=0; i<=menuY; i++) { int yPos = (entrySize+1) * i; g.drawLine(0, yPos, menuX*(entrySize+1), yPos); } g.dispose(); } private void drawArrow(Graphics g, int x, int y) { int imgX = x * (entrySize+1)+1; int imgY = (menuY-y-1) * (entrySize+1)+1; int [] arrowX = new int[3]; int [] arrowY = new int[3]; arrowX[0] = imgX-2 + entrySize*7/8; arrowY[0] = imgY-2 + entrySize; arrowX[1] = imgX-2 + entrySize; arrowY[1] = imgY-2 + entrySize*7/8; arrowX[2] = imgX-2 + entrySize*7/8; arrowY[2] = imgY-2 + entrySize*3/4; g.setColor(new Color(User.getColor(User.ColorPrefType.GRID))); g.fillPolygon(arrowX, arrowY, 3); } /** * Method to draw polygon "poly", transformed through "trans". */ private void drawShapes(Graphics2D g, int imgX, int imgY, double scale, VectorCache.VectorBase[] shapes) { AbstractDrawing.drawShapes(g, imgX, imgY, scale, shapes, offscreen, entryRect); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -