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