/* Rajarshi Guha * 1/11/2004 */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.Component; import javax.swing.JLabel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.AbstractTableModel; import javax.swing.AbstractCellEditor; import java.io.File; import java.io.FileReader; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.Vector; import java.util.HashSet; import java.util.Hashtable; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IChemFile; import org.openscience.cdk.ChemFile; import org.openscience.cdk.ChemObject; import org.openscience.cdk.interfaces.IChemObject; import org.openscience.cdk.interfaces.IMolecule; import org.openscience.cdk.io.IChemObjectReader; import org.openscience.cdk.io.ReaderFactory; import org.openscience.cdk.tools.manipulator.ChemFileManipulator; import org.openscience.cdk.tools.LoggingTool; import org.openscience.cdk.layout.StructureDiagramGenerator; import org.openscience.cdk.geometry.GeometryTools; import org.openscience.cdk.renderer.Renderer2D; import org.openscience.cdk.renderer.Renderer2DModel; class StructureTableModel extends AbstractTableModel { private Object[][] rows; private String[] columns; public StructureTableModel(Object[][] objs, String[] cols) { rows = objs; columns = cols; } public String getColumnName(int column) { return columns[column]; } public int getRowCount() { return rows.length; } public int getColumnCount() { return columns.length; } public Object getValueAt(int row, int column) { return rows[row][column]; } public boolean isCellEditable(int row, int column) { return false; } public Class getColumnClass(int column) { return getValueAt(0, column).getClass(); } } class StructureTableCellRenderer extends render2dPanel implements TableCellRenderer{ public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex ) { if (vColIndex != 0) { return (render2dPanel)value; } return (render2dPanel)value; } // The following methods override the defaults for performance reasons public void validate() {} public void revalidate() {} protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {} public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {} } class StructureTableCellEditor extends AbstractCellEditor implements TableCellEditor{ public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column) { if (column != 0) { return (render2dPanel)value; } return (render2dPanel)value; } public Object getCellEditorValue() { return new Object(); } public boolean isCellEditable(int row, int column) { return false; } public boolean stopCellEditing() { return true; } } class render2dPanel extends JPanel { IAtomContainer mol; boolean withHydrogen = true; Renderer2DModel r2dm; Renderer2D renderer; public render2dPanel() { } public render2dPanel(IAtomContainer mol, int x, int y, boolean withHydrogen) { Hashtable ht = null; r2dm = new Renderer2DModel(); renderer = new Renderer2D(r2dm); Dimension screenSize = new Dimension(x,y); setPreferredSize(screenSize); r2dm.setBackgroundDimension(screenSize); // make sure it is synched with the JPanel size setBackground(r2dm.getBackColor()); this.mol = mol; this.withHydrogen = withHydrogen; if (!this.withHydrogen) {// get rid of hydrogens Vector ra = new Vector(); for (int i = 0; i < this.mol.getAtomCount(); i++) { if (this.mol.getAtomAt(i).getSymbol().equals("H")) ra.add( this.mol.getAtomAt(i) ); } for (int i = 0; i < ra.size(); i++) { this.mol.removeAtomAndConnectedElectronContainers( (IAtom)ra.get(i) ); } } try { r2dm.setDrawNumbers(false); r2dm.setUseAntiAliasing(true); r2dm.setColorAtomsByType(false); r2dm.setShowImplicitHydrogens(false); r2dm.setShowAromaticity(true); GeometryTools.translateAllPositive(this.mol); GeometryTools.scaleMolecule(this.mol, getPreferredSize(), 0.8); GeometryTools.center(this.mol, getPreferredSize()); } catch(Exception exc) { exc.printStackTrace(); } } public void paint(Graphics g) { super.paint(g); renderer.paintMolecule(this.mol, (Graphics2D)g, true); } } class RowLabelRenderer extends DefaultTableCellRenderer { public RowLabelRenderer() { super(); setHorizontalAlignment(javax.swing.SwingConstants.CENTER); } } class StructureTable { private Vector v; boolean withHydrogen = true; private int cellx = 300; private int celly = 300; private int ncol = 5; // excludes the 1st column for row numbers public StructureTable( Vector structs ) { this.v = structs; } public StructureTable( Vector structs , int ncol, boolean withHydrogen) { this.v = structs; this.ncol = ncol; this.withHydrogen = withHydrogen; } public StructureTable( Vector structs , int ncol, int cellx, int celly, boolean withHydrogen) { this.v = structs; this.ncol = ncol; this.cellx = cellx; this.celly = celly; this.withHydrogen = withHydrogen; } public void display() { int i = 0; int j = 0; int pad = 10; Object[][] ndata; String[] nm = new String[this.ncol+1]; int extra = v.size() % this.ncol; int block = v.size() - extra; int nrow = block / this.ncol; if (extra == 0) { ndata = new Object[nrow][this.ncol+1]; } else { ndata = new Object[nrow+1][this.ncol+1]; } int cnt = 0; for (i = 0; i < nrow; i++) { for (j = 1; j < this.ncol+1; j++) { ndata[i][j] = new render2dPanel( (IAtomContainer)v.get(cnt), this.cellx, this.celly, this.withHydrogen ); cnt += 1; } } j = 1; while (cnt < v.size()) { ndata[nrow][j] = new render2dPanel( (IAtomContainer)v.get(cnt), this.cellx, this.celly, this.withHydrogen ); cnt += 1; j += 1; } if (extra != 0) nrow += 1; for (i = 0; i < nrow; i++) { ndata[i][0] = new Integer(i*this.ncol+1); } JFrame frame = new JFrame("2D Structures"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); JTable mtable = new JTable( new StructureTableModel(ndata, nm) ); mtable.setShowGrid(true); // set row heights for (i = 0; i < nrow; i++) { mtable.setRowHeight(i, this.celly); } // disallow cell selections mtable.setColumnSelectionAllowed(false); mtable.setRowSelectionAllowed(false); // set the TableCellRenderer for the all columns // we also set up a TableCellEditor so that events on a render2dPanel // cell get forwarded to the actual render2dPanel. Right now this does nothing TableColumn col = mtable.getColumnModel().getColumn(0); col.setCellRenderer( new RowLabelRenderer() ); for (i = 1; i < this.ncol+1; i++) { col = mtable.getColumnModel().getColumn( i ); col.setCellRenderer( new StructureTableCellRenderer() ); col.setCellEditor( new StructureTableCellEditor() ); } // set up scroll bars JScrollPane scrollpane = new JScrollPane(mtable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); if (nrow > 3) { mtable.setPreferredScrollableViewportSize(new Dimension(this.ncol*this.cellx + pad,3*this.celly + pad)); } else { mtable.setPreferredScrollableViewportSize(new Dimension(this.ncol*this.cellx + pad,nrow*this.celly+pad)); } frame.getContentPane().add(scrollpane); // start the show! frame.pack(); if (nrow > 3) { frame.setSize(this.ncol*this.cellx + pad,3*this.celly + pad); } else { frame.setSize(this.ncol*this.cellx + pad,nrow*this.celly + pad); } frame.setVisible(true); } } public class st2d { public static void main(String[] args) { Vector v = new Vector(); // set some default values boolean showH = false; int ncol = 4; int cellx = 200; int celly = 200; // get any properties set on the command line String sncol = System.getProperty("ncol"); String scellx = System.getProperty("cellx"); String scelly = System.getProperty("celly"); String sH = System.getProperty("withH"); if (sncol != null) ncol = Integer.parseInt(sncol); if (scellx != null) cellx = Integer.parseInt(scellx); if (scelly != null) celly = Integer.parseInt(scelly); if (sH != null) showH = Boolean.valueOf(sH); try { int i = 0; int j = 0; // load the molecule and generate 2D coordinates for (i = 0; i < args.length; i++) { File input = new File(args[i]); IChemObjectReader reader = new ReaderFactory().createReader(new FileReader(input)); ChemFile content = (ChemFile)reader.read((ChemObject)new ChemFile()); IAtomContainer[] c = ChemFileManipulator.getAllAtomContainers(content); // we should do this loop in case we have files // that contain multiple molecules for (j = 0; j < c.length; j++) { StructureDiagramGenerator sdg = new StructureDiagramGenerator(); sdg.setMolecule((IMolecule)c[j]); sdg.generateCoordinates(); v.add((Object)sdg.getMolecule()); } } // some checks for visual niceness if (v.size() < ncol) { StructureTable st = new StructureTable(v,v.size(),cellx,celly, showH); st.display(); } else { StructureTable st = new StructureTable(v,ncol, cellx,celly,showH); st.display(); } } catch (Exception e) { System.out.println(e); } } }