jalview 2.5 release banner
[jalview.git] / src / MCview / AppletPDBCanvas.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package MCview;
19
20 import java.io.*;
21 import java.util.*;
22
23 // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug
24 import java.awt.*;
25 import java.awt.event.*;
26
27 import jalview.analysis.*;
28 import jalview.datamodel.*;
29
30 import jalview.appletgui.*;
31 import jalview.structure.*;
32
33 public class AppletPDBCanvas extends Panel implements MouseListener,
34         MouseMotionListener, StructureListener
35 {
36
37   MCMatrix idmat = new MCMatrix(3, 3);
38
39   MCMatrix objmat = new MCMatrix(3, 3);
40
41   boolean redrawneeded = true;
42
43   int omx = 0;
44
45   int mx = 0;
46
47   int omy = 0;
48
49   int my = 0;
50
51   public PDBfile pdb;
52
53   PDBEntry pdbentry;
54
55   int bsize;
56
57   Image img;
58
59   Graphics ig;
60
61   Dimension prefsize;
62
63   float[] centre = new float[3];
64
65   float[] width = new float[3];
66
67   float maxwidth;
68
69   float scale;
70
71   String inStr;
72
73   String inType;
74
75   boolean bysequence = true;
76
77   boolean depthcue = true;
78
79   boolean wire = false;
80
81   boolean bymolecule = false;
82
83   boolean zbuffer = true;
84
85   boolean dragging;
86
87   int xstart;
88
89   int xend;
90
91   int ystart;
92
93   int yend;
94
95   int xmid;
96
97   int ymid;
98
99   Font font = new Font("Helvetica", Font.PLAIN, 10);
100
101   public SequenceI[] sequence;
102
103   final StringBuffer mappingDetails = new StringBuffer();
104
105   String appletToolTip = null;
106
107   int toolx, tooly;
108
109   PDBChain mainchain;
110
111   Vector highlightRes;
112
113   boolean pdbAction = false;
114
115   Bond highlightBond1, highlightBond2;
116
117   boolean errorLoading = false;
118
119   boolean seqColoursReady = false;
120
121   FeatureRenderer fr;
122
123   AlignmentPanel ap;
124
125   StructureSelectionManager ssm;
126
127   public AppletPDBCanvas(PDBEntry pdbentry, SequenceI[] seq,
128           String[] chains, AlignmentPanel ap, String protocol)
129
130   {
131     this.ap = ap;
132     this.pdbentry = pdbentry;
133     this.sequence = seq;
134
135     ssm = StructureSelectionManager.getStructureSelectionManager();
136
137     try
138     {
139       pdb = ssm.setMapping(seq, chains, pdbentry.getFile(), protocol);
140
141       if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
142         pdbentry.setFile("INLINE" + pdb.id);
143
144     } catch (Exception ex)
145     {
146       ex.printStackTrace();
147       return;
148     }
149
150     pdbentry.setId(pdb.id);
151
152     ssm.addStructureViewerListener(this);
153
154     colourBySequence();
155
156     int max = -10;
157     int maxchain = -1;
158     int pdbstart = 0;
159     int pdbend = 0;
160     int seqstart = 0;
161     int seqend = 0;
162
163     // JUST DEAL WITH ONE SEQUENCE FOR NOW
164     SequenceI sequence = seq[0];
165
166     for (int i = 0; i < pdb.chains.size(); i++)
167     {
168
169       mappingDetails.append("\n\nPDB Sequence is :\nSequence = "
170               + ((PDBChain) pdb.chains.elementAt(i)).sequence
171                       .getSequenceAsString());
172       mappingDetails.append("\nNo of residues = "
173               + ((PDBChain) pdb.chains.elementAt(i)).residues.size()
174               + "\n\n");
175
176       // Now lets compare the sequences to get
177       // the start and end points.
178       // Align the sequence to the pdb
179       AlignSeq as = new AlignSeq(sequence, ((PDBChain) pdb.chains
180               .elementAt(i)).sequence, "pep");
181       as.calcScoreMatrix();
182       as.traceAlignment();
183       PrintStream ps = new PrintStream(System.out)
184       {
185         public void print(String x)
186         {
187           mappingDetails.append(x);
188         }
189
190         public void println()
191         {
192           mappingDetails.append("\n");
193         }
194       };
195
196       as.printAlignment(ps);
197
198       if (as.maxscore > max)
199       {
200         max = as.maxscore;
201         maxchain = i;
202
203         pdbstart = as.seq2start;
204         pdbend = as.seq2end;
205         seqstart = as.seq1start + sequence.getStart() - 1;
206         seqend = as.seq1end + sequence.getEnd() - 1;
207       }
208
209       mappingDetails.append("\nPDB start/end " + pdbstart + " " + pdbend);
210       mappingDetails.append("\nSEQ start/end " + seqstart + " " + seqend);
211     }
212
213     mainchain = (PDBChain) pdb.chains.elementAt(maxchain);
214
215     mainchain.pdbstart = pdbstart;
216     mainchain.pdbend = pdbend;
217     mainchain.seqstart = seqstart;
218     mainchain.seqend = seqend;
219     mainchain.isVisible = true;
220     // mainchain.makeExactMapping(maxAlignseq, sequence);
221     // mainchain.transferRESNUMFeatures(sequence, null);
222     this.pdb = pdb;
223     this.prefsize = new Dimension(getSize().width, getSize().height);
224
225     // Initialize the matrices to identity
226     for (int i = 0; i < 3; i++)
227     {
228       for (int j = 0; j < 3; j++)
229       {
230         if (i != j)
231         {
232           idmat.addElement(i, j, 0);
233           objmat.addElement(i, j, 0);
234         }
235         else
236         {
237           idmat.addElement(i, j, 1);
238           objmat.addElement(i, j, 1);
239         }
240       }
241     }
242
243     addMouseMotionListener(this);
244     addMouseListener(this);
245
246     addKeyListener(new KeyAdapter()
247     {
248       public void keyPressed(KeyEvent evt)
249       {
250         doKeyPressed(evt);
251       }
252     });
253
254     findCentre();
255     findWidth();
256
257     setupBonds();
258
259     scale = findScale();
260   }
261
262   Vector visiblebonds;
263
264   void setupBonds()
265   {
266     seqColoursReady = false;
267     // Sort the bonds by z coord
268     visiblebonds = new Vector();
269
270     for (int ii = 0; ii < pdb.chains.size(); ii++)
271     {
272       if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
273       {
274         Vector tmp = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
275
276         for (int i = 0; i < tmp.size(); i++)
277         {
278           visiblebonds.addElement(tmp.elementAt(i));
279         }
280       }
281     }
282     seqColoursReady = true;
283     colourBySequence();
284     redrawneeded = true;
285     repaint();
286   }
287
288   public void findWidth()
289   {
290     float[] max = new float[3];
291     float[] min = new float[3];
292
293     max[0] = (float) -1e30;
294     max[1] = (float) -1e30;
295     max[2] = (float) -1e30;
296
297     min[0] = (float) 1e30;
298     min[1] = (float) 1e30;
299     min[2] = (float) 1e30;
300
301     for (int ii = 0; ii < pdb.chains.size(); ii++)
302     {
303       if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
304       {
305         Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
306
307         for (int i = 0; i < bonds.size(); i++)
308         {
309           Bond tmp = (Bond) bonds.elementAt(i);
310
311           if (tmp.start[0] >= max[0])
312           {
313             max[0] = tmp.start[0];
314           }
315
316           if (tmp.start[1] >= max[1])
317           {
318             max[1] = tmp.start[1];
319           }
320
321           if (tmp.start[2] >= max[2])
322           {
323             max[2] = tmp.start[2];
324           }
325
326           if (tmp.start[0] <= min[0])
327           {
328             min[0] = tmp.start[0];
329           }
330
331           if (tmp.start[1] <= min[1])
332           {
333             min[1] = tmp.start[1];
334           }
335
336           if (tmp.start[2] <= min[2])
337           {
338             min[2] = tmp.start[2];
339           }
340
341           if (tmp.end[0] >= max[0])
342           {
343             max[0] = tmp.end[0];
344           }
345
346           if (tmp.end[1] >= max[1])
347           {
348             max[1] = tmp.end[1];
349           }
350
351           if (tmp.end[2] >= max[2])
352           {
353             max[2] = tmp.end[2];
354           }
355
356           if (tmp.end[0] <= min[0])
357           {
358             min[0] = tmp.end[0];
359           }
360
361           if (tmp.end[1] <= min[1])
362           {
363             min[1] = tmp.end[1];
364           }
365
366           if (tmp.end[2] <= min[2])
367           {
368             min[2] = tmp.end[2];
369           }
370         }
371       }
372     }
373
374     width[0] = (float) Math.abs(max[0] - min[0]);
375     width[1] = (float) Math.abs(max[1] - min[1]);
376     width[2] = (float) Math.abs(max[2] - min[2]);
377
378     maxwidth = width[0];
379
380     if (width[1] > width[0])
381     {
382       maxwidth = width[1];
383     }
384
385     if (width[2] > width[1])
386     {
387       maxwidth = width[2];
388     }
389
390     // System.out.println("Maxwidth = " + maxwidth);
391   }
392
393   public float findScale()
394   {
395     int dim;
396     int width;
397     int height;
398
399     if (getSize().width != 0)
400     {
401       width = getSize().width;
402       height = getSize().height;
403     }
404     else
405     {
406       width = prefsize.width;
407       height = prefsize.height;
408     }
409
410     if (width < height)
411     {
412       dim = width;
413     }
414     else
415     {
416       dim = height;
417     }
418
419     return (float) (dim / (1.5d * maxwidth));
420   }
421
422   public void findCentre()
423   {
424     float xtot = 0;
425     float ytot = 0;
426     float ztot = 0;
427
428     int bsize = 0;
429
430     // Find centre coordinate
431     for (int ii = 0; ii < pdb.chains.size(); ii++)
432     {
433       if (((PDBChain) pdb.chains.elementAt(ii)).isVisible)
434       {
435         Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
436
437         bsize += bonds.size();
438
439         for (int i = 0; i < bonds.size(); i++)
440         {
441           xtot = xtot + ((Bond) bonds.elementAt(i)).start[0]
442                   + ((Bond) bonds.elementAt(i)).end[0];
443
444           ytot = ytot + ((Bond) bonds.elementAt(i)).start[1]
445                   + ((Bond) bonds.elementAt(i)).end[1];
446
447           ztot = ztot + ((Bond) bonds.elementAt(i)).start[2]
448                   + ((Bond) bonds.elementAt(i)).end[2];
449         }
450       }
451     }
452
453     centre[0] = xtot / (2 * (float) bsize);
454     centre[1] = ytot / (2 * (float) bsize);
455     centre[2] = ztot / (2 * (float) bsize);
456   }
457
458   public void paint(Graphics g)
459   {
460
461     if (errorLoading)
462     {
463       g.setColor(Color.white);
464       g.fillRect(0, 0, getSize().width, getSize().height);
465       g.setColor(Color.black);
466       g.setFont(new Font("Verdana", Font.BOLD, 14));
467       g.drawString("Error loading PDB data!!", 50, getSize().height / 2);
468       return;
469     }
470
471     if (!seqColoursReady)
472     {
473       g.setColor(Color.black);
474       g.setFont(new Font("Verdana", Font.BOLD, 14));
475       g.drawString("Fetching PDB data...", 50, getSize().height / 2);
476       return;
477     }
478
479     // Only create the image at the beginning -
480     // this saves much memory usage
481     if ((img == null) || (prefsize.width != getSize().width)
482             || (prefsize.height != getSize().height))
483     {
484
485       try
486       {
487         prefsize.width = getSize().width;
488         prefsize.height = getSize().height;
489
490         scale = findScale();
491         img = createImage(prefsize.width, prefsize.height);
492         ig = img.getGraphics();
493
494         redrawneeded = true;
495       } catch (Exception ex)
496       {
497         ex.printStackTrace();
498       }
499     }
500
501     if (redrawneeded)
502     {
503       drawAll(ig, prefsize.width, prefsize.height);
504       redrawneeded = false;
505     }
506     if (appletToolTip != null)
507     {
508       ig.setColor(Color.red);
509       ig.drawString(appletToolTip, toolx, tooly);
510     }
511
512     g.drawImage(img, 0, 0, this);
513
514     pdbAction = false;
515   }
516
517   public void drawAll(Graphics g, int width, int height)
518   {
519     ig.setColor(Color.black);
520     ig.fillRect(0, 0, width, height);
521     drawScene(ig);
522     drawLabels(ig);
523   }
524
525   public void setColours(jalview.schemes.ColourSchemeI cs)
526   {
527     bysequence = false;
528     pdb.setColours(cs);
529     redrawneeded = true;
530     repaint();
531   }
532
533   // This method has been taken out of PDBChain to allow
534   // Applet and Application specific sequence renderers to be used
535   void colourBySequence()
536   {
537     SequenceRenderer sr = new SequenceRenderer(ap.av);
538
539     StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile());
540
541     boolean showFeatures = false;
542     if (ap.av.getShowSequenceFeatures())
543     {
544       if (fr == null)
545       {
546         fr = new jalview.appletgui.FeatureRenderer(ap.av);
547       }
548
549       fr.transferSettings(ap.getFeatureRenderer());
550
551       showFeatures = true;
552     }
553
554     PDBChain chain;
555     if (bysequence && pdb != null)
556     {
557       for (int ii = 0; ii < pdb.chains.size(); ii++)
558       {
559         chain = (PDBChain) pdb.chains.elementAt(ii);
560
561         for (int i = 0; i < chain.bonds.size(); i++)
562         {
563           Bond tmp = (Bond) chain.bonds.elementAt(i);
564           tmp.startCol = Color.lightGray;
565           tmp.endCol = Color.lightGray;
566           if (chain != mainchain)
567           {
568             continue;
569           }
570
571           for (int s = 0; s < sequence.length; s++)
572           {
573             for (int m = 0; m < mapping.length; m++)
574             {
575               if (mapping[m].getSequence() == sequence[s])
576               {
577                 int pos = mapping[m].getSeqPos(tmp.at1.resNumber) - 1;
578                 if (pos > 0)
579                 {
580                   pos = sequence[s].findIndex(pos);
581                   tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
582                   if (showFeatures)
583                   {
584                     tmp.startCol = fr.findFeatureColour(tmp.startCol,
585                             sequence[s], pos);
586                   }
587                 }
588                 pos = mapping[m].getSeqPos(tmp.at2.resNumber) - 1;
589                 if (pos > 0)
590                 {
591                   pos = sequence[s].findIndex(pos);
592                   tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
593                   if (showFeatures)
594                   {
595                     tmp.endCol = fr.findFeatureColour(tmp.endCol,
596                             sequence[s], pos);
597                   }
598                 }
599
600               }
601             }
602           }
603         }
604       }
605     }
606   }
607
608   Zsort zsort;
609
610   public void drawScene(Graphics g)
611   {
612     if (zbuffer)
613     {
614       if (zsort == null)
615       {
616         zsort = new Zsort();
617       }
618
619       zsort.Zsort(visiblebonds);
620     }
621
622     Bond tmpBond = null;
623     for (int i = 0; i < visiblebonds.size(); i++)
624     {
625       tmpBond = (Bond) visiblebonds.elementAt(i);
626
627       xstart = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
628       ystart = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
629
630       xend = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
631       yend = (int) (((centre[1] - tmpBond.end[1]) * scale) + (getSize().height / 2));
632
633       xmid = (xend + xstart) / 2;
634       ymid = (yend + ystart) / 2;
635
636       if (depthcue && !bymolecule)
637       {
638         if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
639         {
640           g.setColor(tmpBond.startCol.darker().darker());
641           drawLine(g, xstart, ystart, xmid, ymid);
642
643           g.setColor(tmpBond.endCol.darker().darker());
644           drawLine(g, xmid, ymid, xend, yend);
645         }
646         else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
647         {
648           g.setColor(tmpBond.startCol.darker());
649           drawLine(g, xstart, ystart, xmid, ymid);
650
651           g.setColor(tmpBond.endCol.darker());
652           drawLine(g, xmid, ymid, xend, yend);
653         }
654         else
655         {
656           g.setColor(tmpBond.startCol);
657           drawLine(g, xstart, ystart, xmid, ymid);
658
659           g.setColor(tmpBond.endCol);
660           drawLine(g, xmid, ymid, xend, yend);
661         }
662
663       }
664       else if (depthcue && bymolecule)
665       {
666         if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))
667         {
668           g.setColor(Color.green.darker().darker());
669           drawLine(g, xstart, ystart, xend, yend);
670         }
671         else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))
672         {
673           g.setColor(Color.green.darker());
674           drawLine(g, xstart, ystart, xend, yend);
675         }
676         else
677         {
678           g.setColor(Color.green);
679           drawLine(g, xstart, ystart, xend, yend);
680         }
681       }
682       else if (!depthcue && !bymolecule)
683       {
684         g.setColor(tmpBond.startCol);
685         drawLine(g, xstart, ystart, xmid, ymid);
686         g.setColor(tmpBond.endCol);
687         drawLine(g, xmid, ymid, xend, yend);
688       }
689       else
690       {
691         drawLine(g, xstart, ystart, xend, yend);
692       }
693
694       if (highlightBond1 != null && highlightBond1 == tmpBond)
695       {
696         g.setColor(Color.white);
697         drawLine(g, xmid, ymid, xend, yend);
698       }
699
700       if (highlightBond2 != null && highlightBond2 == tmpBond)
701       {
702         g.setColor(Color.white);
703         drawLine(g, xstart, ystart, xmid, ymid);
704       }
705
706     }
707   }
708
709   public void drawLine(Graphics g, int x1, int y1, int x2, int y2)
710   {
711     if (!wire)
712     {
713       if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5)
714       {
715         g.drawLine(x1, y1, x2, y2);
716         g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);
717         g.drawLine(x1, y1 - 1, x2, y2 - 1);
718       }
719       else
720       {
721         g.setColor(g.getColor().brighter());
722         g.drawLine(x1, y1, x2, y2);
723         g.drawLine(x1 + 1, y1, x2 + 1, y2);
724         g.drawLine(x1 - 1, y1, x2 - 1, y2);
725       }
726     }
727     else
728     {
729       g.drawLine(x1, y1, x2, y2);
730     }
731   }
732
733   public Dimension minimumsize()
734   {
735     return prefsize;
736   }
737
738   public Dimension preferredsize()
739   {
740     return prefsize;
741   }
742
743   public void doKeyPressed(KeyEvent evt)
744   {
745     if (evt.getKeyCode() == KeyEvent.VK_UP)
746     {
747       scale = (float) (scale * 1.1);
748       redrawneeded = true;
749       repaint();
750     }
751     else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
752     {
753       scale = (float) (scale * 0.9);
754       redrawneeded = true;
755       repaint();
756     }
757   }
758
759   public void mousePressed(MouseEvent e)
760   {
761     pdbAction = true;
762     Atom fatom = findAtom(e.getX(), e.getY());
763     if (fatom != null)
764     {
765       fatom.isSelected = !fatom.isSelected;
766
767       redrawneeded = true;
768       repaint();
769       if (foundchain != -1)
770       {
771         PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);
772         if (chain == mainchain)
773         {
774           if (fatom.alignmentMapping != -1)
775           {
776             if (highlightRes == null)
777             {
778               highlightRes = new Vector();
779             }
780
781             if (highlightRes.contains(fatom.alignmentMapping + "" + ""))
782             {
783               highlightRes.removeElement(fatom.alignmentMapping + "");
784             }
785             else
786             {
787               highlightRes.addElement(fatom.alignmentMapping + "");
788             }
789           }
790         }
791       }
792
793     }
794     mx = e.getX();
795     my = e.getY();
796     omx = mx;
797     omy = my;
798     dragging = false;
799   }
800
801   public void mouseMoved(MouseEvent e)
802   {
803     pdbAction = true;
804     if (highlightBond1 != null)
805     {
806       highlightBond1.at2.isSelected = false;
807       highlightBond2.at1.isSelected = false;
808       highlightBond1 = null;
809       highlightBond2 = null;
810     }
811
812     Atom fatom = findAtom(e.getX(), e.getY());
813
814     PDBChain chain = null;
815     if (foundchain != -1)
816     {
817       chain = (PDBChain) pdb.chains.elementAt(foundchain);
818       if (chain == mainchain)
819       {
820         mouseOverStructure(fatom.resNumber, chain.id);
821       }
822     }
823
824     if (fatom != null)
825     {
826       toolx = e.getX();
827       tooly = e.getY();
828
829       appletToolTip = chain.id + ":" + fatom.resNumber + " "
830               + fatom.resName;
831       redrawneeded = true;
832       repaint();
833     }
834     else
835     {
836       mouseOverStructure(-1, chain != null ? chain.id : null);
837       appletToolTip = null;
838       redrawneeded = true;
839       repaint();
840     }
841   }
842
843   public void mouseClicked(MouseEvent e)
844   {
845   }
846
847   public void mouseEntered(MouseEvent e)
848   {
849   }
850
851   public void mouseExited(MouseEvent e)
852   {
853   }
854
855   public void mouseDragged(MouseEvent evt)
856   {
857     int x = evt.getX();
858     int y = evt.getY();
859     mx = x;
860     my = y;
861
862     MCMatrix objmat = new MCMatrix(3, 3);
863     objmat.setIdentity();
864
865     if ((evt.getModifiers() & Event.META_MASK) != 0)
866     {
867       objmat.rotatez((float) ((mx - omx)));
868     }
869     else
870     {
871       objmat.rotatex((float) ((omy - my)));
872       objmat.rotatey((float) ((omx - mx)));
873     }
874
875     // Alter the bonds
876     for (int ii = 0; ii < pdb.chains.size(); ii++)
877     {
878       Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
879
880       for (int i = 0; i < bonds.size(); i++)
881       {
882         Bond tmpBond = (Bond) bonds.elementAt(i);
883
884         // Translate the bond so the centre is 0,0,0
885         tmpBond.translate(-centre[0], -centre[1], -centre[2]);
886
887         // Now apply the rotation matrix
888         tmpBond.start = objmat.vectorMultiply(tmpBond.start);
889         tmpBond.end = objmat.vectorMultiply(tmpBond.end);
890
891         // Now translate back again
892         tmpBond.translate(centre[0], centre[1], centre[2]);
893       }
894     }
895
896     objmat = null;
897
898     omx = mx;
899     omy = my;
900
901     dragging = true;
902
903     redrawneeded = true;
904
905     repaint();
906   }
907
908   public void mouseReleased(MouseEvent evt)
909   {
910     dragging = false;
911     return;
912   }
913
914   void drawLabels(Graphics g)
915   {
916
917     for (int ii = 0; ii < pdb.chains.size(); ii++)
918     {
919       PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
920
921       if (chain.isVisible)
922       {
923         Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
924
925         for (int i = 0; i < bonds.size(); i++)
926         {
927           Bond tmpBond = (Bond) bonds.elementAt(i);
928
929           if (tmpBond.at1.isSelected)
930           {
931             labelAtom(g, tmpBond, 1);
932           }
933
934           if (tmpBond.at2.isSelected)
935           {
936
937             labelAtom(g, tmpBond, 2);
938           }
939         }
940       }
941     }
942   }
943
944   public void labelAtom(Graphics g, Bond b, int n)
945   {
946     g.setFont(font);
947
948     if (n == 1)
949     {
950       int xstart = (int) (((b.start[0] - centre[0]) * scale) + (getSize().width / 2));
951       int ystart = (int) (((centre[1] - b.start[1]) * scale) + (getSize().height / 2));
952
953       g.setColor(Color.red);
954       g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);
955     }
956
957     if (n == 2)
958     {
959       int xstart = (int) (((b.end[0] - centre[0]) * scale) + (getSize().width / 2));
960       int ystart = (int) (((centre[1] - b.end[1]) * scale) + (getSize().height / 2));
961
962       g.setColor(Color.red);
963       g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);
964     }
965   }
966
967   int foundchain = -1;
968
969   public Atom findAtom(int x, int y)
970   {
971     Atom fatom = null;
972
973     foundchain = -1;
974
975     for (int ii = 0; ii < pdb.chains.size(); ii++)
976     {
977       PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
978       int truex;
979       Bond tmpBond = null;
980
981       if (chain.isVisible)
982       {
983         Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;
984
985         for (int i = 0; i < bonds.size(); i++)
986         {
987           tmpBond = (Bond) bonds.elementAt(i);
988
989           truex = (int) (((tmpBond.start[0] - centre[0]) * scale) + (getSize().width / 2));
990
991           if (Math.abs(truex - x) <= 2)
992           {
993             int truey = (int) (((centre[1] - tmpBond.start[1]) * scale) + (getSize().height / 2));
994
995             if (Math.abs(truey - y) <= 2)
996             {
997               fatom = tmpBond.at1;
998               foundchain = ii;
999               break;
1000             }
1001           }
1002         }
1003
1004         // Still here? Maybe its the last bond
1005
1006         truex = (int) (((tmpBond.end[0] - centre[0]) * scale) + (getSize().width / 2));
1007
1008         if (Math.abs(truex - x) <= 2)
1009         {
1010           int truey = (int) (((tmpBond.end[1] - centre[1]) * scale) + (getSize().height / 2));
1011
1012           if (Math.abs(truey - y) <= 2)
1013           {
1014             fatom = tmpBond.at2;
1015             foundchain = ii;
1016             break;
1017           }
1018         }
1019
1020       }
1021
1022       if (fatom != null) // )&& chain.ds != null)
1023       {
1024         chain = (PDBChain) pdb.chains.elementAt(foundchain);
1025       }
1026     }
1027
1028     return fatom;
1029   }
1030
1031   public void update(Graphics g)
1032   {
1033     paint(g);
1034   }
1035
1036   public void highlightRes(int ii)
1037   {
1038     if (!seqColoursReady)
1039     {
1040       return;
1041     }
1042
1043     if (highlightRes != null && highlightRes.contains((ii - 1) + ""))
1044     {
1045       return;
1046     }
1047
1048     int index = -1;
1049     Bond tmpBond;
1050     for (index = 0; index < mainchain.bonds.size(); index++)
1051     {
1052       tmpBond = (Bond) mainchain.bonds.elementAt(index);
1053       if (tmpBond.at1.alignmentMapping == ii - 1)
1054       {
1055         if (highlightBond1 != null)
1056         {
1057           highlightBond1.at2.isSelected = false;
1058         }
1059
1060         if (highlightBond2 != null)
1061         {
1062           highlightBond2.at1.isSelected = false;
1063         }
1064
1065         highlightBond1 = null;
1066         highlightBond2 = null;
1067
1068         if (index > 0)
1069         {
1070           highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
1071           highlightBond1.at2.isSelected = true;
1072         }
1073
1074         if (index != mainchain.bonds.size())
1075         {
1076           highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
1077           highlightBond2.at1.isSelected = true;
1078         }
1079
1080         break;
1081       }
1082     }
1083
1084     redrawneeded = true;
1085     repaint();
1086   }
1087
1088   public void setAllchainsVisible(boolean b)
1089   {
1090     for (int ii = 0; ii < pdb.chains.size(); ii++)
1091     {
1092       PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);
1093       chain.isVisible = b;
1094     }
1095     mainchain.isVisible = true;
1096     findCentre();
1097     setupBonds();
1098   }
1099
1100   // ////////////////////////////////
1101   // /StructureListener
1102   public String getPdbFile()
1103   {
1104     return pdbentry.getFile();
1105   }
1106
1107   String lastMessage;
1108
1109   public void mouseOverStructure(int pdbResNum, String chain)
1110   {
1111     if (lastMessage == null || !lastMessage.equals(pdbResNum + chain))
1112       ssm.mouseOverStructure(pdbResNum, chain, pdbentry.getFile());
1113
1114     lastMessage = pdbResNum + chain;
1115   }
1116
1117   StringBuffer resetLastRes = new StringBuffer();
1118
1119   StringBuffer eval = new StringBuffer();
1120
1121   public void highlightAtom(int atomIndex, int pdbResNum, String chain,
1122           String pdbfile)
1123   {
1124     if (!seqColoursReady)
1125     {
1126       return;
1127     }
1128
1129     if (highlightRes != null && highlightRes.contains((atomIndex - 1) + ""))
1130     {
1131       return;
1132     }
1133
1134     int index = -1;
1135     Bond tmpBond;
1136     for (index = 0; index < mainchain.bonds.size(); index++)
1137     {
1138       tmpBond = (Bond) mainchain.bonds.elementAt(index);
1139       if (tmpBond.at1.atomIndex == atomIndex)
1140       {
1141         if (highlightBond1 != null)
1142         {
1143           highlightBond1.at2.isSelected = false;
1144         }
1145
1146         if (highlightBond2 != null)
1147         {
1148           highlightBond2.at1.isSelected = false;
1149         }
1150
1151         highlightBond1 = null;
1152         highlightBond2 = null;
1153
1154         if (index > 0)
1155         {
1156           highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);
1157           highlightBond1.at2.isSelected = true;
1158         }
1159
1160         if (index != mainchain.bonds.size())
1161         {
1162           highlightBond2 = (Bond) mainchain.bonds.elementAt(index);
1163           highlightBond2.at1.isSelected = true;
1164         }
1165
1166         break;
1167       }
1168     }
1169
1170     redrawneeded = true;
1171     repaint();
1172   }
1173
1174   public Color getColour(int atomIndex, int pdbResNum, String chain,
1175           String pdbfile)
1176   {
1177     return Color.white;
1178     // if (!pdbfile.equals(pdbentry.getFile()))
1179     // return null;
1180
1181     // return new Color(viewer.getAtomArgb(atomIndex));
1182   }
1183
1184   public void updateColours(Object source)
1185   {
1186     colourBySequence();
1187     redrawneeded = true;
1188     repaint();
1189   }
1190
1191 }