Subversion Repositories wimsdev

Rev

Rev 3662 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     Sketch Elements: Chemistry molecular diagram drawing tool.
  3.    
  4.     (c) 2008 Dr. Alex M. Clark
  5.    
  6.     Released as GNUware, under the Gnu Public License (GPL)
  7.    
  8.     See www.gnu.org for details.
  9. */
  10.  
  11. package WIMSchem.ds;
  12.  
  13. import WIMSchem.*;
  14.  
  15. import java.util.*;
  16. import java.awt.*;
  17. import java.awt.event.*;
  18. import javax.swing.*;
  19. import javax.swing.table.*;
  20. import javax.swing.border.*;
  21.  
  22. /*
  23.     Data model to reconcile a DataSheet instance with the editing performed by a JTable component.
  24. */
  25.  
  26. public class DataTableModel extends AbstractTableModel
  27. {
  28.     DataSheet ds=null;
  29.     DataSheetCache cache=null;
  30.     TitleListener tlist=null;
  31.    
  32.     public DataTableModel(DataSheet DS,DataSheetCache Cache,TitleListener TList) {ds=DS; cache=Cache; tlist=TList;}
  33.     public DataSheet getDataSheet() {return ds;}
  34.     public void setDataSheet(DataSheet DS,DataSheetCache Cache) {ds=DS; cache=Cache;}
  35.    
  36.     public int getColumnCount() {return ds.numCols();}
  37.     public int getRowCount() {return ds.numRows();}
  38.     public String getColumnName(int col) {return ds.colName(col);}
  39.     public Object getValueAt(int row,int col)
  40.     {
  41.         int t=ds.colType(col);
  42.         if (ds.isNull(row,col))
  43.         {
  44.             if (t==DataSheet.COLTYPE_MOLECULE) return null;
  45.             if (t==DataSheet.COLTYPE_BOOLEAN) return new Boolean(false); // (no UI concept of null)
  46.             return ""; // null
  47.         }
  48.         else
  49.         {
  50.             if (t==DataSheet.COLTYPE_MOLECULE) return ds.getMolecule(row,col);
  51.             if (t==DataSheet.COLTYPE_STRING) return ds.getString(row,col);
  52.             if (t==DataSheet.COLTYPE_INTEGER) return new Integer(ds.getInteger(row,col));
  53.             if (t==DataSheet.COLTYPE_REAL) return new Double(ds.getReal(row,col));
  54.             if (t==DataSheet.COLTYPE_BOOLEAN) return new Boolean(ds.getBoolean(row,col));
  55.         }
  56.         return "";
  57.     }
  58.     public Class getColumnClass(int col)
  59.     {
  60.         int t=ds.colType(col);
  61.         if (t==DataSheet.COLTYPE_MOLECULE) return new Molecule().getClass();
  62.         if (t==DataSheet.COLTYPE_STRING) return new String("").getClass();
  63.         if (t==DataSheet.COLTYPE_INTEGER) return new String("").getClass();
  64.         if (t==DataSheet.COLTYPE_REAL) return new String("").getClass();
  65.         if (t==DataSheet.COLTYPE_BOOLEAN) return new Boolean(false).getClass();
  66.         return new String("").getClass();
  67.     }
  68.     public boolean isCellEditable(int row,int col) {return true;}
  69.    
  70.     // updates the data in the underlying datasheet, with care to cache undo states, and do nothing if the value is the same
  71.     public void setValueAt(Object val,int row,int col)
  72.     {
  73.         int t=ds.colType(col);
  74.         try
  75.         {
  76.             if (t==DataSheet.COLTYPE_MOLECULE)
  77.             {
  78.                 if (!ds.isEqualMolecule(row,col,(Molecule)val))
  79.                 {
  80.                     cache.cacheUndo(ds);
  81.                     ds.setMolecule(row,col,(Molecule)val);
  82.                     ds.setDirty();
  83.                     tlist.replaceTitle();
  84.                 }
  85.             }
  86.             else if (t==DataSheet.COLTYPE_STRING)
  87.             {
  88.                 if (!ds.isEqualString(row,col,(String)val))
  89.                 {
  90.                     cache.cacheUndo(ds);
  91.                     ds.setString(row,col,(String)val);
  92.                     ds.setDirty();
  93.                     tlist.replaceTitle();
  94.                 }
  95.             }
  96.             else if (t==DataSheet.COLTYPE_INTEGER)
  97.             {
  98.                 String str=(String)val;
  99.                 if (str.length()==0)
  100.                 {
  101.                     if (!ds.isNull(row,col))
  102.                     {
  103.                         cache.cacheUndo(ds);
  104.                         ds.setToNull(row,col);
  105.                         ds.setDirty();
  106.                         tlist.replaceTitle();
  107.                     }
  108.                 }
  109.                 else
  110.                 {
  111.                     int i=Integer.parseInt(str);
  112.                     if (!ds.isEqualInteger(row,col,i))
  113.                     {
  114.                         cache.cacheUndo(ds);
  115.                         ds.setInteger(row,col,i);
  116.                         ds.setDirty();
  117.                         tlist.replaceTitle();
  118.                     }
  119.                 }
  120.             }
  121.             else if (t==DataSheet.COLTYPE_REAL)
  122.             {
  123.                 String str=(String)val;
  124.                 if (str.length()==0)
  125.                 {
  126.                     if (!ds.isNull(row,col))
  127.                     {
  128.                         cache.cacheUndo(ds);
  129.                         ds.setToNull(row,col);
  130.                         ds.setDirty();
  131.                         tlist.replaceTitle();
  132.                     }
  133.                 }
  134.                 else
  135.                 {
  136.                     double d=Double.parseDouble(str);
  137.                     if (!ds.isEqualReal(row,col,d))
  138.                     {
  139.                         cache.cacheUndo(ds);
  140.                         ds.setReal(row,col,d);
  141.                         ds.setDirty();
  142.                         tlist.replaceTitle();
  143.                     }
  144.                 }
  145.             }
  146.             else if (t==DataSheet.COLTYPE_BOOLEAN)
  147.             {
  148.                 boolean b=((Boolean)val).booleanValue();
  149.                 if (!ds.isEqualBoolean(row,col,b))
  150.                 {
  151.                     cache.cacheUndo(ds);
  152.                     ds.setBoolean(row,col,b);
  153.                     ds.setDirty();
  154.                     tlist.replaceTitle();
  155.                 }
  156.             }
  157.         }
  158.         catch (NumberFormatException ex) {} // (do nothing --> change gets rejected)
  159.     }
  160. }
  161.  
  162.  
  163. // Class implemented specially to draw molecules on a table.
  164.  
  165. // !! TODO: don't use EditorPane for rendering; instead use DrawMolecule to render onto an offscreen image, and cache this
  166.  
  167. class TableMoleculeRenderer extends EditorPane implements TableCellRenderer
  168. {
  169.     Border focusBorder=null;
  170.  
  171.     public TableMoleculeRenderer()
  172.     {
  173.         setOpaque(true);
  174.  
  175.         setEditable(false);
  176.         setAutoScale(true);
  177.     }
  178.  
  179.     public Component getTableCellRendererComponent(JTable table,Object mol,boolean isSelected,boolean hasFocus,int row,int col)
  180.     {
  181.         if (mol!=null) this.replace((Molecule)mol); else this.clear();
  182.  
  183.         setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
  184.  
  185.         if (hasFocus)
  186.         {
  187.             if (focusBorder==null)
  188.                 focusBorder=BorderFactory.createMatteBorder(1,1,1,1,table.getSelectionBackground().darker());
  189.             setBorder(focusBorder);
  190.         }
  191.         else setBorder(null);
  192.  
  193.         return this;
  194.     }
  195. }
  196.  
  197. // Class implemented for editing of molecules: just sends an event notice to the parent, rather than actually doing the work.
  198.  
  199. class TableMoleculeEditor extends AbstractCellEditor implements TableCellEditor
  200. {
  201.     EditorPane edview=null;
  202.  
  203.     class PopMeUp implements Runnable
  204.     {
  205.         JFrame win;
  206.         PopMeUp(JFrame win) {this.win=win;}
  207.         public void run() {win.setVisible(true); win.requestFocus();}
  208.     }
  209.  
  210.     public TableMoleculeEditor()
  211.     {
  212.     }
  213.  
  214.     // custom behaviour: the number of ways to make molecule cells popup the editor has to be somewhat constrained
  215.     public boolean isCellEditable(EventObject e)
  216.     {
  217.         if (e instanceof KeyEvent)
  218.         {
  219.             KeyEvent ev=(KeyEvent)e;
  220.             return ev.getKeyChar()==' ';
  221.         }
  222.         else if (e instanceof MouseEvent)
  223.         {
  224.             MouseEvent ev=(MouseEvent)e;
  225.             return ev.getClickCount()==2 && ev.getButton()==MouseEvent.BUTTON1;
  226.         }
  227.         // (anything else??)
  228.         return false;
  229.     }
  230.    
  231.     public void setMolecule(Molecule mol) {edview.replace(mol);}
  232.  
  233.     public Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,int row,int col)
  234.     {
  235.         Molecule mol=(Molecule)value;
  236.         DataTableModel model=(DataTableModel)table.getModel();
  237.  
  238.         if (mol==null) mol=new Molecule();
  239.    
  240.         edview=new EditorPane();
  241.         edview.setOpaque(true);
  242.         edview.setEditable(false);
  243.         edview.setAutoScale(true);
  244.         Color sel=table.getSelectionBackground(),dark=sel.darker();
  245.         edview.setBackground(dark);
  246.         edview.replace(mol);
  247.  
  248.         EditWindow edwin=new EditWindow(mol.clone(),model,this);
  249.         addCellEditorListener(edwin);
  250.  
  251.         javax.swing.SwingUtilities.invokeLater(new PopMeUp(edwin));
  252.  
  253.         return edview;
  254.     }
  255.     public Object getCellEditorValue() {return edview==null ? null : edview.molData();}
  256. }
  257.  
  258.