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