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