/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: ExportMismatchTable.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.ncc; import java.awt.Color; import java.util.Iterator; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.Border; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.variable.VarContext; import com.sun.electric.tool.ncc.result.NetObjReport; import com.sun.electric.tool.ncc.result.PortReport; import com.sun.electric.tool.ncc.result.WireReport; import com.sun.electric.tool.user.Highlighter; /** * This class implements the tbale for Export mismatches */ class ExportMismatchTable extends ExportTable { ExportMismatch[] mismatches; public ExportMismatchTable(NccGuiInfo res) { super(res, 2); height = Math.min(result.getValidExportMismatchCount(), MAXROWS); mismatches = new ExportMismatch[height]; setup(); boolean topoOK = result.isTopologyMatch(); int row = 0; for (Iterator<ExportMismatch> it = result.getExportMismatches().iterator(); it.hasNext() && row<height;) { ExportMismatch em = it.next(); if (topoOK && em.isValidOnlyWhenTopologyMismatch()) continue; mismatches[row] = em; row++; } setModel(new MismatchTableModel(this)); getTableHeader().setReorderingAllowed(false); getColumnModel().getColumn(0).addPropertyChangeListener(this); getColumnModel().getColumn(1).addPropertyChangeListener(this); } } /** * This class implements the model for the Export mismatch table */ class MismatchTableModel extends ExportTableModel { /** * Each item in array indicates whether cells in the corresponding * row should be switched */ private boolean swapCells[]; /** * Array of mismatches */ private ExportMismatch[] mismatches; public MismatchTableModel(ExportMismatchTable parent) { super(parent); mismatches = parent.mismatches; int[][] cellPrefHeights = parent.cellPrefHeights; int[][] cellPrefWidths = parent.cellPrefWidths; swapCells = new boolean[height]; int swap, cellNdx = 0; Border border = BorderFactory.createEmptyBorder(); StringBuffer html = new StringBuffer(64); // fill swap array for (int row=0; row<height; row++) { // if first design in the mismatch object has the same name as // the first design in the parent result object, then don't swap. // Otherwise swap if (mismatches[row].getName(0).equals(parent.result.getNames()[0])) { swap = 0; swapCells[row] = false; } else { swap = 1; swapCells[row] = true; } // fill cells with hyperliked Export lists for (int j=0; j<2; j++, cellNdx++) { html.setLength(0); html.append("<html><font size=3><font face=\"Helvetica, TimesRoman\">"); int lineNdx = cellNdx*10000; if (mismatches[row] instanceof ExportMismatch.MultiMatch) { List<PortReport> ports = ((ExportMismatch.MultiMatch)mismatches[row]).getAll((j+swap)%2); // each Port has a list of Exports which are printed as hyperlinked list for (Iterator<PortReport> it=ports.iterator(); it.hasNext();) { appendNameOf(it.next(), html, lineNdx, false, null); if (it.hasNext()) html.append("<br>" + LSEP); lineNdx++; cellPrefHeights[row][j] += ExportTable.LINEHEIGHT; } } else if (mismatches[row] instanceof ExportMismatch.NameMismatch) { if (j == swap) { PortReport port = ((ExportMismatch.NameMismatch)mismatches[row]).getFirstExport(); appendNameOf(port, html, lineNdx, false, null); } else { NetObjReport no = ((ExportMismatch.NameMismatch)mismatches[row]).getSuggestion(); appendNameOf(no, html, lineNdx, true, ExportTable.GREEN); } lineNdx++; cellPrefHeights[row][j] += ExportTable.LINEHEIGHT; } else if (mismatches[row] instanceof ExportMismatch.TopologyMismatch) { PortReport port; if (j == swap) { port = ((ExportMismatch.TopologyMismatch)mismatches[row]).getFirstExport(); appendNameOf(port, html, lineNdx, true, ExportTable.RED); } else { port = ((ExportMismatch.TopologyMismatch)mismatches[row]).getSecondExport(); appendNameOf(port, html, lineNdx, true, ExportTable.RED); } lineNdx++; if (j != swap) { // if a cell in the right column NetObjReport no = ((ExportMismatch.TopologyMismatch)mismatches[row]).getSuggestion(); if (no != null) { // if suggestion exists html.append("<br>"); appendNameOf(no, html, lineNdx, true, ExportTable.GREEN); lineNdx++; cellPrefHeights[row][j] += ExportTable.LINEHEIGHT; } } cellPrefHeights[row][j] += ExportTable.LINEHEIGHT; } html.append("</font></html>"); JEditorPane htmlPane = new JEditorPane(); htmlPane.setEditable(false); htmlPane.addHyperlinkListener(this); htmlPane.setContentType("text/html"); htmlPane.setText(html.toString()); htmlPane.setMargin(insets); htmlPane.addMouseListener(mouseAdapter); htmlPane.moveCaretPosition(0); cellPrefWidths[row][j] = htmlPane.getPreferredSize().width + ExportTable.WIDTHMARGIN; if (cellPrefHeights[row][j] > ExportTable.MAX_VISIBLE_LINES*ExportTable.LINEHEIGHT+ExportTable.HEIGHTMARGIN) cellPrefHeights[row][j] = ExportTable.MAX_VISIBLE_LINES*ExportTable.LINEHEIGHT+ExportTable.HEIGHTMARGIN; JPanel panel = new JPanel(); panel.setBackground(Color.WHITE); panel.add(htmlPane); panes[row][j] = new JScrollPane(panel); panes[row][j].setBorder(border); } } } /** * If the provieded NetObject is a Port, then print all Exports * corresponding to it. If the NetObject is a Wire, print its name. * @param no Port or Wire * @param html buffer to print to * @param lineNdx line number on which this text is going to appear * in the parent table cell. Used to create hyperlink indices * @param doColoring paint text to the provided Color if this is true. * Print in default color otherwise. * @param sugColor text color */ protected void appendNameOf(NetObjReport no, StringBuffer html, int lineNdx, boolean doColoring, String sugColor) { String href = "<a style=\"text-decoration: none\" href=\""; String text = null; boolean isImpl = false; if (no instanceof PortReport) { PortReport port = (PortReport)no; isImpl = port.isImplied(); text = port.exportNamesString(); if (doColoring) html.append("<font COLOR=\"" + sugColor + "\">"); if (isImpl) { html.append(text); if (doColoring) html.append("</font>"); html.append("<font COLOR=\"gray\"> : implied</font>"); } else { html.append(href + lineNdx +"\">"+ text +"</a>"); if (doColoring) html.append("</font>"); } } else if (no instanceof WireReport) { text = no.getName(); if (doColoring) html.append("<font COLOR=\"" + sugColor + "\">"); html.append(href + lineNdx + "\">"+ text +"</a></font>"); if (doColoring) html.append("</font>"); } } // /** // * Detect whether a Port in mismamatch has noo Exports. // * If no Exports exist then the Port has an implied Export // * @param port Port to test // * @return true if Port has only an implied Export, false otherwise // */ // protected boolean isImplied(PortReport port) { // Iterator it=port.getWire().getNameProxy().getNet().getExports(); // if (it.hasNext()) return false; // return true; // } /** * Highlight Exportson Port with the provided index. * Index encodes table row, table column, and line number inside * the table cell on which the Port is printed * @param index Port index */ protected void highlight(int index) { // decode index int line = index%10000; int row = (index/10000)/2; int col = (index/10000)%2; if (swapCells[row]) col = (col+1)%2; ExportMismatch em = mismatches[row]; Cell cell = em.getCell(col); VarContext context = em.getContext(col); // find the highlighter corresponding to the cell Highlighter highlighter = HighlightTools.getHighlighter(cell, context); if (highlighter == null) return; // find what to highlight if (em instanceof ExportMismatch.MultiMatch) { List<PortReport> ports = ((ExportMismatch.MultiMatch)em).getAll(col); int i; Iterator<PortReport> it; // go to the necessary line for (it=ports.iterator(), i=0; it.hasNext()&&i<line; i++,it.next()); PortReport port = it.next(); HighlightTools.highlightPortExports(highlighter, cell, port); } else if (em instanceof ExportMismatch.NameMismatch) { PortReport port; NetObjReport portOrWire; if (col == 0) { port = ((ExportMismatch.NameMismatch)em).getFirstExport(); HighlightTools.highlightPortExports(highlighter, cell, port); } else { portOrWire = ((ExportMismatch.NameMismatch)em).getSuggestion(); HighlightTools.highlightPortOrWire(highlighter, cell, portOrWire); } } else if (em instanceof ExportMismatch.TopologyMismatch) { PortReport port1, port2; NetObjReport portOrWire; if (col == 0) { port1 = ((ExportMismatch.TopologyMismatch)em).getFirstExport(); HighlightTools.highlightPortExports(highlighter, cell, port1); } else if (line == 0) { port2 = ((ExportMismatch.TopologyMismatch)em).getSecondExport(); HighlightTools.highlightPortExports(highlighter, cell, port2); } else if (line == 1) { // the second line has a suggestion portOrWire = ((ExportMismatch.TopologyMismatch)em).getSuggestion(); HighlightTools.highlightPortOrWire(highlighter, cell, portOrWire); } } highlighter.finished(); } /** * Get column name * @param col column * @return name of the column */ public String getColumnName(int col) { return parent.result.getNames()[col]; } }