/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: ManipulatePorts.java
*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
*
* 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.dialogs;
import com.sun.electric.Main;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.topology.Connection;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.EditWindow_;
import com.sun.electric.database.variable.UserInterface;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.user.ExportChanges;
import com.sun.electric.tool.user.Highlighter;
import com.sun.electric.tool.user.User;
import com.sun.electric.tool.user.ui.EditWindow;
import com.sun.electric.util.TextUtils;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* Class to handle the "Manipulate Ports" dialog.
*/
public class ManipulatePorts extends EDialog
{
private static final String [] columnNames = {" ", "Name", "Characteristic", "Connections", "Arcs", "Exports"};
private class PortsTable extends JTable
{
private PortTableModel model;
/**
* Constructor for PortsTable
*/
public PortsTable(NodeInst ni)
{
model = new PortTableModel(ni);
for(Iterator<PortInst> it = ni.getPortInsts(); it.hasNext(); )
{
PortInst pi = it.next();
model.newVar(pi);
}
model.sortTable(1, true);
setModel(model);
TableColumn tc = getColumn(getColumnName(0));
if (tc != null) tc.setPreferredWidth(20);
tc = getColumn(getColumnName(1));
if (tc != null) tc.setPreferredWidth(120);
tc = getColumn(getColumnName(2));
if (tc != null) tc.setPreferredWidth(100);
tc = getColumn(getColumnName(3));
if (tc != null) tc.setPreferredWidth(90);
tc = getColumn(getColumnName(4));
if (tc != null) tc.setPreferredWidth(30);
tc = getColumn(getColumnName(5));
if (tc != null) tc.setPreferredWidth(120);
}
public void toggleSelection()
{
int [] rows = getSelectedRows();
for(int i=0; i<rows.length; i++)
{
Boolean b = (Boolean)model.getValueAt(rows[i], 0);
model.setValueAt(Boolean.valueOf(!b.booleanValue()), rows[i], 0);
}
}
public PortTableModel getModel() { return model; }
public void selectAll() { model.selectAll(); }
public void deselectAll() { model.deselectAll(); }
public void reExportSelected() { model.reExportSelected(); }
public void unExportSelected() { model.unExportSelected(); }
public void showSelected() { model.showSelected(); }
}
/**
* Model for storing Table data
*/
private class PortTableModel extends AbstractTableModel
{
private NodeInst ni;
private List<PortEntry> ports;
private class PortEntry
{
private boolean selected;
private PortInst pi;
private PortEntry(PortInst pi) { this.pi = pi; }
private PortInst getPort() { return pi; }
private boolean isSelected() { return selected; }
private void setSelected(boolean s) { selected = s; }
private String getConnections()
{
ArcProto [] conns = pi.getPortProto().getBasePort().getConnections();
StringBuffer buf = new StringBuffer();
for(int i=0; i<conns.length; i++)
{
if (conns[i].getTechnology() == Generic.tech())
{
if (ni.getProto().getTechnology() != Generic.tech()) continue;
}
if (buf.length() > 0) buf.append(", ");
buf.append(conns[i].getName());
}
return buf.toString();
}
private int getNumArcs()
{
int num = 0;
for(Iterator<Connection> it = pi.getNodeInst().getConnections(); it.hasNext(); )
{
Connection con = it.next();
if (con.getPortInst() == pi) num++;
}
return num;
}
private String getExports()
{
StringBuffer buf = new StringBuffer();
for(Iterator<Export> it = pi.getNodeInst().getExports(); it.hasNext(); )
{
Export e = it.next();
if (e.getOriginalPort() != pi) continue;
if (buf.length() > 0) buf.append(", ");
buf.append(e.getName());
}
return buf.toString();
}
}
/**
* Class to sort ports.
*/
public class PortEntrySort implements Comparator<PortEntry>
{
private int column;
private boolean ascending;
PortEntrySort(int column, boolean ascending)
{
this.column = column;
this.ascending = ascending;
}
public int compare(PortEntry p1, PortEntry p2)
{
if (!ascending)
{
PortEntry swap = p1;
p1 = p2;
p2 = swap;
}
String s1 = null, s2 = null;
switch (column)
{
case 0:
boolean b1 = p1.isSelected();
boolean b2 = p2.isSelected();
if (b1 == b2) return 0;
if (b1) return 1;
return -1;
case 1:
s1 = p1.getPort().getPortProto().getName();
s2 = p2.getPort().getPortProto().getName();
break;
case 2:
s1 = p1.getPort().getPortProto().getCharacteristic().getName();
s2 = p2.getPort().getPortProto().getCharacteristic().getName();
return s1.compareTo(s2);
case 3:
s1 = p1.getConnections();
s2 = p2.getConnections();
break;
case 4:
int i1 = p1.getNumArcs();
int i2 = p2.getNumArcs();
if (i1 == 12) return 0;
if (i1 < i2) return 1;
return -1;
case 5:
s1 = p1.getExports();
s2 = p2.getExports();
break;
}
return TextUtils.STRING_NUMBER_ORDER.compare(s1, s2);
}
}
// constructor
private PortTableModel(NodeInst ni)
{
this.ni = ni;
ports = new ArrayList<PortEntry>();
}
/**
* Create a new var with default properties
*/
public void newVar(PortInst pi)
{
PortEntry ve = new PortEntry(pi);
ports.add(ve);
}
public void sortTable(int column, boolean ascending)
{
Collections.sort(ports, new PortEntrySort(column, ascending));
fireTableDataChanged();
}
public void selectAll()
{
int i = 0;
for(PortEntry pe : ports)
{
pe.setSelected(true);
fireTableCellUpdated(i++, 0);
}
}
public void deselectAll()
{
int i = 0;
for(PortEntry pe : ports)
{
pe.setSelected(false);
fireTableCellUpdated(i++, 0);
}
}
public void reExportSelected()
{
List<PortInst> queuedExports = new ArrayList<PortInst>();
for(PortEntry pe : ports)
{
if (!pe.isSelected()) continue;
queuedExports.add(pe.getPort());
}
new ExportChanges.ReExportPorts(ni.getParent(), queuedExports, true, true, true,
false, User.isIncrementRightmostIndex(), null);
}
public void unExportSelected()
{
List<Export> queuedExports = new ArrayList<Export>();
for(PortEntry pe : ports)
{
if (!pe.isSelected()) continue;
for(Iterator<Export> eIt = pe.getPort().getExports(); eIt.hasNext(); )
{
Export e = eIt.next();
queuedExports.add(e);
}
}
ExportChanges.deleteExports(ni.getParent(), queuedExports);
}
public void showSelected()
{
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.getCurrentEditWindow_();
if (wnd == null) return;
wnd.clearHighlighting();
for(PortEntry pe : ports)
{
if (!pe.isSelected()) continue;
wnd.addElectricObject(pe.getPort(), ni.getParent());
}
wnd.finishedHighlighting();
}
/** Method to get the number of columns. */
public int getColumnCount() { return 6; }
/** Method to get the number of rows. */
public int getRowCount() { return ports.size(); }
/** Method to get a location in the table. */
public Object getValueAt(int rowIndex, int columnIndex) {
PortEntry pe = ports.get(rowIndex);
if (pe == null) return null;
switch (columnIndex)
{
// selected
case 0: return Boolean.valueOf(pe.isSelected());
// name
case 1: return pe.getPort().getPortProto().getName();
// characteristic
case 2: return pe.getPort().getPortProto().getCharacteristic().getName();
// connections
case 3: return pe.getConnections();
// arcs
case 4: return Integer.toString(pe.getNumArcs());
// exports
case 5: return pe.getExports();
}
return null;
}
/** Method to get a column's header name. */
public String getColumnName(int col)
{
String colName = columnNames[col];
if (col == sortColumn)
{
if (sortAscending) colName += " \u21D3"; else
colName += " \u21D1";
}
return colName;
}
/** Method to determine whether a cell is editable. */
public boolean isCellEditable(int row, int col)
{
if (col == 0) return true;
return false;
}
/** Method to set a value. */
public void setValueAt(Object aValue, int row, int col)
{
PortEntry ve = ports.get(row);
if (ve == null) return;
if (col != 0) return;
Boolean b = (Boolean)aValue;
if (ve.isSelected() != b.booleanValue())
{
ve.setSelected(b.booleanValue());
fireTableCellUpdated(row, col);
}
}
public Class<?> getColumnClass(int col)
{
if (col == 0) return Boolean.class;
return String.class;
}
}
private PortsTable portTable;
private int sortColumn;
private boolean sortAscending;
public static void showDialog()
{
EditWindow wnd = EditWindow.needCurrent();
if (wnd == null) return;
Highlighter h = wnd.getHighlighter();
NodeInst ni = (NodeInst)h.getOneElectricObject(NodeInst.class);
if (ni == null) return;
ManipulatePorts dialog = new ManipulatePorts((Frame) Main.getCurrentJFrame(), ni);
dialog.setVisible(true);
}
/** Creates new form Manipulate Ports */
private ManipulatePorts(Frame parent, NodeInst ni)
{
super(parent, true);
initComponents();
getRootPane().setDefaultButton(done);
title.setText("Ports on node " + ni.describe(false));
sortColumn = 1;
sortAscending = true;
portTable = new PortsTable(ni);
JTableHeader header = portTable.getTableHeader();
header.addMouseListener(new ColumnListener());
portPane.setViewportView(portTable);
finishInitialization();
}
private class ColumnListener extends MouseAdapter
{
public ColumnListener() {}
public void mouseClicked(MouseEvent e)
{
TableColumnModel colModel = portTable.getColumnModel();
int colNumber = colModel.getColumnIndexAtX(e.getX());
int modelIndex = colModel.getColumn(colNumber).getModelIndex();
if (modelIndex < 0) return;
if (sortColumn == modelIndex) sortAscending = !sortAscending; else
sortColumn = modelIndex;
PortTableModel model = portTable.getModel();
model.sortTable(modelIndex, sortAscending);
model.fireTableStructureChanged();
}
}
protected void escapePressed() { doneActionPerformed(null); }
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents()
{
java.awt.GridBagConstraints gridBagConstraints;
done = new javax.swing.JButton();
title = new javax.swing.JLabel();
portPane = new javax.swing.JScrollPane();
selectAll = new javax.swing.JButton();
deselectAll = new javax.swing.JButton();
reExportPorts = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
deleteExports = new javax.swing.JButton();
showPorts = new javax.swing.JButton();
toggleSelection = new javax.swing.JButton();
getContentPane().setLayout(new java.awt.GridBagLayout());
setTitle("Manipulate Ports");
setName("");
addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(java.awt.event.WindowEvent evt)
{
closeDialog(evt);
}
});
done.setText("Done");
done.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
doneActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(done, gridBagConstraints);
title.setText("Ports on node");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(title, gridBagConstraints);
portPane.setMinimumSize(new java.awt.Dimension(200, 200));
portPane.setPreferredSize(new java.awt.Dimension(200, 200));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
getContentPane().add(portPane, gridBagConstraints);
selectAll.setText("Select All Ports");
selectAll.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
selectAllActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(selectAll, gridBagConstraints);
deselectAll.setText("Deselect All Ports");
deselectAll.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
deselectAllActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(deselectAll, gridBagConstraints);
reExportPorts.setText("ReExport Selected Ports");
reExportPorts.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
reExportPortsActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(reExportPorts, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
getContentPane().add(jSeparator1, gridBagConstraints);
deleteExports.setText("Delect Exports on Selected Ports");
deleteExports.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
deleteExportsActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 3;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(deleteExports, gridBagConstraints);
showPorts.setText("Show Selected Ports");
showPorts.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
showPortsActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 4;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(showPorts, gridBagConstraints);
toggleSelection.setText("Toggle Selection");
toggleSelection.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
toggleSelectionActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
getContentPane().add(toggleSelection, gridBagConstraints);
pack();
}
// </editor-fold>//GEN-END:initComponents
private void toggleSelectionActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_toggleSelectionActionPerformed
{//GEN-HEADEREND:event_toggleSelectionActionPerformed
portTable.toggleSelection();
}//GEN-LAST:event_toggleSelectionActionPerformed
private void showPortsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_showPortsActionPerformed
{//GEN-HEADEREND:event_showPortsActionPerformed
portTable.showSelected();
}//GEN-LAST:event_showPortsActionPerformed
private void deleteExportsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteExportsActionPerformed
{//GEN-HEADEREND:event_deleteExportsActionPerformed
portTable.unExportSelected();
closeDialog(null);
}//GEN-LAST:event_deleteExportsActionPerformed
private void reExportPortsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_reExportPortsActionPerformed
{//GEN-HEADEREND:event_reExportPortsActionPerformed
portTable.reExportSelected();
closeDialog(null);
}//GEN-LAST:event_reExportPortsActionPerformed
private void deselectAllActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deselectAllActionPerformed
{//GEN-HEADEREND:event_deselectAllActionPerformed
portTable.deselectAll();
}//GEN-LAST:event_deselectAllActionPerformed
private void selectAllActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_selectAllActionPerformed
{//GEN-HEADEREND:event_selectAllActionPerformed
portTable.selectAll();
}//GEN-LAST:event_selectAllActionPerformed
private void doneActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_doneActionPerformed
{//GEN-HEADEREND:event_doneActionPerformed
closeDialog(null);
}//GEN-LAST:event_doneActionPerformed
/** Closes the dialog */
private void closeDialog(java.awt.event.WindowEvent evt)//GEN-FIRST:event_closeDialog
{
setVisible(false);
dispose();
}//GEN-LAST:event_closeDialog
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton deleteExports;
private javax.swing.JButton deselectAll;
private javax.swing.JButton done;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JScrollPane portPane;
private javax.swing.JButton reExportPorts;
private javax.swing.JButton selectAll;
private javax.swing.JButton showPorts;
private javax.swing.JLabel title;
private javax.swing.JButton toggleSelection;
// End of variables declaration//GEN-END:variables
}