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