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