Back to index

wims  3.65+svn20090927
CatalogWindow.java
Go to the documentation of this file.
00001 /*
00002     WIMSchem Elements: Chemistry molecular diagram drawing tool.
00003     
00004     (c) 2005 Dr. Alex M. Clark
00005     
00006     Released as GNUware, under the Gnu Public License (GPL)
00007     
00008     See www.gnu.org for details.
00009 */
00010 
00011 package WIMSchem;
00012 
00013 import java.util.*;
00014 import java.io.*;
00015 import java.awt.*;
00016 import java.awt.event.*;
00017 import java.awt.image.*;
00018 import javax.swing.*;
00019 
00020 /*
00021     A window class for displaying a catalog of structures, ripped out of a text-style database such as an SD-file.
00022 */
00023 
00024 public class CatalogWindow extends JFrame 
00025     implements MolSelectListener, ActionListener, ComponentListener, AdjustmentListener, WindowListener
00026 {
00027     String catFN;
00028     FileInputStream istr=null;
00029 
00030     final int COL_SIZE=5;
00031     int basepos=0,selnum=-1,highestUpdated=0;
00032 
00033     Color bckgr,highl;
00034 
00035     JScrollBar scroll;
00036     JButton bopen,bclose;
00037     EditorPane[] entries;
00038     
00039     CatalogLoader loader=null;
00040 
00041     public CatalogWindow(String CatFN)
00042     {
00043        catFN=CatFN;
00044        
00045        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
00046        JFrame.setDefaultLookAndFeelDecorated(false); 
00047        
00048        setTitle("WIMSchem Catalog - "+catFN);
00049 
00050        bckgr=getBackground();
00051        highl=new Color(Math.max(bckgr.getRed()-32,0),Math.max(bckgr.getGreen()-32,0),bckgr.getBlue());
00052 
00053        ImageIcon mainIcon=new ImageIcon(getClass().getResource("/images/MainIcon.png"));
00054        setIconImage(mainIcon.getImage());
00055 
00056        GridBagLayout gb=new GridBagLayout();
00057        GridBagConstraints gc=new GridBagConstraints();
00058        gc.insets=new Insets(2,2,2,2);
00059        
00060        // add the molecules
00061        JPanel content=new JPanel();
00062        content.setLayout(new BoxLayout(content,BoxLayout.X_AXIS));
00063        entries=new EditorPane[COL_SIZE];
00064        for (int n=0;n<COL_SIZE;n++)
00065        {
00066            entries[n]=new EditorPane(100,100);
00067            entries[n].SetEditable(false);
00068            entries[n].SetMolSelectListener(this);
00069            entries[n].SetToolCursor();
00070            entries[n].SetBorder(true);
00071            entries[n].setMaximumSize(new Dimension(Short.MAX_VALUE,Short.MAX_VALUE));
00072            content.add(entries[n]);
00073        }
00074        gc.fill=GridBagConstraints.BOTH;
00075        gc.gridwidth=GridBagConstraints.REMAINDER;
00076        gc.weightx=1;
00077        gc.weighty=1;
00078        gb.setConstraints(content,gc);
00079        add(content);
00080        
00081        // add the scroller and buttons
00082        gc.fill=GridBagConstraints.HORIZONTAL;
00083        gc.weighty=0;
00084 
00085        scroll=new JScrollBar(JScrollBar.HORIZONTAL,0,0,0,0);
00086        scroll.addAdjustmentListener(this);
00087        gc.gridwidth=5;
00088        gc.weightx=1;
00089        gb.setConstraints(scroll,gc);
00090        add(scroll);
00091        
00092        bopen=new JButton("Open");
00093        bopen.addActionListener(this);
00094        bopen.setMnemonic(KeyEvent.VK_O);
00095        gc.gridwidth=1;
00096        gc.weightx=0;
00097        gb.setConstraints(bopen,gc);
00098        add(bopen);
00099        
00100        bclose=new JButton("Close");
00101        bclose.setMnemonic(KeyEvent.VK_C);
00102        bclose.addActionListener(this);
00103        gc.gridwidth=1;
00104        gc.weightx=0;
00105        gb.setConstraints(bclose,gc);
00106        add(bclose);
00107 
00108        setLayout(gb);
00109        pack();
00110        addComponentListener(this);
00111        addWindowListener(this);
00112 
00113        try
00114        {      
00115            istr=new FileInputStream(catFN);
00116        }
00117        catch (IOException e)
00118        {
00119            JOptionPane.showMessageDialog(null,e.toString(),"Catalog Read Failed",JOptionPane.ERROR_MESSAGE);
00120            dispose();
00121            return;
00122        }
00123 
00124        loader=new CatalogLoader(this,istr);
00125        loader.start();
00126     }
00127     
00128     
00129     public void Synch(int Sz)
00130     {
00131        scroll.setMaximum(Sz);
00132        scroll.setVisibleAmount(COL_SIZE);
00133        scroll.setUnitIncrement(1);
00134        scroll.setBlockIncrement(COL_SIZE);
00135        
00136        if (basepos+5>=Sz || highestUpdated<=COL_SIZE) UpdatePosition(basepos);
00137        highestUpdated=Sz;
00138     }
00139 
00140     void UpdatePosition(int NewPos)
00141     {
00142        // NB: should speed this up sometime by re-using molecules that are already loaded
00143     
00144        basepos=NewPos;
00145        try
00146        {
00147            for (int n=0;n<COL_SIZE;n++)
00148            {
00149               if (basepos+n>=loader.Count()) 
00150               {
00151                   entries[n].setBackground(bckgr);
00152                   entries[n].Clear();
00153               }
00154               else
00155               {
00156                   Molecule mol=loader.Get(basepos+n);
00157                   entries[n].setBackground(basepos+n==selnum ? highl : bckgr);
00158                   entries[n].Replace(mol,true,false);
00159                   entries[n].ScaleToFit();
00160                   entries[n].repaint();
00161               }
00162            }
00163        }
00164        catch (Exception e) {e.printStackTrace();}
00165     }
00166 
00167     synchronized void OpenMolecule(int N)
00168     {
00169        try
00170        {
00171            Molecule mol=loader.Get(N);
00172            MainWindow mw=new MainWindow(null,false,null);
00173            mw.MainPanel().SetMolecule(mol);
00174            mw.setVisible(true);
00175        }
00176        catch (Exception e) {e.printStackTrace();}
00177     }
00178 
00179     // event handling
00180 
00181     public void MolSelected(EditorPane source,int idx,boolean dblclick)
00182     {
00183        int entnum=-1;
00184        for (int n=0;n<COL_SIZE;n++) if (source==entries[n]) {entnum=n; break;}
00185        if (entnum>=0)
00186        {
00187            selnum=basepos+entnum;
00188            for (int n=0;n<COL_SIZE;n++) 
00189            {
00190               entries[n].setBackground(n==entnum ? highl : bckgr);
00191               entries[n].repaint();
00192            }
00193            
00194            if (idx!=0) OpenMolecule(selnum);
00195        }
00196        
00197     }
00198     public void DirtyChanged(boolean isdirty) {}
00199     
00200     public void actionPerformed(ActionEvent e)
00201     {
00202        if (e.getSource()==bopen) {if (selnum>=0) OpenMolecule(selnum);}
00203        if (e.getSource()==bclose) 
00204        {
00205            if (loader!=null) loader.Zap();
00206            dispose(); 
00207            return;
00208        }
00209     }
00210 
00211     public void componentHidden(ComponentEvent e) {}
00212     public void componentMoved(ComponentEvent e) {}
00213     public void componentResized(ComponentEvent e) 
00214     {
00215        for (int n=0;n<COL_SIZE;n++) entries[n].ScaleToFit();
00216     }
00217     public void componentShown(ComponentEvent e) {}
00218 
00219     public void adjustmentValueChanged(AdjustmentEvent e)
00220     {
00221        if (e.getSource()==scroll)
00222        {
00223            int pos=e.getValue();
00224            if (pos!=basepos) UpdatePosition(pos);
00225        }
00226     }
00227     
00228     public void windowActivated(WindowEvent e) {}
00229     public void windowClosed(WindowEvent e) {loader.Zap();}
00230     public void windowClosing(WindowEvent e) {}
00231     public void windowDeactivated(WindowEvent e) {}
00232     public void windowDeiconified(WindowEvent e) {}
00233     public void windowIconified(WindowEvent e) {}
00234     public void windowOpened(WindowEvent e) {}
00235 }
00236 
00237 // background thread which loads up the entries of the database, and lets the window know when new ones have arrived
00238 
00239 class CatalogLoader extends Thread
00240 {
00241     CatalogWindow wnd;
00242     FileInputStream istr;
00243     boolean zap=false;
00244     ArrayList<Long> filepos=new ArrayList<Long>();
00245     Object mutex=new Object();
00246 
00247     public CatalogLoader(CatalogWindow Wnd,FileInputStream IStr)
00248     {
00249        wnd=Wnd;
00250        istr=IStr;
00251     }
00252     
00253     public void run() 
00254     {
00255        try
00256        {          
00257            long pos=0,nextpos;
00258            while (!zap)
00259            {
00260               synchronized (mutex) {nextpos=MoleculeStream.FindNextPosition(istr,pos);}
00261               if (nextpos<0) break;
00262 
00263               filepos.add(pos);
00264               pos=nextpos;
00265               
00266               // inform the main window that is has work to do!
00267               EventQueue.invokeLater(new Runnable()
00268               {
00269                   public void run()
00270                   {
00271                      wnd.Synch(filepos.size());
00272                   }
00273               });
00274            }
00275        }
00276        catch (IOException e) 
00277        {
00278            JOptionPane.showMessageDialog(null,e.toString(),"Catalog Load Failed",JOptionPane.ERROR_MESSAGE);
00279            e.printStackTrace();
00280        }
00281     }
00282     
00283     public void Zap() {zap=true;} 
00284     public int Count() {synchronized(mutex) {return filepos.size();}}
00285     public Molecule Get(int N) 
00286     {
00287        try
00288        {
00289            synchronized(mutex) {return MoleculeStream.FetchFromPosition(istr,filepos.get(N).longValue());}
00290        }
00291        catch (IOException e) {return null;}
00292     }
00293 }