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