Add mousewheel listener
[jalview.git] / src / MCview / PDBCanvas.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4 *\r
5 * This program is free software; you can redistribute it and/or\r
6 * modify it under the terms of the GNU General Public License\r
7 * as published by the Free Software Foundation; either version 2\r
8 * of the License, or (at your option) any later version.\r
9 *\r
10 * This program is distributed in the hope that it will be useful,\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 * GNU General Public License for more details.\r
14 *\r
15 * You should have received a copy of the GNU General Public License\r
16 * along with this program; if not, write to the Free Software\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18 */\r
19 package MCview;\r
20 \r
21 import jalview.analysis.AlignSeq;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug\r
26 import java.awt.*;\r
27 import java.awt.event.*;\r
28 \r
29 import java.io.*;\r
30 \r
31 import java.util.*;\r
32 \r
33 import javax.swing.*;\r
34 \r
35 \r
36 public class PDBCanvas extends JPanel implements MouseListener, MouseMotionListener\r
37 {\r
38     MCMatrix idmat = new MCMatrix(3, 3);\r
39     MCMatrix objmat = new MCMatrix(3, 3);\r
40     boolean redrawneeded = true;\r
41     int omx = 0;\r
42     int mx = 0;\r
43     int omy = 0;\r
44     int my = 0;\r
45     public PDBfile pdb;\r
46     int bsize;\r
47     Image img;\r
48     Graphics ig;\r
49     Dimension prefsize;\r
50     float[] centre = new float[3];\r
51     float[] width = new float[3];\r
52     float maxwidth;\r
53     float scale;\r
54     String inStr;\r
55     String inType;\r
56     boolean bysequence = true;\r
57     boolean depthcue = true;\r
58     boolean wire = false;\r
59     boolean bymolecule = false;\r
60     boolean zbuffer = true;\r
61     boolean dragging;\r
62     int xstart;\r
63     int xend;\r
64     int ystart;\r
65     int yend;\r
66     int xmid;\r
67     int ymid;\r
68     Font font = new Font("Helvetica", Font.PLAIN, 10);\r
69     jalview.gui.SequenceRenderer sr;\r
70     jalview.gui.FeatureRenderer  fr;\r
71     jalview.gui.SeqCanvas seqcanvas;\r
72     Sequence sequence;\r
73     final StringBuffer mappingDetails = new StringBuffer();\r
74 \r
75     public PDBCanvas(jalview.gui.SeqCanvas seqcanvas, Sequence seq)\r
76     {\r
77       this.seqcanvas = seqcanvas;\r
78       this.sequence = seq;\r
79       sr = seqcanvas.getSequenceRenderer();\r
80       fr = seqcanvas.getFeatureRenderer();\r
81 \r
82       seqcanvas.setPDBViewer(this);\r
83     }\r
84 \r
85   public void setPDBFile(PDBfile pdb)\r
86    {\r
87         this.sr = sr;\r
88         this.fr = fr;\r
89         int max = -10;\r
90         int maxchain = -1;\r
91         int pdbstart = 0;\r
92         int pdbend = 0;\r
93         int seqstart = 0;\r
94         int seqend = 0;\r
95 \r
96         for (int i = 0; i < pdb.chains.size(); i++)\r
97         {\r
98 \r
99           mappingDetails.append("\n\nPDB Sequence is :\nSequence = " + ((PDBChain) pdb.chains.elementAt(i)).sequence.getSequence());\r
100           mappingDetails.append("\nNo of residues = " + ((PDBChain) pdb.chains.elementAt(i)).residues.size()+"\n\n");\r
101 \r
102             // Now lets compare the sequences to get\r
103             // the start and end points.\r
104             // Align the sequence to the pdb\r
105             AlignSeq as = new AlignSeq(sequence,\r
106                     ((PDBChain) pdb.chains.elementAt(i)).sequence, "pep");\r
107             as.calcScoreMatrix();\r
108             as.traceAlignment();\r
109             PrintStream  ps = new PrintStream(System.out)\r
110            {\r
111               public void print(String x) {\r
112                    mappingDetails.append(x);\r
113                }\r
114                public void println()\r
115                {\r
116                  mappingDetails.append("\n");\r
117                }\r
118             };\r
119 \r
120             as.printAlignment(ps);\r
121 \r
122             if (as.maxscore > max) {\r
123                 max = as.maxscore;\r
124                 maxchain = i;\r
125 \r
126                 pdbstart = as.seq2start;\r
127                 pdbend = as.seq2end;\r
128                 seqstart = as.seq1start + sequence.getStart()-1;\r
129                 seqend = as.seq1end + sequence.getEnd()-1;\r
130             }\r
131 \r
132             mappingDetails.append("\nPDB start/end "  + pdbstart + " " + pdbend);\r
133             mappingDetails.append("\nSEQ start/end "+ seqstart + " " + seqend);\r
134         }\r
135 \r
136         ((PDBChain) pdb.chains.elementAt(maxchain)).pdbstart = pdbstart;\r
137         ((PDBChain) pdb.chains.elementAt(maxchain)).pdbend = pdbend;\r
138         ((PDBChain) pdb.chains.elementAt(maxchain)).seqstart = seqstart;\r
139         ((PDBChain) pdb.chains.elementAt(maxchain)).seqend = seqend;\r
140         ((PDBChain) pdb.chains.elementAt(maxchain)).isVisible = true;\r
141         ((PDBChain) pdb.chains.elementAt(maxchain)).sequence = sequence;\r
142 \r
143         this.pdb = pdb;\r
144         this.prefsize = new Dimension(getWidth(), getHeight());\r
145 \r
146         //Initialize the matrices to identity\r
147         for (int i = 0; i < 3; i++) {\r
148             for (int j = 0; j < 3; j++) {\r
149                 if (i != j) {\r
150                     idmat.addElement(i, j, 0);\r
151                     objmat.addElement(i, j, 0);\r
152                 } else {\r
153                     idmat.addElement(i, j, 1);\r
154                     objmat.addElement(i, j, 1);\r
155                 }\r
156             }\r
157         }\r
158 \r
159         addMouseMotionListener(this);\r
160         addMouseListener(this);\r
161 \r
162         addMouseWheelListener(new MouseWheelListener()\r
163         {\r
164           public void mouseWheelMoved(MouseWheelEvent e)\r
165           {\r
166             if (e.getWheelRotation() > 0)\r
167             {\r
168               scale = (float) (scale * 1.1);\r
169               redrawneeded = true;\r
170               repaint();\r
171             }\r
172 \r
173             else\r
174             {\r
175               scale = (float) (scale * 0.9);\r
176               redrawneeded = true;\r
177               repaint();\r
178             }\r
179           }\r
180        });\r
181 \r
182 \r
183         findCentre();\r
184         findWidth();\r
185 \r
186         scale = findScale();\r
187 \r
188 \r
189         updateSeqColours();\r
190         ToolTipManager.sharedInstance().registerComponent(this);\r
191         ToolTipManager.sharedInstance().setInitialDelay(0);\r
192         ToolTipManager.sharedInstance().setDismissDelay(10000);\r
193 \r
194     }\r
195 \r
196     public void deleteBonds() {\r
197         scale = 0;\r
198         maxwidth = 0;\r
199 \r
200         width[0] = 0;\r
201         width[1] = 0;\r
202         width[2] = 0;\r
203 \r
204         centre[0] = 0;\r
205         centre[1] = 0;\r
206         centre[2] = 0;\r
207 \r
208         for (int i = 0; i < pdb.chains.size(); i++) {\r
209             ((PDBChain) pdb.chains.elementAt(i)).bonds = null;\r
210         }\r
211     }\r
212 \r
213     public void findWidth() {\r
214         float[] max = new float[3];\r
215         float[] min = new float[3];\r
216 \r
217         max[0] = (float) -1e30;\r
218         max[1] = (float) -1e30;\r
219         max[2] = (float) -1e30;\r
220 \r
221         min[0] = (float) 1e30;\r
222         min[1] = (float) 1e30;\r
223         min[2] = (float) 1e30;\r
224 \r
225         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
226             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {\r
227                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
228 \r
229                 for (int i = 0; i < bonds.size(); i++) {\r
230                     Bond tmp = (Bond) bonds.elementAt(i);\r
231 \r
232                     if (tmp.start[0] >= max[0]) {\r
233                         max[0] = tmp.start[0];\r
234                     }\r
235 \r
236                     if (tmp.start[1] >= max[1]) {\r
237                         max[1] = tmp.start[1];\r
238                     }\r
239 \r
240                     if (tmp.start[2] >= max[2]) {\r
241                         max[2] = tmp.start[2];\r
242                     }\r
243 \r
244                     if (tmp.start[0] <= min[0]) {\r
245                         min[0] = tmp.start[0];\r
246                     }\r
247 \r
248                     if (tmp.start[1] <= min[1]) {\r
249                         min[1] = tmp.start[1];\r
250                     }\r
251 \r
252                     if (tmp.start[2] <= min[2]) {\r
253                         min[2] = tmp.start[2];\r
254                     }\r
255 \r
256                     if (tmp.end[0] >= max[0]) {\r
257                         max[0] = tmp.end[0];\r
258                     }\r
259 \r
260                     if (tmp.end[1] >= max[1]) {\r
261                         max[1] = tmp.end[1];\r
262                     }\r
263 \r
264                     if (tmp.end[2] >= max[2]) {\r
265                         max[2] = tmp.end[2];\r
266                     }\r
267 \r
268                     if (tmp.end[0] <= min[0]) {\r
269                         min[0] = tmp.end[0];\r
270                     }\r
271 \r
272                     if (tmp.end[1] <= min[1]) {\r
273                         min[1] = tmp.end[1];\r
274                     }\r
275 \r
276                     if (tmp.end[2] <= min[2]) {\r
277                         min[2] = tmp.end[2];\r
278                     }\r
279                 }\r
280             }\r
281         }\r
282         /*\r
283         System.out.println("xmax " + max[0] + " min " + min[0]);\r
284         System.out.println("ymax " + max[1] + " min " + min[1]);\r
285         System.out.println("zmax " + max[2] + " min " + min[2]);*/\r
286 \r
287         width[0] = (float) Math.abs(max[0] - min[0]);\r
288         width[1] = (float) Math.abs(max[1] - min[1]);\r
289         width[2] = (float) Math.abs(max[2] - min[2]);\r
290 \r
291         maxwidth = width[0];\r
292 \r
293         if (width[1] > width[0]) {\r
294             maxwidth = width[1];\r
295         }\r
296 \r
297         if (width[2] > width[1]) {\r
298             maxwidth = width[2];\r
299         }\r
300 \r
301        // System.out.println("Maxwidth = " + maxwidth);\r
302     }\r
303 \r
304     public float findScale() {\r
305         int dim;\r
306         int width;\r
307         int height;\r
308 \r
309         if (getWidth() != 0) {\r
310             width = getWidth();\r
311             height = getHeight();\r
312         } else {\r
313             width = prefsize.width;\r
314             height = prefsize.height;\r
315         }\r
316 \r
317         if (width < height) {\r
318             dim = width;\r
319         } else {\r
320             dim = height;\r
321         }\r
322 \r
323         return (float) (dim / (1.5d * maxwidth));\r
324     }\r
325 \r
326     public void findCentre() {\r
327         float xtot = 0;\r
328         float ytot = 0;\r
329         float ztot = 0;\r
330 \r
331         int bsize = 0;\r
332 \r
333         //Find centre coordinate\r
334         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
335             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {\r
336                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
337 \r
338                 bsize += bonds.size();\r
339 \r
340                 for (int i = 0; i < bonds.size(); i++) {\r
341                     xtot = xtot + ((Bond) bonds.elementAt(i)).start[0] +\r
342                         ((Bond) bonds.elementAt(i)).end[0];\r
343 \r
344                     ytot = ytot + ((Bond) bonds.elementAt(i)).start[1] +\r
345                         ((Bond) bonds.elementAt(i)).end[1];\r
346 \r
347                     ztot = ztot + ((Bond) bonds.elementAt(i)).start[2] +\r
348                         ((Bond) bonds.elementAt(i)).end[2];\r
349                 }\r
350             }\r
351         }\r
352 \r
353         centre[0] = xtot / (2 * (float) bsize);\r
354         centre[1] = ytot / (2 * (float) bsize);\r
355         centre[2] = ztot / (2 * (float) bsize);\r
356     }\r
357 \r
358     public void paintComponent(Graphics g) {\r
359 \r
360       super.paintComponent(g);\r
361 \r
362       if(pdb==null)\r
363       {\r
364         g.setColor(Color.black);\r
365         g.setFont(new Font("Verdana", Font.BOLD, 14));\r
366         g.drawString("Retrieving PDB data....", 20, getHeight()/2);\r
367         return;\r
368       }\r
369 \r
370 \r
371         //Only create the image at the beginning -\r
372         //this saves much memory usage\r
373         if ((img == null) || (prefsize.width != getWidth()) ||\r
374                 (prefsize.height != getHeight())) {\r
375             prefsize.width = getWidth();\r
376             prefsize.height = getHeight();\r
377 \r
378             scale = findScale();\r
379             img = createImage(prefsize.width, prefsize.height);\r
380             ig = img.getGraphics();\r
381             Graphics2D ig2 = (Graphics2D) ig;\r
382 \r
383             ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
384                                  RenderingHints.VALUE_ANTIALIAS_ON);\r
385 \r
386 \r
387             redrawneeded = true;\r
388         }\r
389 \r
390 \r
391         if (redrawneeded)\r
392         {\r
393           drawAll(ig, prefsize.width, prefsize.height);\r
394           redrawneeded = false;\r
395         }\r
396 \r
397         g.drawImage(img, 0, 0, this);\r
398     }\r
399 \r
400     public void drawAll(Graphics g, int width, int height)\r
401     {\r
402       g.setColor(Color.black);\r
403       g.fillRect(0, 0, width, height);\r
404       drawScene(g);\r
405       drawLabels(g);\r
406     }\r
407 \r
408 \r
409     public void updateSeqColours()\r
410     {\r
411       if(bysequence && pdb!=null)\r
412       {\r
413         for (int ii = 0; ii < pdb.chains.size(); ii++)\r
414         {\r
415           ( (PDBChain) pdb.chains.elementAt(ii)).colourBySequence(sr, fr);\r
416         }\r
417       }\r
418 \r
419       redrawneeded=true;\r
420       repaint();\r
421 \r
422     }\r
423 \r
424     public void drawScene(Graphics g) {\r
425         // Sort the bonds by z coord\r
426         Vector bonds = new Vector();\r
427 \r
428         for (int ii = 0; ii < pdb.chains.size(); ii++)\r
429         {\r
430           if ( ( (PDBChain) pdb.chains.elementAt(ii)).isVisible)\r
431           {\r
432             Vector tmp = ( (PDBChain) pdb.chains.elementAt(ii)).bonds;\r
433 \r
434             for (int i = 0; i < tmp.size(); i++)\r
435             {\r
436               bonds.addElement(tmp.elementAt(i));\r
437             }\r
438           }\r
439         }\r
440 \r
441         if (zbuffer) {\r
442             Zsort.Zsort(bonds);\r
443         }\r
444 \r
445         for (int i = 0; i < bonds.size(); i++) {\r
446             Bond tmpBond = (Bond) bonds.elementAt(i);\r
447 \r
448             xstart = (int) (((tmpBond.start[0] - centre[0]) * scale) +\r
449                 (getWidth() / 2));\r
450             ystart = (int) (((tmpBond.start[1] - centre[1]) * scale) +\r
451                 (getHeight() / 2));\r
452 \r
453             xend = (int) (((tmpBond.end[0] - centre[0]) * scale) +\r
454                 (getWidth() / 2));\r
455             yend = (int) (((tmpBond.end[1] - centre[1]) * scale) +\r
456                 (getHeight() / 2));\r
457 \r
458             xmid = (xend + xstart) / 2;\r
459             ymid = (yend + ystart) / 2;\r
460 \r
461             if (depthcue && !bymolecule) {\r
462                 if (tmpBond.start[2] < (centre[2] - (maxwidth / 6))) {\r
463                     g.setColor(tmpBond.startCol.darker().darker());\r
464                     drawLine(g, xstart, ystart, xmid, ymid);\r
465 \r
466                     g.setColor(tmpBond.endCol.darker().darker());\r
467                     drawLine(g, xmid, ymid, xend, yend);\r
468                 } else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6))) {\r
469                     g.setColor(tmpBond.startCol.darker());\r
470                     drawLine(g, xstart, ystart, xmid, ymid);\r
471 \r
472                     g.setColor(tmpBond.endCol.darker());\r
473                     drawLine(g, xmid, ymid, xend, yend);\r
474                 } else {\r
475                     g.setColor(tmpBond.startCol);\r
476                     drawLine(g, xstart, ystart, xmid, ymid);\r
477 \r
478                     g.setColor(tmpBond.endCol);\r
479                     drawLine(g, xmid, ymid, xend, yend);\r
480                 }\r
481             } else if (depthcue && bymolecule) {\r
482                 if (tmpBond.start[2] < (centre[2] - (maxwidth / 6))) {\r
483                     g.setColor(Color.green.darker().darker());\r
484                     drawLine(g, xstart, ystart, xend, yend);\r
485                 } else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6))) {\r
486                     g.setColor(Color.green.darker());\r
487                     drawLine(g, xstart, ystart, xend, yend);\r
488                 } else {\r
489                     g.setColor(Color.green);\r
490                     drawLine(g, xstart, ystart, xend, yend);\r
491                 }\r
492             } else if (!depthcue && !bymolecule) {\r
493                 g.setColor(tmpBond.startCol);\r
494                 drawLine(g, xstart, ystart, xmid, ymid);\r
495                 g.setColor(tmpBond.endCol);\r
496                 drawLine(g, xmid, ymid, xend, yend);\r
497             } else {\r
498                 drawLine(g, xstart, ystart, xend, yend);\r
499             }\r
500         }\r
501     }\r
502 \r
503     public void drawLine(Graphics g, int x1, int y1, int x2, int y2) {\r
504         if (!wire) {\r
505             if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5) {\r
506                 g.drawLine(x1, y1, x2, y2);\r
507                 g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);\r
508                 g.drawLine(x1, y1 - 1, x2, y2 - 1);\r
509             } else {\r
510                 g.setColor(g.getColor().brighter());\r
511                 g.drawLine(x1, y1, x2, y2);\r
512                 g.drawLine(x1 + 1, y1, x2 + 1, y2);\r
513                 g.drawLine(x1 - 1, y1, x2 - 1, y2);\r
514             }\r
515         } else {\r
516             g.drawLine(x1, y1, x2, y2);\r
517         }\r
518     }\r
519 \r
520     public Dimension minimumsize() {\r
521         return prefsize;\r
522     }\r
523 \r
524     public Dimension preferredsize() {\r
525         return prefsize;\r
526     }\r
527 \r
528     public void keyPressed(KeyEvent evt)\r
529     {\r
530       if (evt.getKeyCode() == KeyEvent.VK_UP)\r
531       {\r
532         scale = (float) (scale * 1.1);\r
533         redrawneeded = true;\r
534         repaint();\r
535       }\r
536       else if (evt.getKeyCode() == KeyEvent.VK_DOWN)\r
537       {\r
538         scale = (float) (scale * 0.9);\r
539         redrawneeded = true;\r
540         repaint();\r
541       }\r
542     }\r
543 \r
544     public void mousePressed(MouseEvent e) {\r
545         myAtom fatom = findAtom(e.getX(), e.getY());\r
546         if(fatom!=null)\r
547         {\r
548           fatom.isSelected = !fatom.isSelected;\r
549           redrawneeded = true;\r
550           repaint();\r
551         }\r
552         mx = e.getX();\r
553         my = e.getY();\r
554         omx = mx;\r
555         omy = my;\r
556         dragging = false;\r
557     }\r
558 \r
559     public void mouseMoved(MouseEvent e) {\r
560 \r
561         myAtom fatom = findAtom(e.getX(), e.getY());\r
562 \r
563         if(foundchain!=-1)\r
564         {\r
565           PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);\r
566           int pos = chain.seqstart +\r
567               (fatom.resNumber - chain.pdbstart - chain.offset)+1;\r
568 \r
569           int index = seqcanvas.getViewport().getAlignment().findIndex(sequence);\r
570 \r
571           seqcanvas.highlightSearchResults(new int[]{index, pos, pos});\r
572         }\r
573         else\r
574           seqcanvas.highlightSearchResults(null);\r
575 \r
576         if (fatom != null) {\r
577             this.setToolTipText(fatom.resNumber+" "+ fatom.resName);\r
578         } else {\r
579             this.setToolTipText("");\r
580         }\r
581     }\r
582 \r
583     public void mouseClicked(MouseEvent e) {\r
584     }\r
585 \r
586     public void mouseEntered(MouseEvent e) {\r
587     }\r
588 \r
589     public void mouseExited(MouseEvent e) {\r
590     }\r
591 \r
592     public void mouseDragged(MouseEvent evt) {\r
593         int x = evt.getX();\r
594         int y = evt.getY();\r
595         mx = x;\r
596         my = y;\r
597 \r
598         MCMatrix objmat = new MCMatrix(3, 3);\r
599         objmat.setIdentity();\r
600 \r
601         if ((evt.getModifiers() & Event.META_MASK) != 0) {\r
602             objmat.rotatez((float) ((mx - omx)));\r
603         } else {\r
604             objmat.rotatex((float) ((my - omy)));\r
605             objmat.rotatey((float) ((omx - mx)));\r
606         }\r
607 \r
608         //Alter the bonds\r
609         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
610             Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
611 \r
612             for (int i = 0; i < bonds.size(); i++) {\r
613                 Bond tmpBond = (Bond) bonds.elementAt(i);\r
614 \r
615                 //Translate the bond so the centre is 0,0,0\r
616                 tmpBond.translate(-centre[0], -centre[1], -centre[2]);\r
617 \r
618                 //Now apply the rotation matrix\r
619                 tmpBond.start = objmat.vectorMultiply(tmpBond.start);\r
620                 tmpBond.end = objmat.vectorMultiply(tmpBond.end);\r
621 \r
622                 //Now translate back again\r
623                 tmpBond.translate(centre[0], centre[1], centre[2]);\r
624             }\r
625         }\r
626 \r
627         objmat = null;\r
628 \r
629         omx = mx;\r
630         omy = my;\r
631 \r
632         dragging = true;\r
633 \r
634         redrawneeded = true;\r
635 \r
636         repaint();\r
637     }\r
638 \r
639     public void mouseReleased(MouseEvent evt) {\r
640         dragging = false;\r
641         return;\r
642     }\r
643 \r
644     void drawLabels(Graphics g) {\r
645 \r
646         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
647             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);\r
648 \r
649             if (chain.isVisible) {\r
650                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
651 \r
652                 for (int i = 0; i < bonds.size(); i++) {\r
653                     Bond tmpBond = (Bond) bonds.elementAt(i);\r
654 \r
655                     if (tmpBond.at1.isSelected) {\r
656                         labelAtom(g, tmpBond, 1);\r
657                     }\r
658 \r
659                     if (tmpBond.at2.isSelected) {\r
660                         labelAtom(g, tmpBond, 2);\r
661                     }\r
662                 }\r
663             }\r
664         }\r
665     }\r
666 \r
667     public void labelAtom(Graphics g, Bond b, int n) {\r
668         g.setFont(font);\r
669 \r
670         if (n == 1) {\r
671             int xstart = (int) (((b.start[0] - centre[0]) * scale) +\r
672                 (getWidth() / 2));\r
673             int ystart = (int) (((b.start[1] - centre[1]) * scale) +\r
674                 (getHeight() / 2));\r
675 \r
676             g.setColor(Color.red);\r
677             g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);\r
678         }\r
679 \r
680         if (n == 2) {\r
681             int xstart = (int) (((b.end[0] - centre[0]) * scale) +\r
682                 (getWidth() / 2));\r
683             int ystart = (int) (((b.end[1] - centre[1]) * scale) +\r
684                 (getHeight() / 2));\r
685 \r
686             g.setColor(Color.red);\r
687             g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);\r
688         }\r
689     }\r
690 \r
691     int foundchain = -1;\r
692     public myAtom findAtom(int x, int y) {\r
693         myAtom fatom = null;\r
694 \r
695         foundchain = -1;\r
696 \r
697         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
698             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);\r
699 \r
700             if (chain.isVisible) {\r
701                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
702 \r
703                 for (int i = 0; i < bonds.size(); i++) {\r
704                     Bond tmpBond = (Bond) bonds.elementAt(i);\r
705 \r
706                     int truex = (int) (((tmpBond.start[0] - centre[0]) * scale) +\r
707                         (getWidth() / 2));\r
708 \r
709                     if (Math.abs(truex - x) <= 2) {\r
710                         int truey = (int) (((tmpBond.start[1] - centre[1]) * scale) +\r
711                             (getHeight() / 2));\r
712 \r
713                         if (Math.abs(truey - y) <= 2)\r
714                         {\r
715                             fatom = tmpBond.at1;\r
716                             foundchain = ii;\r
717                             break;\r
718                         }\r
719                     }\r
720                 }\r
721             }\r
722 \r
723             if (fatom != null) //)&& chain.ds != null)\r
724              {\r
725                 chain = (PDBChain) pdb.chains.elementAt(foundchain);\r
726             }\r
727         }\r
728 \r
729         return fatom;\r
730     }\r
731 }\r