📄 waveformwindow.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: WaveformWindow.java * * Copyright (c) 2004 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.waveform;import com.sun.electric.database.geometry.PolyBase;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.HierarchyEnumerator;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.network.Global;import com.sun.electric.database.network.Netlist;import com.sun.electric.database.network.Network;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.Pref;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.variable.CodeExpression;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.VarContext;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.tool.Job;import com.sun.electric.tool.io.FileType;import com.sun.electric.tool.io.input.EpicAnalysis;import com.sun.electric.tool.io.input.Simulate;import com.sun.electric.tool.io.output.PNG;import com.sun.electric.tool.io.output.Spice;import com.sun.electric.tool.ncc.NccCrossProbing;import com.sun.electric.tool.ncc.result.NccResult;import com.sun.electric.tool.simulation.*;import com.sun.electric.tool.user.ActivityLogger;import com.sun.electric.tool.user.HighlightListener;import com.sun.electric.tool.user.Highlighter;import com.sun.electric.tool.user.Resources;import com.sun.electric.tool.user.User;import com.sun.electric.tool.user.dialogs.OpenFile;import com.sun.electric.tool.user.ui.EditWindow;import com.sun.electric.tool.user.ui.ElectricPrinter;import com.sun.electric.tool.user.ui.ExplorerTree;import com.sun.electric.tool.user.ui.ExplorerTreeModel;import com.sun.electric.tool.user.ui.TopLevel;import com.sun.electric.tool.user.ui.WindowContent;import com.sun.electric.tool.user.ui.WindowFrame;import java.awt.Color;import java.awt.Component;import java.awt.Cursor;import java.awt.Dimension;import java.awt.Font;import java.awt.Graphics2D;import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.Insets;import java.awt.Point;import java.awt.Rectangle;import java.awt.datatransfer.DataFlavor;import java.awt.dnd.DnDConstants;import java.awt.dnd.DropTarget;import java.awt.dnd.DropTargetDragEvent;import java.awt.dnd.DropTargetDropEvent;import java.awt.dnd.DropTargetEvent;import java.awt.dnd.DropTargetListener;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ComponentEvent;import java.awt.event.ComponentListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.awt.font.FontRenderContext;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.awt.image.BufferedImage;import java.awt.print.PageFormat;import java.awt.print.PrinterJob;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import java.io.PrintWriter;import java.net.URL;import java.net.URLConnection;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;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 java.util.Stack;import javax.print.attribute.standard.ColorSupported;import javax.swing.AbstractCellEditor;import javax.swing.BoxLayout;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JComboBox;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JSplitPane;import javax.swing.JTable;import javax.swing.SwingUtilities;import javax.swing.Timer;import javax.swing.event.TableModelEvent;import javax.swing.table.DefaultTableModel;import javax.swing.table.TableCellEditor;import javax.swing.table.TableCellRenderer;import javax.swing.table.TableColumn;import javax.swing.table.TableColumnModel;import javax.swing.table.TableModel;import javax.swing.tree.DefaultMutableTreeNode;import javax.swing.tree.MutableTreeNode;import javax.swing.tree.TreeNode;import javax.swing.tree.TreePath;/** * This class defines the a screenful of Panels that make up a waveform display. */public class WaveformWindow implements WindowContent, PropertyChangeListener{ /** minimum height of an Analog panel */ private static final int MINANALOGPANELSIZE = 30; /** minimum height of a Digital panel */ private static final int MINDIGITALPANELSIZE = 20; public static final boolean USETABLES = true; /** the window that this lives in */ private WindowFrame wf; /** the cell being simulated */ private Stimuli sd; /** the signal on all X axes (null for time) */ private Signal xAxisSignalAll; /** the top-level panel of the waveform window. */ private JPanel overall; /** the "lock X axis" button. */ private JButton xAxisLockButton; /** the "refresh" button. */ private JButton refresh; /** the "show points" button. */ private JButton showPoints; /** the "grow panel" button for widening. */ private JButton growPanel; /** the "shrink panel" button for narrowing. */ private JButton shrinkPanel; /** the list of panels. */ private JComboBox signalNameList; /** mapping from analysis to entries in "SIGNALS" tree*/private Map<Analysis,TreePath> treePathFromAnalysis = new HashMap<Analysis,TreePath>(); /** true if rebuilding the list of panels */ private boolean rebuildingSignalNameList = false; /** the main scroll of all panels. */ private JScrollPane scrollAll; /** the split between signal names and traces. */ private JSplitPane split; /** left panel: the signal names */ private JPanel left; /** right panel: the signal traces */ private JPanel right; /** the table with panels and labels */ private WaveTable table; /** the table editor for left and right halves */ private WaveCellEditor leftSideColumn, rightSideColumn; /** the table with panels and labels */ private TableModel tableModel; /** labels for the text at the top */ private JLabel mainPos, extPos, delta, diskLabel; /** buttons for centering the X-axis cursors. */ private JButton centerMain, centerExt; /** a list of panels in this window */ private List<Panel> wavePanels; /** a list of sweep signals in this window */ private List<SweepSignal> sweepSignals; /** the main horizontal ruler for all panels. */ private HorizRuler mainHorizRulerPanel; /** true if the main horizontal ruler is logarithmic */ private boolean mainHorizRulerPanelLogarithmic; /** the VCR timer, when running */ private Timer vcrTimer; /** true to run VCR backwards */ private boolean vcrPlayingBackwards = false; /** time the VCR last advanced */ private long vcrLastAdvance; /** speed of the VCR (in screen pixels) */ private int vcrAdvanceSpeed = 3; /** current "main" x-axis cursor */ private double mainXPosition; /** current "extension" x-axis cursor */ private double extXPosition; /** default range along horozintal axis */ private double minXPosition, maxXPosition; /** true if the X axis is the same in each panel */ private boolean xAxisLocked; /** the sweep signal that is highlighted */ private int highlightedSweep = -1; /** display mode (0=lines, 1=lines&points, 2=points) */ private int linePointMode; /** true to show a grid (analog only) */ private boolean showGrid; /** the actual screen coordinates of the waveform */ private int screenLowX, screenHighX; /** a listener for redraw requests */ private WaveComponentListener wcl; /** The highlighter for this waveform window. */ private Highlighter highlighter; /** 0: color display, 1: color printing, 2: B&W printing */ private int nowPrinting; /** lock for crossprobing */ private static boolean freezeWaveformHighlighting = false; /** lock for crossprobing */ private static boolean freezeEditWindowHighlighting = false; /** The global listener for all waveform windows. */ private static WaveformWindowHighlightListener waveHighlighter = new WaveformWindowHighlightListener(); /** Font for all text in the window */ private static Font waveWindowFont; /** For rendering text */ private static FontRenderContext waveWindowFRC; /** The colors of signal lines */ private static Color offStrengthColor, nodeStrengthColor, gateStrengthColor, powerStrengthColor; /** drop target (for drag and drop) */ public static WaveFormDropTarget waveformDropTarget = new WaveFormDropTarget(); private static final ImageIcon iconAddPanel = Resources.getResource(WaveformWindow.class, "ButtonSimAddPanel.gif"); private static final ImageIcon iconLockXAxes = Resources.getResource(WaveformWindow.class, "ButtonSimLockTime.gif"); private static final ImageIcon iconUnLockXAxes = Resources.getResource(WaveformWindow.class, "ButtonSimUnLockTime.gif"); private static final ImageIcon iconRefresh = Resources.getResource(WaveformWindow.class, "ButtonSimRefresh.gif"); private static final ImageIcon iconLineOnPointOn = Resources.getResource(WaveformWindow.class, "ButtonSimLineOnPointOn.gif"); private static final ImageIcon iconLineOnPointOff = Resources.getResource(WaveformWindow.class, "ButtonSimLineOnPointOff.gif"); private static final ImageIcon iconLineOffPointOn = Resources.getResource(WaveformWindow.class, "ButtonSimLineOffPointOn.gif"); private static final ImageIcon iconToggleGrid = Resources.getResource(WaveformWindow.class, "ButtonSimGrid.gif"); private static final ImageIcon iconGrowPanel = Resources.getResource(WaveformWindow.class, "ButtonSimGrow.gif"); private static final ImageIcon iconShrinkPanel = Resources.getResource(WaveformWindow.class, "ButtonSimShrink.gif"); private static final ImageIcon iconVCRRewind = Resources.getResource(WaveformWindow.class, "ButtonVCRRewind.gif"); private static final ImageIcon iconVCRPlayBackward = Resources.getResource(WaveformWindow.class, "ButtonVCRPlayBackward.gif"); private static final ImageIcon iconVCRStop = Resources.getResource(WaveformWindow.class, "ButtonVCRStop.gif"); private static final ImageIcon iconVCRPlay = Resources.getResource(WaveformWindow.class, "ButtonVCRPlay.gif"); private static final ImageIcon iconVCRToEnd = Resources.getResource(WaveformWindow.class, "ButtonVCRToEnd.gif"); private static final ImageIcon iconVCRFaster = Resources.getResource(WaveformWindow.class, "ButtonVCRFaster.gif"); private static final ImageIcon iconVCRSlower = Resources.getResource(WaveformWindow.class, "ButtonVCRSlower.gif"); private static final Cursor resizeRowCursor = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR); private static final Cursor resizeColumnCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); /** * Constructor creates a Waveform window in a given WindowFrame with given Stimuli data. * @param sd the Stimuli data to show in the window. * @param wf the WindowFrame in which to place the window. */ public WaveformWindow(Stimuli sd, WindowFrame wf) { // initialize the structure this.wf = wf; this.sd = sd; sd.setWaveformWindow(this); resetSweeps(); wavePanels = new ArrayList<Panel>(); xAxisLocked = true; linePointMode = 0; nowPrinting = 0; showGrid = false; xAxisSignalAll = null; mainHorizRulerPanelLogarithmic = false; // compute static fields used in graphics waveWindowFont = new Font(User.getDefaultFont(), Font.PLAIN, 12); waveWindowFRC = new FontRenderContext(null, false, false); offStrengthColor = new Color(User.getColor(User.ColorPrefType.WAVE_OFF_STRENGTH)); nodeStrengthColor = new Color(User.getColor(User.ColorPrefType.WAVE_NODE_STRENGTH)); gateStrengthColor = new Color(User.getColor(User.ColorPrefType.WAVE_GATE_STRENGTH)); powerStrengthColor = new Color(User.getColor(User.ColorPrefType.WAVE_POWER_STRENGTH)); highlighter = new Highlighter(Highlighter.SELECT_HIGHLIGHTER, wf); Highlighter.addHighlightListener(waveHighlighter); // the total panel in the waveform window overall = new OnePanel(null, this); overall.setLayout(new GridBagLayout()); wcl = new WaveComponentListener(overall); overall.addComponentListener(wcl); // a drop target for the overall waveform window new DropTarget(overall, DnDConstants.ACTION_LINK, waveformDropTarget, true); // the table that holds the waveform panels if (USETABLES) { tableModel = new WaveTableModel(); table = new WaveTable(tableModel, this); new TableMouseListener(table); table.getTableHeader().setPreferredSize(new Dimension(1, 1)); TableColumn column1 = table.getColumnModel().getColumn(0); column1.setPreferredWidth(100); TableColumn column2 = table.getColumnModel().getColumn(1); column2.setPreferredWidth(500); leftSideColumn = new WaveCellEditor(table, 0); rightSideColumn = new WaveCellEditor(table, 1); int height = User.getWaveformDigitalPanelHeight(); if (sd.isAnalog()) height = User.getWaveformAnalogPanelHeight(); table.setRowHeight(height); scrollAll = new JScrollPane(table); // a drop target for the table new DropTarget(table, DnDConstants.ACTION_LINK, WaveformWindow.waveformDropTarget, true); } else { // the left half has signal names; the right half has waveforms left = new JPanel(); left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); right = new JPanel(); right.setLayout(new BoxLayout(right, BoxLayout.Y_AXIS)); // the main part of the waveform window: a split-pane between names and waveforms, put into a scrollpane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); split.setResizeWeight(0.1); split.addPropertyChangeListener(this); scrollAll = new JScrollPane(split); } GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 11; gbc.gridheight = 1; gbc.weightx = 0; gbc.weighty = 1; gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.BOTH; overall.add(scrollAll, gbc); if (sd.isAnalog()) { // the top part of the waveform window: status information JButton addPanel = new JButton(iconAddPanel); addPanel.setBorderPainted(false); addPanel.setDefaultCapable(false); addPanel.setToolTipText("Create new waveform panel"); Dimension minWid = new Dimension(iconAddPanel.getIconWidth()+4, iconAddPanel.getIconHeight()+4); addPanel.setMinimumSize(minWid); addPanel.setPreferredSize(minWid); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.CENTER; overall.add(addPanel, gbc); addPanel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { makeNewPanel(null); } }); showPoints = new JButton(iconLineOnPointOff); showPoints.setBorderPainted(false); showPoints.setDefaultCapable(false); showPoints.setToolTipText("Toggle display of vertex points and lines"); minWid = new Dimension(iconLineOnPointOff.getIconWidth()+4, iconLineOnPointOff.getIconHeight()+4); showPoints.setMinimumSize(minWid); showPoints.setPreferredSize(minWid); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 0; gbc.anchor = GridBagConstraints.CENTER; overall.add(showPoints, gbc); showPoints.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { toggleShowPoints(); } }); JButton toggleGrid = new JButton(iconToggleGrid); toggleGrid.setBorderPainted(false); toggleGrid.setDefaultCapable(false); toggleGrid.setToolTipText("Toggle display of a grid"); minWid = new Dimension(iconToggleGrid.getIconWidth()+4, iconToggleGrid.getIconHeight()+4); toggleGrid.setMinimumSize(minWid); toggleGrid.setPreferredSize(minWid); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.anchor = GridBagConstraints.CENTER; overall.add(toggleGrid, gbc); toggleGrid.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { toggleGridPoints(); } }); } refresh = new JButton(iconRefresh); refresh.setBorderPainted(false); refresh.setDefaultCapable(false); refresh.setToolTipText("Reread stimuli data file and update waveforms"); Dimension minWid = new Dimension(iconRefresh.getIconWidth()+4, iconRefresh.getIconHeight()+4); refresh.setMinimumSize(minWid); refresh.setPreferredSize(minWid); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 1; gbc.anchor = GridBagConstraints.CENTER; overall.add(refresh, gbc); refresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { refreshData(); } }); xAxisLockButton = new JButton(iconLockXAxes); xAxisLockButton.setBorderPainted(false); xAxisLockButton.setDefaultCapable(false); xAxisLockButton.setToolTipText("Lock all panels horizontally"); minWid = new Dimension(iconLockXAxes.getIconWidth()+4, iconLockXAxes.getIconHeight()+4); xAxisLockButton.setMinimumSize(minWid); xAxisLockButton.setPreferredSize(minWid); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 0; gbc.anchor = GridBagConstraints.CENTER; overall.add(xAxisLockButton, gbc); xAxisLockButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { togglePanelXAxisLock(); } }); signalNameList = new JComboBox(); signalNameList.setToolTipText("Show or hide waveform panels"); signalNameList.setLightWeightPopupEnabled(false); gbc = new GridBagConstraints(); gbc.gridx = 3; gbc.gridy = 0; gbc.gridwidth = 5; gbc.gridheight = 1; gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(0, 0, 0, 0); overall.add(signalNameList, gbc); signalNameList.addItem("Panel 1"); signalNameList.addActionListener(new ActionListener() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -