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