Modified for wrappingAlignment
[jalview.git] / src / jalview / gui / SeqPanel.java
1 package jalview.gui;\r
2 \r
3 import java.awt.*;\r
4 import java.awt.event.*;\r
5 import jalview.datamodel.*;\r
6 import javax.swing.*;\r
7 import jalview.schemes.*;\r
8 import jalview.analysis.*;\r
9 \r
10 \r
11 public class SeqPanel extends JPanel\r
12 {\r
13 \r
14   public    SeqCanvas         seqCanvas;\r
15   public    AlignmentPanel    ap;\r
16 \r
17   protected int startres;\r
18   protected int lastres;\r
19   protected int endres;\r
20 \r
21   protected int startseq;\r
22   protected int padseq;\r
23 \r
24   protected AlignViewport av;\r
25 \r
26   // if character is inserted or deleted, we will need to recalculate the conservation\r
27   int seqEditOccurred = -1;\r
28 \r
29   public SeqPanel(AlignViewport avp, AlignmentPanel p) {\r
30     this.av         = avp;\r
31 \r
32     seqCanvas  = new SeqCanvas(avp);\r
33     setLayout(new BorderLayout());\r
34     add(seqCanvas, BorderLayout.CENTER);\r
35 \r
36     ap = p;\r
37 \r
38     addMouseMotionListener( new MouseMotionAdapter()\r
39     {\r
40       public void mouseMoved(MouseEvent evt)\r
41       {\r
42        if(av.getWrapAlignment())\r
43          return;\r
44         doMouseMoved(evt);    }\r
45 \r
46       public void mouseDragged(MouseEvent evt)\r
47       {\r
48         if(av.getWrapAlignment())\r
49          return;\r
50         if(evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())\r
51           doMouseDragged(evt);\r
52         else\r
53           doMouseDraggedDefineMode(evt);\r
54       }\r
55     });\r
56 \r
57     addMouseListener( new MouseAdapter()\r
58     {\r
59       public void mouseReleased(MouseEvent evt)\r
60       {\r
61         if(av.getWrapAlignment())\r
62          return;\r
63         if(evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())\r
64           doMouseReleased(evt);\r
65         else\r
66           doMouseReleasedDefineMode(evt);\r
67       }\r
68       public void mousePressed(MouseEvent evt)\r
69       {\r
70         if(av.getWrapAlignment())\r
71          return;\r
72         if(evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())\r
73           doMousePressed(evt);\r
74         else\r
75           doMousePressedDefineMode(evt);\r
76       }\r
77 \r
78     });\r
79     repaint();\r
80   }\r
81 \r
82 \r
83   public void doMouseReleased(MouseEvent evt) {\r
84 \r
85     int x = evt.getX();\r
86     int res = x/av.getCharWidth() + av.getStartRes();\r
87 \r
88     endres = res;\r
89 \r
90     startseq = -1;\r
91     startres = -1;\r
92     lastres  = -1;\r
93     if(seqEditOccurred>-1)\r
94       updateConservation(seqEditOccurred);\r
95 \r
96     seqEditOccurred = -1;\r
97 \r
98     ap.RefreshPanels();\r
99     repaint();\r
100 \r
101   }\r
102 \r
103   public void doMousePressed(MouseEvent evt) {\r
104     ap.alignFrame.addHistoryItem("sequence edit");\r
105     int seq;\r
106     int res;\r
107 \r
108     int x = evt.getX();\r
109     int y = evt.getY();\r
110 \r
111     res = x/av.getCharWidth() + av.getStartRes();\r
112     seq = y/av.getCharHeight() + av.getStartSeq();\r
113 \r
114     if (seq < av.getAlignment().getHeight() &&\r
115         res < av.getAlignment().getSequenceAt(seq).getLength())\r
116     {\r
117       //char resstr = align.getSequenceAt(seq).getSequence().charAt(res);\r
118       // Find the residue's position in the sequence (res is the position\r
119       // in the alignment\r
120 \r
121       startseq = seq;\r
122 \r
123       if (startseq == (av.getAlignment().getHeight() - 1))\r
124         padseq = 1;\r
125       else\r
126         padseq = 1;\r
127 \r
128       startres = res;\r
129       lastres = res;\r
130 \r
131     }\r
132     else\r
133     {\r
134       startseq = -1;\r
135       startres = -1;\r
136       lastres = -1;\r
137     }\r
138 \r
139     return;\r
140   }\r
141 \r
142   public void doMouseMoved(MouseEvent evt)\r
143   {\r
144     int res=0, seq=0;\r
145     int x = evt.getX();\r
146     int y = evt.getY();\r
147     if(av.wrapAlignment)\r
148     {\r
149       y -= 2*av.charHeight;\r
150       int chunkHeight = (av.getAlignment().getHeight()+2)*av.charHeight;\r
151 \r
152 \r
153       res =   (int)((y/chunkHeight)*(getWidth()/av.charWidth)) +  x/av.getCharWidth() + av.getStartRes();\r
154 \r
155       y %= chunkHeight;\r
156       seq =     y / av.getCharHeight() + av.getStartSeq();\r
157 \r
158       //   chunkHeight =  (da.getHeight() + 2)*charHeight;\r
159       //  startx += chunkWidth;\r
160     }\r
161     else\r
162     {\r
163       res = x / av.getCharWidth()  + av.getStartRes();\r
164       seq = y / av.getCharHeight() + av.getStartSeq();\r
165     }\r
166 \r
167 \r
168     if(seq>=av.getAlignment().getHeight())\r
169       return;\r
170 \r
171     Object obj = ResidueProperties.aa2Triplet.get( av.getAlignment().getSequenceAt(seq).getCharAt(res)+"" ) ;\r
172     String aa = "";\r
173     if(obj!=null)\r
174          aa = obj.toString();\r
175 \r
176     StringBuffer text = new StringBuffer("Sequence " +(seq+1)+" ID: "+av.getAlignment().getSequenceAt(seq).getName());\r
177     if(aa!="")\r
178       text.append("  Residue: "+aa+" ("+  av.getAlignment().getSequenceAt(seq).findPosition(res)+")");\r
179 \r
180     ap.alignFrame.statusBar.setText(text.toString());\r
181 \r
182   }\r
183 \r
184   public void doMouseDragged(MouseEvent evt) {\r
185     // If we're dragging we're editing\r
186 \r
187     int x = evt.getX();\r
188 \r
189     int res = x/av.getCharWidth() + av.getStartRes();\r
190     if (res < 0)\r
191       res = 0;\r
192 \r
193     if (res != lastres)\r
194     {\r
195         // Group editing\r
196         if (evt.isAltDown() || evt.isControlDown())\r
197         {\r
198           SequenceGroup sg = av.getAlignment().findGroup(startseq);\r
199           if (sg != null)\r
200           {\r
201             boolean deleteAllowed = false;\r
202             if (res < av.getAlignment().getWidth() && res < lastres)\r
203             {\r
204               /// Are we able to delete?\r
205               boolean allGaps = true;\r
206               for (int i = 0; i < sg.getSize(); i++)\r
207               {\r
208                 SequenceI s = sg.getSequenceAt(i);\r
209                 for (int j = lastres-1; j >= res && allGaps; j--)\r
210                 {\r
211                     if (!jalview.util.Comparison.isGap(s.getSequence().charAt(j)))\r
212                     {\r
213                       res = j + 1;\r
214                       allGaps = false;\r
215                     }\r
216                 }\r
217 \r
218                 if(!deleteAllowed && allGaps)\r
219                   deleteAllowed = true;\r
220               }\r
221             }\r
222 \r
223             // drag to right\r
224             if (res < av.getAlignment().getWidth() && res > lastres)\r
225                 sg.setEndRes(sg.getEndRes() + 1);\r
226 \r
227             // drag to left\r
228             else if (deleteAllowed && res < av.getAlignment().getWidth() &&\r
229                      res < lastres)\r
230                 sg.setEndRes(sg.getEndRes() - 1);\r
231 \r
232 \r
233 \r
234 \r
235             for (int i = 0; i < sg.getSize(); i++)\r
236             {\r
237               SequenceI s = sg.getSequenceAt(i);\r
238               int k = av.alignment.findIndex(s);\r
239 \r
240               // drag to right\r
241               if (res < av.getAlignment().getWidth() && res > lastres)\r
242                 for (int j = lastres; j < res; j++)\r
243                   insertChar(j, k);\r
244 \r
245               // drag to left\r
246               else if (deleteAllowed && res < av.getAlignment().getWidth() && res < lastres)\r
247               {\r
248                 for (int j = res; j < lastres; j++)\r
249                 {\r
250                   deleteChar(j, k);\r
251                   startres = res;\r
252                 }\r
253               }\r
254             }\r
255           }\r
256         }\r
257         else /////Editing a single sequence///////////\r
258         {\r
259           if (res < av.getAlignment().getWidth() && res > lastres)\r
260           {\r
261             // dragging to the right\r
262             for (int j = lastres; j < res; j++)\r
263               insertChar(j, startseq);\r
264           }\r
265           else if (res < av.getAlignment().getWidth() && res < lastres)\r
266           {\r
267             // dragging to the left\r
268             for (int j = res; j < lastres; j++)\r
269             {\r
270               deleteChar(j, startseq);\r
271               startres = res;\r
272             }\r
273           }\r
274 \r
275         }\r
276 \r
277     }\r
278 \r
279     lastres = res;\r
280     repaint();\r
281   }\r
282 \r
283   public void drawChars(int seqstart, int seqend, int start) {\r
284     seqCanvas.drawPanel(seqCanvas.gg, start,av.getEndRes(),seqstart,seqend,av.getStartRes(),av.getStartSeq(),0);\r
285     repaint();\r
286   }\r
287 \r
288   public void insertChar(int j, int seq)\r
289   {\r
290     av.alignment.getSequenceAt(seq).insertCharAt(j, av.getGapCharacter());\r
291     seqEditOccurred=seq;\r
292   }\r
293 \r
294   public void deleteChar(int j, int seq)\r
295   {\r
296 \r
297     if ( jalview.util.Comparison.isGap( av.alignment.getSequenceAt(seq).getSequence().charAt(j)))\r
298         av.alignment.getSequenceAt(seq).deleteCharAt(j);\r
299 \r
300     av.alignment.getWidth();\r
301     repaint();\r
302     seqEditOccurred=seq;\r
303   }\r
304 \r
305 \r
306   void updateConservation(int i)\r
307   {\r
308   /*  Alignment al = (Alignment) av.getAlignment();\r
309     SequenceGroup sg = av.alignment.findGroup( al.getSequenceAt(i));\r
310     if(sg==null || !(sg.cs instanceof ConservationColourScheme))\r
311       return;\r
312 \r
313     Conservation c = sg.getConservation();\r
314 \r
315     c = new Conservation("All", al.cons,\r
316                          ResidueProperties.propHash, 3, sg.sequences, 0,\r
317                          al.getWidth());\r
318     c.calculate();\r
319     c.verdict(false, 100);\r
320     sg.setConservation(c);\r
321     ConservationColourScheme ccs = (ConservationColourScheme)sg.cs;\r
322     ccs.conserve = c;*/\r
323   }\r
324 \r
325 //////////////////////////////////////////\r
326 /////Everything below this is for defining the boundary of the rubberband\r
327 //////////////////////////////////////////\r
328   int oldSeq = -1;\r
329   public void doMousePressedDefineMode(MouseEvent evt)\r
330   {\r
331     int res = evt.getX()/av.getCharWidth() + av.getStartRes();\r
332     int seq = evt.getY()/av.getCharHeight() + av.getStartSeq();\r
333     oldSeq = seq;\r
334 \r
335     stretchGroup = av.getRubberbandGroup();\r
336 \r
337     if(stretchGroup == null)\r
338      {\r
339        stretchGroup = av.alignment.findGroup( (Sequence) av.getAlignment().\r
340                                              getSequenceAt(seq));\r
341        av.setRubberbandGroup( stretchGroup );\r
342      }\r
343 \r
344     else if(!stretchGroup.sequences.contains((Sequence)av.getAlignment().getSequenceAt(seq))\r
345             || stretchGroup.getStartRes()>res\r
346             || stretchGroup.getEndRes()<res)\r
347      {\r
348        stretchGroup = null;\r
349 \r
350        SequenceGroup[] allGroups = av.alignment.findAllGroups( (Sequence) av.\r
351            getAlignment().\r
352            getSequenceAt(seq));\r
353 \r
354        if (allGroups != null)\r
355          for (int i = 0; i < allGroups.length; i++)\r
356            if (allGroups[i].getStartRes() <= res &&\r
357                allGroups[i].getEndRes() >= res)\r
358            {\r
359              stretchGroup = allGroups[i];\r
360              av.setRubberbandGroup(stretchGroup);\r
361              break;\r
362            }\r
363      }\r
364 \r
365     if(stretchGroup==null)\r
366     {\r
367       // define a new group here\r
368       SequenceGroup sg = new SequenceGroup();\r
369       sg.setStartRes(res);\r
370       sg.setEndRes(res);\r
371       sg.addSequence( (Sequence)av.getAlignment().getSequenceAt(seq) );\r
372       av.setRubberbandGroup( sg );\r
373       stretchGroup = sg;\r
374 \r
375       if(av.getConservationSelected())\r
376         Desktop.setConservationSliderSource(ap, av.getGlobalColourScheme(), "Background");\r
377       else if(av.getGlobalColourScheme()!=null && av.getGlobalColourScheme().canThreshold())\r
378       {\r
379         ResidueColourScheme rcs = (ResidueColourScheme) av.getGlobalColourScheme();\r
380         int threshold = rcs.getThreshold();\r
381         if (threshold > 0)\r
382           Desktop.setPIDSliderSource(ap, av.getGlobalColourScheme(), "Background");\r
383       }\r
384 \r
385     }\r
386     else if( javax.swing.SwingUtilities.isRightMouseButton(evt))\r
387     {\r
388         jalview.gui.PopupMenu pop = new jalview.gui.PopupMenu( ap , null);\r
389         pop.show(this, evt.getX(), evt.getY());\r
390 \r
391     // edit the properties of existing group\r
392     }\r
393 \r
394     if(stretchGroup!=null && stretchGroup.getEndRes()==res)\r
395       // Edit end res position of selected group\r
396       changeEndRes = true;\r
397 \r
398    else if(stretchGroup!=null && stretchGroup.getStartRes()==res)\r
399       // Edit end res position of selected group\r
400       changeStartRes = true;\r
401 \r
402 \r
403     seqCanvas.paintFlag = true;\r
404     repaint();\r
405 \r
406   }\r
407 \r
408   boolean changeEndSeq = false;\r
409   boolean changeStartSeq = false;\r
410   boolean changeEndRes = false;\r
411   boolean changeStartRes = false;\r
412   SequenceGroup stretchGroup = null;\r
413 \r
414   public void doMouseReleasedDefineMode(MouseEvent evt)\r
415   {\r
416 \r
417     if(stretchGroup.cs instanceof ClustalxColourScheme)\r
418     {\r
419       stretchGroup.cs = new ClustalxColourScheme(stretchGroup.sequences, av.alignment.getWidth());\r
420       seqCanvas.paintFlag = true;\r
421       repaint();\r
422     }\r
423 \r
424     else if(stretchGroup.cs instanceof ConservationColourScheme)\r
425     {\r
426       ConservationColourScheme ccs = (ConservationColourScheme)stretchGroup.cs;\r
427 \r
428       Conservation c = new Conservation("Group",\r
429                                         ResidueProperties.propHash, 3, stretchGroup.sequences, 0,\r
430                                         av.alignment.getWidth() );\r
431 \r
432        c.calculate();\r
433        c.verdict(false, 100);\r
434        ccs = new ConservationColourScheme(c, ccs.cs);\r
435 \r
436        stretchGroup.cs = ccs;\r
437 \r
438 \r
439        Desktop.setConservationSliderSource(ap, stretchGroup.cs, stretchGroup.getName()) ;\r
440 \r
441        seqCanvas.paintFlag = true;\r
442        repaint();\r
443     }\r
444     else\r
445     {\r
446       if(stretchGroup.cs !=null && stretchGroup.cs.canThreshold())\r
447       {\r
448         ResidueColourScheme rcs =  (ResidueColourScheme) stretchGroup.cs;\r
449         int threshold = rcs.getThreshold();\r
450         if(threshold>0)\r
451           Desktop.setPIDSliderSource(ap, stretchGroup.cs, stretchGroup.getName());\r
452       }\r
453 \r
454     }\r
455 \r
456 \r
457     changeEndRes = false;\r
458     changeStartRes = false;\r
459     stretchGroup = null;\r
460   }\r
461 \r
462 \r
463   boolean remove = false;\r
464   public void doMouseDraggedDefineMode(MouseEvent evt)\r
465   {\r
466     int res = evt.getX()/av.getCharWidth() + av.getStartRes();\r
467     int y = evt.getY()/av.getCharHeight() + av.getStartSeq();\r
468 \r
469 \r
470     if(stretchGroup.getEndRes()==res)\r
471       // Edit end res position of selected group\r
472       changeEndRes = true;\r
473 \r
474     else if(stretchGroup.getStartRes()==res)\r
475       // Edit start res position of selected group\r
476       changeStartRes = true;\r
477 \r
478 \r
479     if(res<av.getStartRes())\r
480       res = av.getStartRes();\r
481     else if(res>av.getEndRes())\r
482       res = av.getEndRes();\r
483 \r
484     if(changeEndRes)\r
485     {\r
486       if(res>stretchGroup.getStartRes()-1)\r
487         stretchGroup.setEndRes( res );\r
488     }\r
489     else if(changeStartRes)\r
490     {\r
491       if(res<stretchGroup.getEndRes()+1)\r
492         stretchGroup.setStartRes( res );\r
493     }\r
494 \r
495 \r
496     int dragDirection = 0;\r
497     if (y > oldSeq)\r
498       dragDirection = 1;\r
499     else if (y < oldSeq)\r
500       dragDirection = -1;\r
501 \r
502     while (y != oldSeq)\r
503     {\r
504       // This routine ensures we don't skip any sequences, as the\r
505       // selection is quite slow.\r
506       Sequence seq = (Sequence) av.getAlignment().getSequenceAt(oldSeq);\r
507 \r
508       oldSeq += dragDirection;\r
509       Sequence nextSeq = (Sequence) av.getAlignment().getSequenceAt(oldSeq);\r
510 \r
511       if (stretchGroup.sequences.contains(nextSeq))\r
512       {\r
513         stretchGroup.deleteSequence(seq);\r
514         stretchGroup.deleteSequence(nextSeq);\r
515       }\r
516       else\r
517       {\r
518         stretchGroup.addSequence(seq);\r
519         stretchGroup.addSequence(nextSeq);\r
520       }\r
521     }\r
522     oldSeq = y;\r
523 \r
524     seqCanvas.paintFlag = true;\r
525     repaint();\r
526   }\r
527 \r
528 \r
529 }\r
530 \r
531 \r
532 \r
533 \r