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