Changeable background colour
[jalview.git] / src / MCview / PDBCanvas.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4 *\r
5 * This program is free software; you can redistribute it and/or\r
6 * modify it under the terms of the GNU General Public License\r
7 * as published by the Free Software Foundation; either version 2\r
8 * of the License, or (at your option) any later version.\r
9 *\r
10 * This program is distributed in the hope that it will be useful,\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 * GNU General Public License for more details.\r
14 *\r
15 * You should have received a copy of the GNU General Public License\r
16 * along with this program; if not, write to the Free Software\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18 */\r
19 package MCview;\r
20 \r
21 import jalview.analysis.AlignSeq;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 // JBPNote TODO: This class is quite noisy - needs proper log.info/log.debug\r
26 import java.awt.*;\r
27 import java.awt.event.*;\r
28 \r
29 import java.io.*;\r
30 \r
31 import java.util.*;\r
32 \r
33 import javax.swing.*;\r
34 \r
35 \r
36 public class PDBCanvas extends JPanel implements MouseListener, MouseMotionListener\r
37 {\r
38     MCMatrix idmat = new MCMatrix(3, 3);\r
39     MCMatrix objmat = new MCMatrix(3, 3);\r
40     boolean redrawneeded = true;\r
41     int omx = 0;\r
42     int mx = 0;\r
43     int omy = 0;\r
44     int my = 0;\r
45     public PDBfile pdb;\r
46     int bsize;\r
47     Image img;\r
48     Graphics ig;\r
49     Dimension prefsize;\r
50     float[] centre = new float[3];\r
51     float[] width = new float[3];\r
52     float maxwidth;\r
53     float scale;\r
54     String inStr;\r
55     String inType;\r
56     boolean bysequence = true;\r
57     boolean depthcue = true;\r
58     boolean wire = false;\r
59     boolean bymolecule = false;\r
60     boolean zbuffer = true;\r
61     boolean dragging;\r
62     int xstart;\r
63     int xend;\r
64     int ystart;\r
65     int yend;\r
66     int xmid;\r
67     int ymid;\r
68     Font font = new Font("Helvetica", Font.PLAIN, 10);\r
69     jalview.gui.SeqCanvas seqcanvas;\r
70     public Sequence sequence;\r
71     final StringBuffer mappingDetails = new StringBuffer();\r
72     PDBChain mainchain;\r
73     Vector highlightRes;\r
74     boolean pdbAction = false;\r
75     boolean seqColoursReady = false;\r
76     jalview.gui.FeatureRenderer fr;\r
77     Color backgroundColour = Color.black;\r
78 \r
79     public PDBCanvas(jalview.gui.SeqCanvas seqcanvas, Sequence seq)\r
80     {\r
81       this.seqcanvas = seqcanvas;\r
82       this.sequence = seq;\r
83       seqcanvas.setPDBCanvas(this);\r
84     }\r
85 \r
86   public void setPDBFile(PDBfile pdb)\r
87    {\r
88         int max = -10;\r
89         int maxchain = -1;\r
90         int pdbstart = 0;\r
91         int pdbend = 0;\r
92         int seqstart = 0;\r
93         int seqend = 0;\r
94         AlignSeq maxAlignseq = null;\r
95 \r
96         for (int i = 0; i < pdb.chains.size(); i++)\r
97         {\r
98 \r
99           mappingDetails.append("\n\nPDB Sequence is :\nSequence = " + ((PDBChain) pdb.chains.elementAt(i)).sequence.getSequence());\r
100           mappingDetails.append("\nNo of residues = " + ((PDBChain) pdb.chains.elementAt(i)).residues.size()+"\n\n");\r
101 \r
102             // Now lets compare the sequences to get\r
103             // the start and end points.\r
104             // Align the sequence to the pdb\r
105             AlignSeq as = new AlignSeq(sequence,\r
106                     ((PDBChain) pdb.chains.elementAt(i)).sequence, "pep");\r
107             as.calcScoreMatrix();\r
108             as.traceAlignment();\r
109             PrintStream  ps = new PrintStream(System.out)\r
110            {\r
111               public void print(String x) {\r
112                    mappingDetails.append(x);\r
113                }\r
114                public void println()\r
115                {\r
116                  mappingDetails.append("\n");\r
117                }\r
118             };\r
119 \r
120             as.printAlignment(ps);\r
121 \r
122 \r
123 \r
124             if (as.maxscore > max)\r
125             {\r
126                 max = as.maxscore;\r
127                 maxchain = i;\r
128                 pdbstart = as.seq2start;\r
129                 pdbend = as.seq2end;\r
130                 seqstart = as.seq1start + sequence.getStart()-1;\r
131                 seqend = as.seq1end + sequence.getEnd()-1;\r
132                 maxAlignseq = as;\r
133             }\r
134 \r
135             mappingDetails.append("\nPDB start/end "  + pdbstart + " " + pdbend);\r
136             mappingDetails.append("\nSEQ start/end "+ seqstart + " " + seqend);\r
137         }\r
138 \r
139         mainchain = (PDBChain) pdb.chains.elementAt(maxchain);\r
140 \r
141         mainchain.pdbstart = pdbstart;\r
142         mainchain.pdbend = pdbend;\r
143         mainchain.seqstart = seqstart;\r
144         mainchain.seqend = seqend;\r
145         mainchain.isVisible = true;\r
146         mainchain.makeExactMapping(maxAlignseq, sequence);\r
147 \r
148         this.pdb = pdb;\r
149         this.prefsize = new Dimension(getWidth(), getHeight());\r
150 \r
151         //Initialize the matrices to identity\r
152         for (int i = 0; i < 3; i++) {\r
153             for (int j = 0; j < 3; j++) {\r
154                 if (i != j) {\r
155                     idmat.addElement(i, j, 0);\r
156                     objmat.addElement(i, j, 0);\r
157                 } else {\r
158                     idmat.addElement(i, j, 1);\r
159                     objmat.addElement(i, j, 1);\r
160                 }\r
161             }\r
162         }\r
163 \r
164         addMouseMotionListener(this);\r
165         addMouseListener(this);\r
166 \r
167         addMouseWheelListener(new MouseWheelListener()\r
168         {\r
169           public void mouseWheelMoved(MouseWheelEvent e)\r
170           {\r
171             if (e.getWheelRotation() > 0)\r
172             {\r
173               scale = (float) (scale * 1.1);\r
174               redrawneeded = true;\r
175               repaint();\r
176             }\r
177 \r
178             else\r
179             {\r
180               scale = (float) (scale * 0.9);\r
181               redrawneeded = true;\r
182               repaint();\r
183             }\r
184           }\r
185        });\r
186 \r
187 \r
188         findCentre();\r
189         findWidth();\r
190 \r
191         setupBonds();\r
192 \r
193         scale = findScale();\r
194 \r
195         ToolTipManager.sharedInstance().registerComponent(this);\r
196         ToolTipManager.sharedInstance().setInitialDelay(0);\r
197         ToolTipManager.sharedInstance().setDismissDelay(10000);\r
198     }\r
199 \r
200 \r
201     Vector visiblebonds;\r
202     void setupBonds()\r
203     {\r
204       seqColoursReady = false;\r
205       // Sort the bonds by z coord\r
206       visiblebonds = new Vector();\r
207 \r
208       for (int ii = 0; ii < pdb.chains.size(); ii++)\r
209       {\r
210         if ( ( (PDBChain) pdb.chains.elementAt(ii)).isVisible)\r
211         {\r
212           Vector tmp = ( (PDBChain) pdb.chains.elementAt(ii)).bonds;\r
213 \r
214           for (int i = 0; i < tmp.size(); i++)\r
215           {\r
216             visiblebonds.addElement(tmp.elementAt(i));\r
217           }\r
218         }\r
219       }\r
220 \r
221       updateSeqColours();\r
222       seqColoursReady = true;\r
223       redrawneeded = true;\r
224       repaint();\r
225     }\r
226 \r
227 \r
228     public void findWidth() {\r
229         float[] max = new float[3];\r
230         float[] min = new float[3];\r
231 \r
232         max[0] = (float) -1e30;\r
233         max[1] = (float) -1e30;\r
234         max[2] = (float) -1e30;\r
235 \r
236         min[0] = (float) 1e30;\r
237         min[1] = (float) 1e30;\r
238         min[2] = (float) 1e30;\r
239 \r
240         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
241             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {\r
242                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
243 \r
244                 for (int i = 0; i < bonds.size(); i++) {\r
245                     Bond tmp = (Bond) bonds.elementAt(i);\r
246 \r
247                     if (tmp.start[0] >= max[0]) {\r
248                         max[0] = tmp.start[0];\r
249                     }\r
250 \r
251                     if (tmp.start[1] >= max[1]) {\r
252                         max[1] = tmp.start[1];\r
253                     }\r
254 \r
255                     if (tmp.start[2] >= max[2]) {\r
256                         max[2] = tmp.start[2];\r
257                     }\r
258 \r
259                     if (tmp.start[0] <= min[0]) {\r
260                         min[0] = tmp.start[0];\r
261                     }\r
262 \r
263                     if (tmp.start[1] <= min[1]) {\r
264                         min[1] = tmp.start[1];\r
265                     }\r
266 \r
267                     if (tmp.start[2] <= min[2]) {\r
268                         min[2] = tmp.start[2];\r
269                     }\r
270 \r
271                     if (tmp.end[0] >= max[0]) {\r
272                         max[0] = tmp.end[0];\r
273                     }\r
274 \r
275                     if (tmp.end[1] >= max[1]) {\r
276                         max[1] = tmp.end[1];\r
277                     }\r
278 \r
279                     if (tmp.end[2] >= max[2]) {\r
280                         max[2] = tmp.end[2];\r
281                     }\r
282 \r
283                     if (tmp.end[0] <= min[0]) {\r
284                         min[0] = tmp.end[0];\r
285                     }\r
286 \r
287                     if (tmp.end[1] <= min[1]) {\r
288                         min[1] = tmp.end[1];\r
289                     }\r
290 \r
291                     if (tmp.end[2] <= min[2]) {\r
292                         min[2] = tmp.end[2];\r
293                     }\r
294                 }\r
295             }\r
296         }\r
297         /*\r
298         System.out.println("xmax " + max[0] + " min " + min[0]);\r
299         System.out.println("ymax " + max[1] + " min " + min[1]);\r
300         System.out.println("zmax " + max[2] + " min " + min[2]);*/\r
301 \r
302         width[0] = (float) Math.abs(max[0] - min[0]);\r
303         width[1] = (float) Math.abs(max[1] - min[1]);\r
304         width[2] = (float) Math.abs(max[2] - min[2]);\r
305 \r
306         maxwidth = width[0];\r
307 \r
308         if (width[1] > width[0]) {\r
309             maxwidth = width[1];\r
310         }\r
311 \r
312         if (width[2] > width[1]) {\r
313             maxwidth = width[2];\r
314         }\r
315 \r
316        // System.out.println("Maxwidth = " + maxwidth);\r
317     }\r
318 \r
319     public float findScale() {\r
320         int dim;\r
321         int width;\r
322         int height;\r
323 \r
324         if (getWidth() != 0) {\r
325             width = getWidth();\r
326             height = getHeight();\r
327         } else {\r
328             width = prefsize.width;\r
329             height = prefsize.height;\r
330         }\r
331 \r
332         if (width < height) {\r
333             dim = width;\r
334         } else {\r
335             dim = height;\r
336         }\r
337 \r
338         return (float) (dim / (1.5d * maxwidth));\r
339     }\r
340 \r
341     public void findCentre() {\r
342         float xtot = 0;\r
343         float ytot = 0;\r
344         float ztot = 0;\r
345 \r
346         int bsize = 0;\r
347 \r
348         //Find centre coordinate\r
349         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
350             if (((PDBChain) pdb.chains.elementAt(ii)).isVisible) {\r
351                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
352 \r
353                 bsize += bonds.size();\r
354 \r
355                 for (int i = 0; i < bonds.size(); i++) {\r
356                     xtot = xtot + ((Bond) bonds.elementAt(i)).start[0] +\r
357                         ((Bond) bonds.elementAt(i)).end[0];\r
358 \r
359                     ytot = ytot + ((Bond) bonds.elementAt(i)).start[1] +\r
360                         ((Bond) bonds.elementAt(i)).end[1];\r
361 \r
362                     ztot = ztot + ((Bond) bonds.elementAt(i)).start[2] +\r
363                         ((Bond) bonds.elementAt(i)).end[2];\r
364                 }\r
365             }\r
366         }\r
367 \r
368         centre[0] = xtot / (2 * (float) bsize);\r
369         centre[1] = ytot / (2 * (float) bsize);\r
370         centre[2] = ztot / (2 * (float) bsize);\r
371     }\r
372 \r
373     public void paintComponent(Graphics g)\r
374     {\r
375       super.paintComponent(g);\r
376 \r
377       if(!seqColoursReady)\r
378       {\r
379         g.setColor(Color.black);\r
380         g.setFont(new Font("Verdana", Font.BOLD, 14));\r
381         g.drawString("Retrieving PDB data....", 20, getHeight()/2);\r
382         return;\r
383       }\r
384 \r
385 \r
386         //Only create the image at the beginning -\r
387         //this saves much memory usage\r
388         if ((img == null)\r
389             || (prefsize.width != getWidth())\r
390             || (prefsize.height != getHeight()))\r
391 \r
392       {\r
393             prefsize.width = getWidth();\r
394             prefsize.height = getHeight();\r
395 \r
396             scale = findScale();\r
397             img = createImage(prefsize.width, prefsize.height);\r
398             ig = img.getGraphics();\r
399             Graphics2D ig2 = (Graphics2D) ig;\r
400 \r
401             ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
402                                  RenderingHints.VALUE_ANTIALIAS_ON);\r
403 \r
404             redrawneeded = true;\r
405         }\r
406 \r
407 \r
408         if (redrawneeded)\r
409         {\r
410           drawAll(ig, prefsize.width, prefsize.height);\r
411           redrawneeded = false;\r
412         }\r
413 \r
414         g.drawImage(img, 0, 0, this);\r
415 \r
416         pdbAction = false;\r
417     }\r
418 \r
419     public void drawAll(Graphics g, int width, int height)\r
420     {\r
421       g.setColor(backgroundColour);\r
422       g.fillRect(0, 0, width, height);\r
423       drawScene(g);\r
424       drawLabels(g);\r
425     }\r
426 \r
427 \r
428     public void updateSeqColours()\r
429     {\r
430       if(pdbAction)\r
431       {\r
432         return;\r
433       }\r
434 \r
435      // System.out.println("update seq colours");\r
436       if(bysequence && pdb!=null)\r
437       {\r
438         for (int ii = 0; ii < pdb.chains.size(); ii++)\r
439         {\r
440           colourBySequence( (PDBChain) pdb.chains.elementAt(ii));\r
441         }\r
442       }\r
443 \r
444       redrawneeded=true;\r
445       repaint();\r
446     }\r
447 \r
448     int findTrueIndex(int pos)\r
449     {\r
450       // returns the alignment position for a residue\r
451       int j = sequence.getStart();\r
452       int i = 0;\r
453 \r
454       while ( (i < sequence.getLength()) && (j <= sequence.getEnd()) && (j <= pos+1))\r
455       {\r
456         if (!jalview.util.Comparison.isGap(sequence.getCharAt(i)))\r
457         {\r
458           j++;\r
459         }\r
460 \r
461         i++;\r
462       }\r
463 \r
464       if(i>1)\r
465          i--;\r
466 \r
467       if ( (j == sequence.getEnd()) && (j < pos))\r
468       {\r
469         return sequence.getEnd() + 1;\r
470       }\r
471       else\r
472       {\r
473         return i;\r
474       }\r
475     }\r
476 \r
477     // This method has been taken out of PDBChain to allow\r
478     // Applet and Application specific sequence renderers to be used\r
479     void colourBySequence(PDBChain chain)\r
480     {\r
481      // System.out.println("colour by seq");\r
482      boolean showFeatures = false;\r
483      if(seqcanvas.getViewport().getShowSequenceFeatures())\r
484      {\r
485        showFeatures = true;\r
486        if (fr == null)\r
487          fr = new jalview.gui.FeatureRenderer(seqcanvas.getViewport());\r
488 \r
489        fr.transferSettings( seqcanvas.getFeatureRenderer() );\r
490      }\r
491 \r
492       Bond tmp;\r
493       for (int i = 0; i < chain.bonds.size(); i++)\r
494       {\r
495         tmp = (Bond) chain.bonds.elementAt(i);\r
496 \r
497         if(chain!=mainchain)\r
498           continue;\r
499 \r
500         if ( (tmp.at1.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&\r
501             (tmp.at1.resNumber <= ( (chain.offset + chain.pdbend) - 1)))\r
502         {\r
503             int index = findTrueIndex(tmp.at1.alignmentMapping);\r
504                 //sequence.findIndex(tmp.at1.alignmentMapping);\r
505             if (index != -1)\r
506             {\r
507               tmp.startCol = seqcanvas.getSequenceRenderer().\r
508                   getResidueBoxColour( sequence, index);\r
509 \r
510               if(showFeatures)\r
511                 tmp.startCol = fr.findFeatureColour(tmp.startCol, sequence, index);\r
512 \r
513               if(tmp.startCol==null)\r
514                 tmp.startCol = Color.white;\r
515             }\r
516         }\r
517 \r
518         if ( (tmp.at2.resNumber >= ( (chain.offset + chain.pdbstart) - 1)) &&\r
519             (tmp.at2.resNumber <= ( (chain.pdbend + chain.offset) - 1)))\r
520         {\r
521 \r
522             int index =  findTrueIndex(tmp.at2.alignmentMapping);\r
523                 //sequence.findIndex( tmp.at2.alignmentMapping );\r
524             if (index != -1)\r
525             {\r
526               tmp.endCol = seqcanvas.getSequenceRenderer().\r
527                   getResidueBoxColour( sequence, index);\r
528 \r
529               if(showFeatures)\r
530                 tmp.endCol = fr.findFeatureColour(tmp.endCol, sequence, index);\r
531 \r
532               if(tmp.endCol==null)\r
533                 tmp.endCol = Color.white;\r
534             }\r
535         }\r
536       }\r
537     }\r
538 \r
539 \r
540     Zsort zsort;\r
541     public void drawScene(Graphics g)\r
542     {\r
543       if (zbuffer)\r
544       {\r
545         if (zsort == null)\r
546           zsort = new Zsort();\r
547 \r
548         zsort.Zsort(visiblebonds);\r
549       }\r
550 \r
551       Bond tmpBond = null;\r
552       for (int i = 0; i < visiblebonds.size(); i++)\r
553       {\r
554         tmpBond = (Bond) visiblebonds.elementAt(i);\r
555 \r
556         xstart = (int) ( ( (tmpBond.start[0] - centre[0]) * scale) +\r
557                         (getWidth() / 2));\r
558         ystart = (int) ( ( (tmpBond.start[1] - centre[1]) * scale) +\r
559                         (getHeight() / 2));\r
560 \r
561         xend = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +\r
562                       (getWidth() / 2));\r
563         yend = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +\r
564                       (getHeight() / 2));\r
565 \r
566         xmid = (xend + xstart) / 2;\r
567         ymid = (yend + ystart) / 2;\r
568         if (depthcue && !bymolecule)\r
569         {\r
570           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))\r
571           {\r
572 \r
573             g.setColor(tmpBond.startCol.darker().darker());\r
574             drawLine(g, xstart, ystart, xmid, ymid);\r
575             g.setColor(tmpBond.endCol.darker().darker());\r
576             drawLine(g, xmid, ymid, xend, yend);\r
577 \r
578           }\r
579           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))\r
580           {\r
581             g.setColor(tmpBond.startCol.darker());\r
582             drawLine(g, xstart, ystart, xmid, ymid);\r
583 \r
584             g.setColor(tmpBond.endCol.darker());\r
585             drawLine(g, xmid, ymid, xend, yend);\r
586           }\r
587           else\r
588           {\r
589             g.setColor(tmpBond.startCol);\r
590             drawLine(g, xstart, ystart, xmid, ymid);\r
591 \r
592             g.setColor(tmpBond.endCol);\r
593             drawLine(g, xmid, ymid, xend, yend);\r
594           }\r
595         }\r
596         else if (depthcue && bymolecule)\r
597         {\r
598           if (tmpBond.start[2] < (centre[2] - (maxwidth / 6)))\r
599           {\r
600             g.setColor(Color.green.darker().darker());\r
601             drawLine(g, xstart, ystart, xend, yend);\r
602           }\r
603           else if (tmpBond.start[2] < (centre[2] + (maxwidth / 6)))\r
604           {\r
605             g.setColor(Color.green.darker());\r
606             drawLine(g, xstart, ystart, xend, yend);\r
607           }\r
608           else\r
609           {\r
610             g.setColor(Color.green);\r
611             drawLine(g, xstart, ystart, xend, yend);\r
612           }\r
613         }\r
614         else if (!depthcue && !bymolecule)\r
615         {\r
616           g.setColor(tmpBond.startCol);\r
617           drawLine(g, xstart, ystart, xmid, ymid);\r
618           g.setColor(tmpBond.endCol);\r
619           drawLine(g, xmid, ymid, xend, yend);\r
620         }\r
621         else\r
622         {\r
623           drawLine(g, xstart, ystart, xend, yend);\r
624         }\r
625 \r
626         if (highlightBond1 != null && highlightBond1 == tmpBond)\r
627         {\r
628           g.setColor(tmpBond.endCol.brighter().brighter().brighter().brighter());\r
629           drawLine(g, xmid, ymid, xend, yend);\r
630         }\r
631 \r
632         if (highlightBond2 != null && highlightBond2 == tmpBond)\r
633         {\r
634           g.setColor(tmpBond.startCol.brighter().brighter().brighter().brighter());\r
635           drawLine(g, xstart, ystart, xmid, ymid);\r
636         }\r
637 \r
638       }\r
639 \r
640 \r
641     }\r
642 \r
643     public void drawLine(Graphics g, int x1, int y1, int x2, int y2) {\r
644         if (!wire) {\r
645             if (((float) Math.abs(y2 - y1) / (float) Math.abs(x2 - x1)) < 0.5) {\r
646                 g.drawLine(x1, y1, x2, y2);\r
647                 g.drawLine(x1 + 1, y1 + 1, x2 + 1, y2 + 1);\r
648                 g.drawLine(x1, y1 - 1, x2, y2 - 1);\r
649             } else {\r
650                 g.setColor(g.getColor().brighter());\r
651                 g.drawLine(x1, y1, x2, y2);\r
652                 g.drawLine(x1 + 1, y1, x2 + 1, y2);\r
653                 g.drawLine(x1 - 1, y1, x2 - 1, y2);\r
654             }\r
655         } else {\r
656             g.drawLine(x1, y1, x2, y2);\r
657         }\r
658     }\r
659 \r
660     public Dimension minimumsize() {\r
661         return prefsize;\r
662     }\r
663 \r
664     public Dimension preferredsize() {\r
665         return prefsize;\r
666     }\r
667 \r
668     public void keyPressed(KeyEvent evt)\r
669     {\r
670       if (evt.getKeyCode() == KeyEvent.VK_UP)\r
671       {\r
672         scale = (float) (scale * 1.1);\r
673         redrawneeded = true;\r
674         repaint();\r
675       }\r
676       else if (evt.getKeyCode() == KeyEvent.VK_DOWN)\r
677       {\r
678         scale = (float) (scale * 0.9);\r
679         redrawneeded = true;\r
680         repaint();\r
681       }\r
682     }\r
683 \r
684     public void mousePressed(MouseEvent e)\r
685     {\r
686         pdbAction = true;\r
687         Atom fatom = findAtom(e.getX(), e.getY());\r
688         if(fatom!=null)\r
689         {\r
690           fatom.isSelected = !fatom.isSelected;\r
691 \r
692           redrawneeded = true;\r
693           repaint();\r
694           if (foundchain != -1)\r
695           {\r
696             PDBChain chain = (PDBChain) pdb.chains.elementAt(foundchain);\r
697             if (chain == mainchain)\r
698             {\r
699               if (fatom.alignmentMapping != -1)\r
700               {\r
701                 if (highlightRes == null)\r
702                   highlightRes = new Vector();\r
703 \r
704                 if (highlightRes.contains(fatom.alignmentMapping+""))\r
705                   highlightRes.remove(fatom.alignmentMapping + "");\r
706                 else\r
707                   highlightRes.add(fatom.alignmentMapping + "");\r
708               }\r
709             }\r
710           }\r
711 \r
712         }\r
713         mx = e.getX();\r
714         my = e.getY();\r
715         omx = mx;\r
716         omy = my;\r
717         dragging = false;\r
718     }\r
719 \r
720     public void mouseMoved(MouseEvent e)\r
721     {\r
722       pdbAction = true;\r
723       if(highlightBond1!=null)\r
724       {\r
725         highlightBond1.at2.isSelected = false;\r
726         highlightBond2.at1.isSelected = false;\r
727         highlightBond1 = null;\r
728         highlightBond2 = null;\r
729       }\r
730 \r
731         Atom fatom = findAtom(e.getX(), e.getY());\r
732 \r
733         PDBChain chain = null;\r
734         if(foundchain!=-1)\r
735         {\r
736           chain = (PDBChain) pdb.chains.elementAt(foundchain);\r
737           if(chain == mainchain)\r
738           {\r
739             highlightSeqcanvas( fatom.alignmentMapping );\r
740           }\r
741         }\r
742 \r
743         if (fatom != null)\r
744         {\r
745             this.setToolTipText(chain.id+":"+ fatom.resNumber+" "+ fatom.resName);\r
746         } else\r
747         {\r
748             highlightSeqcanvas( -1);\r
749             this.setToolTipText(null);\r
750         }\r
751     }\r
752 \r
753 \r
754     void highlightSeqcanvas(int pos)\r
755     {\r
756       SearchResults searchResults = new SearchResults();\r
757       if(highlightRes!=null)\r
758       {\r
759         for (int i = 0; i < highlightRes.size(); i++)\r
760         {\r
761           int a = Integer.parseInt(highlightRes.elementAt(\r
762               i).toString())+1;\r
763 \r
764           searchResults.addResult(sequence, a, a);\r
765         }\r
766       }\r
767 \r
768       if(pos!=-1)\r
769       {\r
770         searchResults.addResult(sequence, pos+1, pos+1);\r
771       }\r
772 \r
773       seqcanvas.highlightSearchResults(searchResults);\r
774     }\r
775 \r
776 \r
777     public void mouseClicked(MouseEvent e)  { }\r
778 \r
779     public void mouseEntered(MouseEvent e) {  }\r
780 \r
781     public void mouseExited(MouseEvent e) { }\r
782 \r
783     public void mouseDragged(MouseEvent evt)\r
784     {\r
785         int x = evt.getX();\r
786         int y = evt.getY();\r
787         mx = x;\r
788         my = y;\r
789 \r
790 \r
791         MCMatrix objmat = new MCMatrix(3, 3);\r
792         objmat.setIdentity();\r
793 \r
794         if ((evt.getModifiers() & Event.META_MASK) != 0) {\r
795             objmat.rotatez((float) ((mx - omx)));\r
796         } else {\r
797             objmat.rotatex((float) ((my - omy)));\r
798             objmat.rotatey((float) ((omx - mx)));\r
799         }\r
800 \r
801         //Alter the bonds\r
802         for (int ii = 0; ii < pdb.chains.size(); ii++) {\r
803             Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
804 \r
805             for (int i = 0; i < bonds.size(); i++) {\r
806                 Bond tmpBond = (Bond) bonds.elementAt(i);\r
807 \r
808                 //Translate the bond so the centre is 0,0,0\r
809                 tmpBond.translate(-centre[0], -centre[1], -centre[2]);\r
810 \r
811                 //Now apply the rotation matrix\r
812                 tmpBond.start = objmat.vectorMultiply(tmpBond.start);\r
813                 tmpBond.end = objmat.vectorMultiply(tmpBond.end);\r
814 \r
815                 //Now translate back again\r
816                 tmpBond.translate(centre[0], centre[1], centre[2]);\r
817             }\r
818         }\r
819 \r
820         objmat = null;\r
821 \r
822         omx = mx;\r
823         omy = my;\r
824 \r
825         dragging = true;\r
826 \r
827         redrawneeded = true;\r
828 \r
829         repaint();\r
830     }\r
831 \r
832     public void mouseReleased(MouseEvent evt)\r
833     {\r
834         dragging = false;\r
835         return;\r
836     }\r
837 \r
838     void drawLabels(Graphics g) {\r
839 \r
840         for (int ii = 0; ii < pdb.chains.size(); ii++)\r
841         {\r
842             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);\r
843 \r
844             if (chain.isVisible)\r
845             {\r
846               Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
847 \r
848               for (int i = 0; i < bonds.size(); i++)\r
849               {\r
850                   Bond tmpBond = (Bond) bonds.elementAt(i);\r
851 \r
852                   if (tmpBond.at1.isSelected)\r
853                   {\r
854                       labelAtom(g, tmpBond, 1);\r
855                   }\r
856 \r
857                   if (tmpBond.at2.isSelected)\r
858                   {\r
859 \r
860                       labelAtom(g, tmpBond, 2);\r
861                   }\r
862                 }\r
863             }\r
864         }\r
865     }\r
866 \r
867     public void labelAtom(Graphics g, Bond b, int n) {\r
868         g.setFont(font);\r
869         g.setColor(Color.red);\r
870         if (n == 1)\r
871         {\r
872             int xstart = (int) (((b.start[0] - centre[0]) * scale) +\r
873                 (getWidth() / 2));\r
874             int ystart = (int) (((b.start[1] - centre[1]) * scale) +\r
875                 (getHeight() / 2));\r
876 \r
877             g.drawString(b.at1.resName + "-" + b.at1.resNumber, xstart, ystart);\r
878         }\r
879 \r
880         if (n == 2) {\r
881             int xstart = (int) (((b.end[0] - centre[0]) * scale) +\r
882                 (getWidth() / 2));\r
883             int ystart = (int) (((b.end[1] - centre[1]) * scale) +\r
884                 (getHeight() / 2));\r
885 \r
886             g.drawString(b.at2.resName + "-" + b.at2.resNumber, xstart, ystart);\r
887         }\r
888     }\r
889 \r
890     int foundchain = -1;\r
891     public Atom findAtom(int x, int y) {\r
892         Atom fatom = null;\r
893 \r
894         foundchain = -1;\r
895 \r
896         for (int ii = 0; ii < pdb.chains.size(); ii++)\r
897         {\r
898             PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);\r
899             int truex;\r
900             Bond tmpBond=null;\r
901 \r
902             if (chain.isVisible)\r
903             {\r
904                 Vector bonds = ((PDBChain) pdb.chains.elementAt(ii)).bonds;\r
905 \r
906                 for (int i = 0; i < bonds.size(); i++)\r
907                 {\r
908                     tmpBond = (Bond) bonds.elementAt(i);\r
909 \r
910                     truex = (int) (((tmpBond.start[0] - centre[0]) * scale) +\r
911                         (getWidth() / 2));\r
912 \r
913                     if (Math.abs(truex - x) <= 2)\r
914                     {\r
915                         int truey = (int) (((tmpBond.start[1] - centre[1]) * scale) +\r
916                             (getHeight() / 2));\r
917 \r
918                         if (Math.abs(truey - y) <= 2)\r
919                         {\r
920                             fatom = tmpBond.at1;\r
921                             foundchain = ii;\r
922                             break;\r
923                         }\r
924                     }\r
925                 }\r
926 \r
927                 // Still here? Maybe its the last bond\r
928 \r
929                 truex = (int) ( ( (tmpBond.end[0] - centre[0]) * scale) +\r
930                                (getWidth() / 2));\r
931 \r
932                 if (Math.abs(truex - x) <= 2)\r
933                 {\r
934                   int truey = (int) ( ( (tmpBond.end[1] - centre[1]) * scale) +\r
935                                      (getHeight() / 2));\r
936 \r
937                   if (Math.abs(truey - y) <= 2)\r
938                   {\r
939                     fatom = tmpBond.at2;\r
940                     foundchain = ii;\r
941                     break;\r
942                   }\r
943                 }\r
944 \r
945             }\r
946 \r
947             if (fatom != null) //)&& chain.ds != null)\r
948              {\r
949                 chain = (PDBChain) pdb.chains.elementAt(foundchain);\r
950             }\r
951         }\r
952 \r
953         return fatom;\r
954     }\r
955 \r
956    Bond highlightBond1, highlightBond2;\r
957    public void highlightRes(int ii)\r
958   {\r
959     if( !seqColoursReady )\r
960       return;\r
961 \r
962     if (highlightRes != null\r
963         && highlightRes.contains((ii-1) + ""))\r
964     {\r
965       return;\r
966     }\r
967 \r
968     int index = -1;\r
969     Bond tmpBond;\r
970     for(index=0; index<mainchain.bonds.size(); index++)\r
971     {\r
972       tmpBond = (Bond) mainchain.bonds.elementAt(index);\r
973       if (tmpBond.at1.alignmentMapping == ii - 1)\r
974       {\r
975         if (highlightBond1 != null)\r
976           highlightBond1.at2.isSelected = false;\r
977 \r
978         if (highlightBond2 != null)\r
979           highlightBond2.at1.isSelected = false;\r
980 \r
981         highlightBond1 = null;\r
982         highlightBond2 = null;\r
983 \r
984         if (index > 0)\r
985         {\r
986           highlightBond1 = (Bond) mainchain.bonds.elementAt(index - 1);\r
987           highlightBond1.at2.isSelected = true;\r
988         }\r
989 \r
990         if (index != mainchain.bonds.size())\r
991         {\r
992           highlightBond2 = (Bond) mainchain.bonds.elementAt(index);\r
993           highlightBond2.at1.isSelected = true;\r
994         }\r
995 \r
996         break;\r
997       }\r
998     }\r
999 \r
1000     redrawneeded = true;\r
1001     repaint();\r
1002   }\r
1003 \r
1004     public void setAllchainsVisible(boolean b)\r
1005     {\r
1006       for (int ii = 0; ii < pdb.chains.size(); ii++)\r
1007       {\r
1008         PDBChain chain = (PDBChain) pdb.chains.elementAt(ii);\r
1009         chain.isVisible = b;\r
1010       }\r
1011       mainchain.isVisible = true;\r
1012       findCentre();\r
1013       setupBonds();\r
1014     }\r
1015 }\r