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