📄 techpalette.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: TechPalette.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.tool.user.ui;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.hierarchy.View;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.variable.Variable;import com.sun.electric.lib.LibFile;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.Artwork;import com.sun.electric.technology.technologies.Generic;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.simulation.Simulation;import com.sun.electric.tool.user.User;import com.sun.electric.tool.user.dialogs.AnnularRing;import com.sun.electric.tool.user.dialogs.CellBrowser;import com.sun.electric.tool.user.dialogs.EDialog;import com.sun.electric.tool.user.dialogs.LayoutText;import com.sun.electric.tool.user.menus.CellMenu;import com.sun.electric.tool.user.redisplay.AbstractDrawing;import com.sun.electric.tool.user.redisplay.PixelDrawing;import com.sun.electric.tool.user.redisplay.VectorCache;import com.sun.electric.tool.user.tecEdit.Info;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.FontMetrics;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.Point;import java.awt.Rectangle;import java.awt.RenderingHints;import java.awt.dnd.DnDConstants;import java.awt.dnd.DragGestureEvent;import java.awt.dnd.DragGestureListener;import java.awt.dnd.DragSource;import java.awt.dnd.DragSourceDragEvent;import java.awt.dnd.DragSourceDropEvent;import java.awt.dnd.DragSourceEvent;import java.awt.dnd.DragSourceListener;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ComponentEvent;import java.awt.event.ComponentListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.awt.event.MouseWheelEvent;import java.awt.event.MouseWheelListener;import java.awt.event.WindowEvent;import java.awt.event.WindowFocusListener;import java.awt.image.VolatileImage;import java.net.URL;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import javax.swing.BorderFactory;import javax.swing.DefaultListModel;import javax.swing.JList;import javax.swing.JMenuItem;import javax.swing.JPanel;import javax.swing.JPopupMenu;import javax.swing.JScrollPane;import javax.swing.JSeparator;import javax.swing.ListSelectionModel;import javax.swing.border.BevelBorder;/** * Class to display the nodes and arcs in a technology (in the Component Menu). */public class TechPalette extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener, PaletteFrame.PlaceNodeEventListener, ComponentListener, DragGestureListener, DragSourceListener { /** the number of palette entries. */ private int menuX = -1, menuY = -1; /** the size of a palette entry. */ private int entrySize; /** the list of objects in the palette. */ private List<Object> inPalette = new ArrayList<Object>(); /** the currently selected Node object. */ private Object highlightedNode; /** to collect contacts that must be groups */ private Map<Object,Object> elementsMap = new HashMap<Object,Object>(); /** cached palette image */ private VolatileImage paletteImage; /** if the palette image needs to be redrawn */ private boolean paletteImageStale; /** menu entry bounds */ private Rectangle entryRect; /** Variables needed for drag-and-drop */ private DragSource dragSource = null; /** Offscreen image */ private PixelDrawing offscreen; TechPalette() { addKeyListener(this); addMouseListener(this); addMouseMotionListener(this); addMouseWheelListener(this); addComponentListener(this); paletteImage = null; paletteImageStale = true; // initialize drag-and-drop from this palette dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this); } /** * Loads a new technology into the palette. Returns the * new desired size of the panel * @param tech the technology to load * @param curCell the cell in the window associated with this palette * @return the preferred size of the new panel */ public Dimension loadForTechnology(Technology tech, Cell curCell) { inPalette.clear(); elementsMap.clear(); Object[][] paletteMatrix = tech.getNodesGrouped(curCell); if (paletteMatrix == null) { System.out.println("Error: no palette information found for " + tech.getTechName()); } else { menuX = paletteMatrix[0].length; menuY = paletteMatrix.length; inPalette.clear(); for (int i = 0; i < menuX; i++) { for (int j = 0; j < menuY; j++) { Object item = (paletteMatrix[j] == null) ? null : paletteMatrix[j][i]; if (item instanceof NodeInst) { item = rotateTransistor((NodeInst)item); } else if (item instanceof List) { List nodes = (List)item; for(int k=0; k<nodes.size(); k++) { Object o = nodes.get(k); if (o instanceof NodeInst) { NodeInst ni = (NodeInst)o; nodes.set(k, rotateTransistor(ni)); } } } item = getInUse(item); inPalette.add(item); } } } Dimension size = TopLevel.getScreenSize(); entrySize = (int)size.getWidth() / menuX; int ysize = (int)(size.getHeight()*0.9) / menuY; if (ysize < entrySize) entrySize = ysize; size.setSize(entrySize*menuX+1, entrySize*menuY+1); User.getUserTool().setCurrentArcProto(tech.getArcs().next()); paletteImageStale = true; return size; } private NodeInst rotateTransistor(NodeInst ni) { if (!ni.getProto().getTechnology().isLayout()) return ni; int rot = 0; if (User.isRotateLayoutTransistors()) rot = 900; rot = (rot + ni.getAngle()) % 3600; PrimitiveNode.Function fun = ni.getFunction(); if (fun.isTransistor()) { NodeInst newNi = Technology.makeNodeInst(ni.getProto(), fun, rot, false, null, 0); newNi.copyVarsFrom(ni); ni = newNi; } return ni; } /** * Method to determine if item is in use or not. Null if not. */ private static Object getInUse(Object item) { if (item != null) { PrimitiveNode p = null; // checking if node is in use if (item instanceof NodeInst && ((NodeInst)item).getProto() instanceof PrimitiveNode) { p = (PrimitiveNode)((NodeInst)item).getProto(); } else if (item instanceof PrimitiveNode) p = (PrimitiveNode)item; if (p != null && p.isNotUsed()) item = null; } return item; } /** * Method to compose item name depending on object class */ private static String getItemName(Object item, boolean getVarName) { if (item instanceof PrimitiveNode) { PrimitiveNode np = (PrimitiveNode)item; return (np.getName()); } if (item instanceof NodeInst) { NodeInst ni = (NodeInst)item; Variable var = ni.getVar(Technology.TECH_TMPVAR); if (getVarName && var != null && !var.isDisplay()) { return (var.getObject().toString()); } // At least case for well contacts return (ni.getProto().getName()); } if (item instanceof ArcProto) { ArcProto ap = (ArcProto)item; return (ap.getName()); } return (""); } public void mousePressed(MouseEvent e) {} /** * Method called when the user clicks over an entry in the component menu. */ public void mouseReleased(MouseEvent e) { TechPalette panel = (TechPalette)e.getSource(); panel.requestFocus(); Object obj = getObjectUnderCursor(e.getX(), e.getY()); JMenuItem menuItem; if (obj == null) return; // nothing selected if (obj instanceof NodeProto || obj instanceof NodeInst || obj instanceof ArcProto || obj instanceof List) { if (obj instanceof List) { List<?> list = (List)obj; // Getting first element obj = list.get(0); if (obj instanceof List) obj = ((List)obj).get(0); if (list.size() > 1 && isCursorOnCorner(e)) { // Careful with this name JPopupMenu menu = new JPopupMenu(getItemName(obj, true)); for (Object item : list) { if (item instanceof JSeparator) menu.add((JSeparator)item); else if (item instanceof List) { List<?> subList = (List)item; for (Object subItem : subList) { subItem = getInUse(subItem); if (subItem == null) continue; menu.add(menuItem = new JMenuItem(getItemName(subItem, true))); menuItem.addActionListener(new TechPalette.PlacePopupListListener(panel, subItem, list, subList)); } } else { item = getInUse(item); if (item == null) continue; menu.add(menuItem = new JMenuItem(getItemName(item, true))); menuItem.addActionListener(new TechPalette.PlacePopupListListener(panel, item, list, null)); } } menu.show(panel, e.getX(), e.getY()); return; } } if (obj instanceof ArcProto) User.getUserTool().setCurrentArcProto((ArcProto)obj); else { PaletteFrame.placeInstance(obj, panel, false); } } else if (obj instanceof String) { String msg = (String)obj; if (msg.startsWith("LOADCELL ")) { String cellName = msg.substring(9); Cell cell = (Cell)Cell.findNodeProto(cellName); if (cell == null) { Job.getUserInterface().showErrorMessage("Cannot find cell " + cellName, "Unknown Cell"); return; } PaletteFrame.placeInstance(cell, panel, false); } else if (msg.equals(Technology.SPECIALMENUCELL)) { // get current cell type View view = null; Cell curCell = WindowFrame.getCurrentCell(); if (curCell != null) { if (curCell.getTechnology().isLayout()) view = View.LAYOUT; else if (curCell.getTechnology().isSchematics()) view = View.ICON; } JPopupMenu cellMenu = new JPopupMenu("Cells"); for(Iterator<Cell> it = Library.getCurrent().getCells(); it.hasNext(); ) { Cell cell = it.next(); if (cell == curCell) continue; // ignore same cell to avoid the recursive case if (view != null && cell.getView() != view) continue; menuItem = new JMenuItem(cell.describe(false)); menuItem.addActionListener(new TechPalette.PlacePopupListener(panel, cell)); cellMenu.add(menuItem); } cellMenu.show(panel, e.getX(), e.getY()); } else if (msg.equals(Technology.SPECIALMENUMISC)) { JPopupMenu specialMenu = new JPopupMenu("Miscellaneous"); menuItem = new JMenuItem("Cell Instance..."); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CellMenu.cellBrowserCommand(CellBrowser.DoAction.newInstance); } }); specialMenu.add(menuItem); specialMenu.addSeparator(); menuItem = new JMenuItem("Annotation Text"); menuItem.addActionListener(new TechPalette.PlacePopupListener(panel, "ART_message")); specialMenu.add(menuItem); menuItem = new JMenuItem("Layout Text..."); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { makeLayoutTextCommand(); } }); specialMenu.add(menuItem); menuItem = new JMenuItem("Annular Ring..."); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AnnularRing.showAnnularRingDialog(); } }); specialMenu.add(menuItem); specialMenu.addSeparator(); menuItem = new JMenuItem("Cell Center"); menuItem.addActionListener(new TechPalette.PlacePopupListener(panel, Generic.tech().cellCenterNode)); specialMenu.add(menuItem); menuItem = new JMenuItem("Essential Bounds"); menuItem.addActionListener(new TechPalette.PlacePopupListener(panel, Generic.tech().essentialBoundsNode)); specialMenu.add(menuItem); specialMenu.addSeparator(); menuItem = new JMenuItem("Spice Code"); menuItem.addActionListener(new TechPalette.PlacePopupListener(panel, "SIM_spice_card")); specialMenu.add(menuItem); menuItem = new JMenuItem("Spice Declaration");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -