001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.gui;
022
023import org.biojava.nbio.structure.Structure;
024import org.biojava.nbio.structure.align.gui.MenuCreator;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import javax.swing.*;
029import java.awt.*;
030import java.awt.event.WindowAdapter;
031import java.awt.event.WindowEvent;
032import java.lang.reflect.Constructor;
033import java.lang.reflect.InvocationTargetException;
034import java.lang.reflect.Method;
035
036public class JmolViewerImpl implements StructureViewer {
037
038        private static final Logger logger = LoggerFactory.getLogger(JmolViewerImpl.class);
039
040        public static final String viewer = "org.jmol.api.JmolSimpleViewer";
041        public static final String adapter = "org.jmol.api.JmolAdapter";
042        public static final String smartAdapter = "org.jmol.adapter.smarter.SmarterJmolAdapter";
043        Structure structure;
044        JmolPanel jmolPanel;
045        JFrame frame;
046
047        public JmolViewerImpl() {
048
049                frame = new JFrame();
050
051                JMenuBar menu = MenuCreator.initJmolMenu(frame, null, null, null);
052
053                frame.setJMenuBar(menu);
054
055                frame.addWindowListener(new WindowAdapter() {
056
057                        @Override
058                        public void windowClosing(WindowEvent e) {
059                                frame.dispose();
060                                //System.exit(0);
061                        }
062                });
063
064                Container contentPane = frame.getContentPane();
065
066                Box vBox = Box.createVerticalBox();
067
068                try {
069
070                        jmolPanel = new JmolPanel();
071
072                } catch (ClassNotFoundException e) {
073                        e.printStackTrace();
074                        System.err.println("Could not find Jmol in classpath, please install first. http://www.jmol.org");
075                        return;
076                }
077                jmolPanel.setPreferredSize(new Dimension(500, 500));
078                vBox.add(jmolPanel);
079
080
081                JTextField field = new JTextField();
082
083                field.setMaximumSize(new Dimension(Short.MAX_VALUE, 30));
084                field.setText("enter RASMOL like command...");
085//        RasmolCommandListener listener = new RasmolCommandListener(jmolPanel, field);
086
087//        field.addActionListener(listener);
088//        field.addMouseListener(listener);
089//        field.addKeyListener(listener);
090                vBox.add(field);
091
092                contentPane.add(vBox);
093
094
095
096                frame.pack();
097                frame.setVisible(true);
098
099        }
100
101        public void setTitle(String label) {
102                frame.setTitle(label);
103                frame.repaint();
104        }
105
106        @Override
107        public void setStructure(Structure structure) {
108                if (jmolPanel == null) {
109                        System.err.println("please install Jmol first");
110                        return;
111                }
112
113                setTitle(structure.getPDBCode());
114
115                // actually this is very simple
116                // just convert the structure to a PDB file
117
118                String pdb = structure.toPDB();
119                //System.out.println(s.isNmr());
120
121                //System.out.println(pdb);
122                // Jmol could also read the file directly from your file system
123                //viewer.openFile("/Path/To/PDB/1tim.pdb");
124
125                //System.out.println(pdb);
126                jmolPanel.openStringInline(pdb);
127
128                // send the PDB file to Jmol.
129                // there are also other ways to interact with Jmol, e.g make it directly
130                // access the biojava structure object, but they require more
131                // code. See the SPICE code repository for how to do this.
132        }
133
134        @Override
135        public void clear() {
136                // TODO Auto-generated method stub
137        }
138
139        @Override
140        public Color getColor() {
141                // TODO Auto-generated method stub
142                return null;
143        }
144
145        @Override
146        public Selection getSelection() {
147                // TODO Auto-generated method stub
148                return null;
149        }
150
151        @Override
152        public void repaint() {
153                // TODO Auto-generated method stub
154        }
155
156        @Override
157        public void setColor(Color red) {
158                // TODO Auto-generated method stub
159        }
160
161        @Override
162        public void setSelection(Selection selection) {
163                // TODO Auto-generated method stub
164        }
165
166        @Override
167        public void setStyle(RenderStyle wireframe) {
168                // TODO Auto-generated method stub
169        }
170
171        @Override
172        public void setZoom(int i) {
173                // TODO Auto-generated method stub
174        }
175        @SuppressWarnings("rawtypes")
176        static class JmolPanel extends JPanel {
177
178                /**
179                 *
180                 */
181                private static final long serialVersionUID = -3661941083797644242L;
182
183                Class viewerC;
184
185                Class adapterC;
186
187
188                Class smartAdapterC;
189                Object viewerO;
190                Object adapterO;
191                Method evalString;
192                Method renderScreenImage;
193                Method openStringInline;
194
195                //JmolSimpleViewer viewer;
196                //JmolAdapter adapter;
197                @SuppressWarnings("unchecked")
198                JmolPanel() throws ClassNotFoundException {
199
200                        try {
201                                viewerC = Class.forName(viewer);
202
203                                adapterC = Class.forName(adapter);
204                                smartAdapterC = Class.forName(smartAdapter);
205
206                                Method m = viewerC.getMethod("allocateSimpleViewer", new Class[]{Component.class, adapterC});
207
208                                Constructor constructor = smartAdapterC.getConstructor(new Class[]{});
209                                adapterO = constructor.newInstance(new Object[]{});
210
211                                //viewerC = JmolSimpleViewer.allocateSimpleViewer(this, adapter);
212                                viewerO = m.invoke(viewerC, this, adapterO);
213
214                                evalString = viewerC.getMethod("evalString", String.class);
215
216                                renderScreenImage = viewerC.getMethod("renderScreenImage",
217                                                new Class[]{Graphics.class, Dimension.class, Rectangle.class});
218
219                                openStringInline = viewerC.getMethod("openStringInline", new Class[]{String.class});
220
221                        } catch (InstantiationException ex) {
222                                logger.error("Exception caught", ex);
223                        } catch (IllegalAccessException ex) {
224                                logger.error("Exception caught", ex);
225                        } catch (IllegalArgumentException ex) {
226                                logger.error("Exception caught", ex);
227                        } catch (InvocationTargetException ex) {
228                                logger.error("Exception caught", ex);
229                        } catch (NoSuchMethodException e) {
230                                logger.error("Exception caught", e);
231                        }
232
233                        evalString("set scriptQueue on;");
234
235                }
236
237
238                public Class getViewer() {
239                        return viewerC;
240                }
241
242                public void evalString(String rasmolScript) {
243                        try {
244                                evalString.invoke(viewerO, rasmolScript);
245                        } catch (Exception e) {
246                                e.printStackTrace();
247                        }
248                }
249
250                public void openStringInline(String pdbFile) {
251                        try {
252                                openStringInline.invoke(viewerO, pdbFile);
253                        } catch (Exception e) {
254                                e.printStackTrace();
255                        }
256                }
257
258                public void executeCmd(String rasmolScript) {
259                        try {
260                                evalString.invoke(viewerO, rasmolScript);
261                        } catch (Exception e) {
262                                e.printStackTrace();
263                        }
264                }
265                final Dimension currentSize = new Dimension();
266                final Rectangle rectClip = new Rectangle();
267
268                @Override
269                public void paint(Graphics g) {
270                        getSize(currentSize);
271                        g.getClipBounds(rectClip);
272                        //viewer.renderScreenImage(g, currentSize, rectClip);
273
274                        try {
275                                renderScreenImage.invoke(viewerO, g, currentSize, rectClip);
276                        } catch (Exception e) {
277                                e.printStackTrace();
278                        }
279                }
280        }
281}