after merge
[jalview.git] / src / jalview / appletgui / SeqPanel.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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.util.*;\r
23 \r
24 import java.awt.*;\r
25 import java.awt.event.*;\r
26 \r
27 import jalview.datamodel.*;\r
28 import jalview.schemes.*;\r
29 \r
30 public class SeqPanel\r
31     extends Panel\r
32 {\r
33 \r
34   public SeqCanvas seqCanvas;\r
35   public AlignmentPanel ap;\r
36 \r
37   protected int lastres;\r
38   protected int startseq;\r
39   int startEdit = -1;\r
40   int endEdit = -1;\r
41 \r
42   protected AlignViewport av;\r
43 \r
44   // if character is inserted or deleted, we will need to recalculate the conservation\r
45   int seqEditOccurred = -1;\r
46 \r
47   ScrollThread scrollThread = null;\r
48   boolean mouseDragging = false;\r
49 \r
50   boolean editingSeqs = false;\r
51   boolean groupEditing = false;\r
52 \r
53   public SeqPanel(AlignViewport avp, AlignmentPanel p)\r
54   {\r
55     this.av = avp;\r
56 \r
57     seqCanvas = new SeqCanvas(avp);\r
58     setLayout(new BorderLayout());\r
59     add(seqCanvas);\r
60 \r
61     ap = p;\r
62 \r
63     seqCanvas.addMouseMotionListener(new MouseMotionAdapter()\r
64     {\r
65       public void mouseMoved(MouseEvent evt)\r
66       {\r
67         doMouseMoved(evt);\r
68       }\r
69 \r
70       public void mouseDragged(MouseEvent evt)\r
71       {\r
72         if (editingSeqs)\r
73         {\r
74           doMouseDragged(evt);\r
75         }\r
76         else\r
77         {\r
78           doMouseDraggedDefineMode(evt);\r
79         }\r
80       }\r
81     });\r
82 \r
83     seqCanvas.addMouseListener(new MouseAdapter()\r
84     {\r
85       public void mouseReleased(MouseEvent evt)\r
86       {\r
87         if (editingSeqs)\r
88         {\r
89           doMouseReleased(evt);\r
90         }\r
91         else\r
92         {\r
93           doMouseReleasedDefineMode(evt);\r
94         }\r
95 \r
96       }\r
97 \r
98       public void mousePressed(MouseEvent evt)\r
99       {\r
100         if (evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())\r
101         {\r
102           if (evt.isAltDown() || evt.isControlDown())\r
103           {\r
104             groupEditing = true;\r
105           }\r
106 \r
107           editingSeqs = true;\r
108           doMousePressed(evt);\r
109         }\r
110         else\r
111         {\r
112           doMousePressedDefineMode(evt);\r
113         }\r
114       }\r
115 \r
116       public void mouseExited(MouseEvent evt)\r
117       {\r
118         if (editingSeqs)\r
119         {\r
120           return;\r
121         }\r
122         doMouseExitedDefineMode(evt);\r
123 \r
124       }\r
125 \r
126       public void mouseEntered(MouseEvent evt)\r
127       {\r
128         if (editingSeqs)\r
129         {\r
130           return;\r
131         }\r
132         doMouseEnteredDefineMode(evt);\r
133       }\r
134 \r
135     });\r
136     seqCanvas.repaint();\r
137   }\r
138 \r
139   public void doMouseReleased(MouseEvent evt)\r
140   {\r
141 \r
142     if (seqEditOccurred > -1)\r
143     {\r
144       editOccurred(seqEditOccurred);\r
145     }\r
146 \r
147     startseq = -1;\r
148     lastres = -1;\r
149     seqEditOccurred = -1;\r
150     editingSeqs = false;\r
151     groupEditing = false;\r
152     ap.repaint();\r
153   }\r
154 \r
155   int startWrapBlock=-1;\r
156   int wrappedBlock=-1;\r
157   int findRes(MouseEvent evt)\r
158  {\r
159    int res = 0;\r
160    int x = evt.getX();\r
161 \r
162   if (av.wrapAlignment)\r
163   {\r
164 \r
165     int hgap = av.charHeight;\r
166     if (av.scaleAboveWrapped)\r
167       hgap += av.charHeight;\r
168 \r
169     int cHeight = av.getAlignment().getHeight() * av.charHeight\r
170         + hgap + seqCanvas.getAnnotationHeight();\r
171 \r
172       int y = evt.getY();\r
173       y -= hgap;\r
174       x -= seqCanvas.LABEL_WEST;\r
175 \r
176 \r
177       int cwidth = seqCanvas.getWrappedCanvasWidth(getSize().width);\r
178 \r
179       wrappedBlock = y / cHeight;\r
180       wrappedBlock += av.getStartRes() / cwidth;\r
181 \r
182       res = wrappedBlock * cwidth + x / av.getCharWidth();\r
183 \r
184   }\r
185   else\r
186   {\r
187       res = (x / av.getCharWidth()) + av.getStartRes();\r
188   }\r
189 \r
190   return res;\r
191 \r
192  }\r
193 \r
194  int findSeq(MouseEvent evt)\r
195  {\r
196 \r
197    int seq = 0;\r
198    int y = evt.getY();\r
199 \r
200    if (av.wrapAlignment)\r
201    {\r
202      int hgap = av.charHeight;\r
203      if (av.scaleAboveWrapped)\r
204        hgap += av.charHeight;\r
205 \r
206      int cHeight = av.getAlignment().getHeight() * av.charHeight\r
207          + hgap + seqCanvas.getAnnotationHeight();\r
208 \r
209        y -= hgap;\r
210 \r
211      seq = ( (y % cHeight) / av.getCharHeight());\r
212    }\r
213    else\r
214    {\r
215      seq = (y / av.getCharHeight()) + av.getStartSeq();\r
216    }\r
217 \r
218    return seq;\r
219  }\r
220 \r
221 \r
222   public void doMousePressed(MouseEvent evt)\r
223   {\r
224     ap.alignFrame.addHistoryItem(new HistoryItem(\r
225         "Edit Sequence", av.alignment, HistoryItem.EDIT));\r
226 \r
227     int seq = findSeq(evt);\r
228     int res = findRes(evt);\r
229 \r
230     if (seq < av.getAlignment().getHeight() &&\r
231         res < av.getAlignment().getSequenceAt(seq).getLength())\r
232     {\r
233       //char resstr = align.getSequenceAt(seq).getSequence().charAt(res);\r
234       // Find the residue's position in the sequence (res is the position\r
235       // in the alignment\r
236 \r
237       startseq = seq;\r
238       lastres = res;\r
239     }\r
240     else\r
241     {\r
242       startseq = -1;\r
243       lastres = -1;\r
244     }\r
245 \r
246     return;\r
247   }\r
248 \r
249   public void doMouseMoved(MouseEvent evt)\r
250   {\r
251     int res = findRes(evt);\r
252     int seq = findSeq(evt);\r
253 \r
254     if (seq >= av.getAlignment().getHeight() || seq<0 || res<0)\r
255     {\r
256       return;\r
257     }\r
258 \r
259     SequenceI sequence = av.getAlignment().getSequenceAt(seq);\r
260     if (res > sequence.getLength())\r
261     {\r
262       return;\r
263     }\r
264 \r
265     StringBuffer text = new StringBuffer("Sequence " + (seq + 1) + " ID: " +\r
266             sequence.getName());\r
267 \r
268     Object obj = null;\r
269     if (av.alignment.isNucleotide())\r
270     {\r
271       obj = ResidueProperties.nucleotideName.get(sequence.getCharAt(res) +\r
272           "");\r
273       if(obj!=null)\r
274         text.append(" Nucleotide: ");\r
275     }\r
276     else\r
277     {\r
278       obj = ResidueProperties.aa2Triplet.get(sequence.getCharAt(res) + "");\r
279       if(obj!=null)\r
280         text.append("  Residue: ");\r
281     }\r
282 \r
283     if (obj != null)\r
284     {\r
285 \r
286       if (obj != "")\r
287       {\r
288         text.append(obj + " (" +\r
289                     av.getAlignment().getSequenceAt(seq).findPosition(res) + ")");\r
290       }\r
291     }\r
292 \r
293     if(seqCanvas.pdbCanvas!=null && sequence==seqCanvas.pdbCanvas.sequence)\r
294     {\r
295       seqCanvas.pdbCanvas.highlightRes(sequence.findPosition(res));\r
296     }\r
297 \r
298 \r
299     // use aa to see if the mouse pointer is on a\r
300     if (av.showSequenceFeatures && sequence.getSequenceFeatures()!=null)\r
301     {\r
302       Vector features = sequence.getSequenceFeatures();\r
303       Enumeration e = features.elements();\r
304       text.append(" Sequence Feature: ");\r
305 \r
306       while (e.hasMoreElements())\r
307       {\r
308         SequenceFeature sf = (SequenceFeature) e.nextElement();\r
309         if (sf.getBegin() <= sequence.findPosition(res) &&\r
310             sf.getEnd() >= sequence.findPosition(res))\r
311         {\r
312           text.append(sf.getDescription());\r
313           if (sf.getStatus().length() > 0)\r
314           {\r
315             text.append(" (" + sf.getStatus() + ")");\r
316           }\r
317           text.append("; ");\r
318         }\r
319 \r
320       }\r
321     }\r
322 \r
323      ap.alignFrame.statusBar.setText(text.toString());\r
324 \r
325   }\r
326 \r
327   public void doMouseDragged(MouseEvent evt)\r
328   {\r
329 \r
330     // If we're dragging we're editing\r
331     int res = findRes(evt);\r
332     if (res < 0)\r
333     {\r
334       res = 0;\r
335     }\r
336 \r
337     if (lastres == -1 || lastres == res)\r
338     {\r
339       return;\r
340     }\r
341 \r
342     boolean dragRight = true;\r
343     if (res < av.getAlignment().getWidth() && res < lastres)\r
344     {\r
345       dragRight = false;\r
346     }\r
347 \r
348     if (res != lastres)\r
349     {\r
350       // Group editing\r
351       if (groupEditing)\r
352       {\r
353         SequenceGroup sg = av.getSelectionGroup();\r
354         if (sg == null)\r
355         {\r
356           lastres = -1;\r
357           return;\r
358         }\r
359 \r
360         // drag to right\r
361         if (dragRight)\r
362         {\r
363           sg.setEndRes(sg.getEndRes() + (res - lastres));\r
364         }\r
365 \r
366         // drag to left\r
367         else\r
368         {\r
369           /// Are we able to delete?\r
370           // ie are all columns blank?\r
371           boolean deleteAllowed = false;\r
372           for (int s = 0; s < sg.getSize(); s++)\r
373           {\r
374             SequenceI seq = sg.getSequenceAt(s);\r
375             for (int j = res; j < lastres; j++)\r
376             {\r
377               if (seq.getSequence().length() <= j)\r
378               {\r
379                 continue;\r
380               }\r
381 \r
382               if (!jalview.util.Comparison.isGap(seq.getSequence().charAt(j)))\r
383               {\r
384                 // Not a gap, block edit not valid\r
385                 res = j + 1;\r
386                 deleteAllowed = false;\r
387                 continue;\r
388               }\r
389               deleteAllowed = true;\r
390             }\r
391           }\r
392 \r
393           if (!deleteAllowed)\r
394           {\r
395             lastres = -1;\r
396             return;\r
397           }\r
398 \r
399           sg.setEndRes(sg.getEndRes() - (lastres - res));\r
400         }\r
401 \r
402         for (int i = 0; i < sg.getSize(); i++)\r
403         {\r
404           SequenceI s = sg.getSequenceAt(i);\r
405           int k = av.alignment.findIndex(s);\r
406 \r
407           // drag to right\r
408           if (dragRight)\r
409           {\r
410             for (int j = lastres; j < res; j++)\r
411             {\r
412               insertChar(j, k);\r
413             }\r
414           }\r
415 \r
416           // drag to left\r
417           else\r
418           {\r
419             for (int j = res; j < lastres; j++)\r
420             {\r
421               if (s.getLength() > j)\r
422               {\r
423                 deleteChar(res, k);\r
424               }\r
425             }\r
426           }\r
427         }\r
428       }\r
429       else /////Editing a single sequence///////////\r
430       {\r
431         if (res < av.getAlignment().getWidth() && res > lastres)\r
432         {\r
433           // dragging to the right\r
434           for (int j = lastres; j < res; j++)\r
435           {\r
436             insertChar(j, startseq);\r
437           }\r
438         }\r
439         else if (res < av.getAlignment().getWidth() && res < lastres)\r
440         {\r
441           // dragging to the left\r
442           for (int j = lastres; j > res; j--)\r
443           {\r
444             if (jalview.util.Comparison.isGap(\r
445                 av.alignment.getSequenceAt(startseq).getSequence().charAt(res)))\r
446             {\r
447 \r
448               deleteChar(res, startseq);\r
449             }\r
450             else\r
451             {\r
452 \r
453               break;\r
454             }\r
455           }\r
456         }\r
457 \r
458       }\r
459     }\r
460 \r
461     endEdit = res;\r
462     lastres = res;\r
463     seqCanvas.repaint();\r
464   }\r
465 \r
466   public void drawChars(int seqstart, int seqend, int start)\r
467   {\r
468     seqCanvas.drawPanel(seqCanvas.gg, start, av.getEndRes(), seqstart, seqend,\r
469                         av.getStartRes(), av.getStartSeq(), 0);\r
470     seqCanvas.repaint();\r
471   }\r
472 \r
473   public void insertChar(int j, int seq)\r
474   {\r
475     av.alignment.getSequenceAt(seq).insertCharAt(j, av.getGapCharacter());\r
476     seqEditOccurred = seq;\r
477   }\r
478 \r
479   public void deleteChar(int j, int seq)\r
480   {\r
481 \r
482     av.alignment.getSequenceAt(seq).deleteCharAt(j);\r
483     seqEditOccurred = seq;\r
484     av.alignment.getWidth();\r
485     repaint();\r
486   }\r
487 \r
488   void editOccurred(int i)\r
489   {\r
490     if (endEdit == startEdit)\r
491     {\r
492         ap.alignFrame.historyList.pop();\r
493         ap.alignFrame.updateEditMenuBar();\r
494     }\r
495 \r
496     av.firePropertyChange("alignment", null,av.getAlignment().getSequences());\r
497   }\r
498 \r
499 //////////////////////////////////////////\r
500 /////Everything below this is for defining the boundary of the rubberband\r
501 //////////////////////////////////////////\r
502   int oldSeq = -1;\r
503   public void doMousePressedDefineMode(MouseEvent evt)\r
504   {\r
505     int res = findRes(evt);\r
506     int seq = findSeq(evt);\r
507     oldSeq = seq;\r
508     startWrapBlock=wrappedBlock;\r
509 \r
510     if(seq==-1)\r
511       return;\r
512 \r
513     SequenceI sequence = (Sequence) av.getAlignment().getSequenceAt(seq);\r
514 \r
515     if (sequence == null || res > sequence.getLength())\r
516     {\r
517       return;\r
518     }\r
519 \r
520     stretchGroup = av.getSelectionGroup();\r
521 \r
522     if (stretchGroup == null)\r
523     {\r
524       stretchGroup = av.alignment.findGroup(sequence);\r
525       if (stretchGroup != null && res > stretchGroup.getStartRes() &&\r
526           res < stretchGroup.getEndRes())\r
527       {\r
528         av.setSelectionGroup(stretchGroup);\r
529       }\r
530       else\r
531       {\r
532         stretchGroup = null;\r
533       }\r
534     }\r
535 \r
536     else if (!stretchGroup.sequences.contains(sequence)\r
537              || stretchGroup.getStartRes() > res\r
538              || stretchGroup.getEndRes() < res)\r
539     {\r
540       stretchGroup = null;\r
541 \r
542       SequenceGroup[] allGroups = av.alignment.findAllGroups(sequence);\r
543 \r
544       if (allGroups != null)\r
545       {\r
546         for (int i = 0; i < allGroups.length; i++)\r
547         {\r
548           if (allGroups[i].getStartRes() <= res &&\r
549               allGroups[i].getEndRes() >= res)\r
550           {\r
551             stretchGroup = allGroups[i];\r
552             av.setSelectionGroup(stretchGroup);\r
553             break;\r
554           }\r
555         }\r
556       }\r
557     }\r
558 \r
559     if (stretchGroup == null)\r
560     {\r
561       // define a new group here\r
562       SequenceGroup sg = new SequenceGroup();\r
563       sg.setStartRes(res);\r
564       sg.setEndRes(res);\r
565       sg.addSequence(sequence, false);\r
566       av.setSelectionGroup(sg);\r
567       stretchGroup = sg;\r
568 \r
569       if (av.getConservationSelected())\r
570       {\r
571         SliderPanel.setConservationSlider(ap, av.getGlobalColourScheme(),\r
572                                           "Background");\r
573       }\r
574       if (av.getAbovePIDThreshold())\r
575       {\r
576         SliderPanel.setPIDSliderSource(ap, av.getGlobalColourScheme(),\r
577                                        "Background");\r
578       }\r
579 \r
580     }\r
581 \r
582     // DETECT RIGHT MOUSE BUTTON IN AWT\r
583     else if ( (evt.getModifiers() & InputEvent.BUTTON3_MASK) ==\r
584              InputEvent.BUTTON3_MASK)\r
585     {\r
586       APopupMenu popup = new APopupMenu(ap, null, null);\r
587       this.add(popup);\r
588       popup.show(this, evt.getX(), evt.getY());\r
589     }\r
590 \r
591     if (stretchGroup != null && stretchGroup.getEndRes() == res)\r
592     {\r
593       // Edit end res position of selected group\r
594       changeEndRes = true;\r
595     }\r
596 \r
597     else if (stretchGroup != null && stretchGroup.getStartRes() == res)\r
598     {\r
599       // Edit end res position of selected group\r
600       changeStartRes = true;\r
601     }\r
602 \r
603   }\r
604 \r
605   boolean changeEndSeq = false;\r
606   boolean changeStartSeq = false;\r
607   boolean changeEndRes = false;\r
608   boolean changeStartRes = false;\r
609   SequenceGroup stretchGroup = null;\r
610 \r
611   public void doMouseReleasedDefineMode(MouseEvent evt)\r
612   {\r
613     if(mouseDragging)\r
614      {\r
615        stretchGroup.recalcConservation();\r
616        mouseDragging = false;\r
617      }\r
618 \r
619     if (stretchGroup == null)\r
620     {\r
621       return;\r
622     }\r
623 \r
624     if(stretchGroup.cs!=null)\r
625     {\r
626       if (stretchGroup.cs.conservationApplied())\r
627       {\r
628         SliderPanel.setConservationSlider(ap, stretchGroup.cs,\r
629                                           stretchGroup.getName());\r
630       }\r
631       else\r
632       {\r
633         SliderPanel.setPIDSliderSource(ap, stretchGroup.cs,\r
634                                        stretchGroup.getName());\r
635       }\r
636     }\r
637     changeEndRes = false;\r
638     changeStartRes = false;\r
639     stretchGroup = null;\r
640     seqCanvas.repaint();\r
641     ap.repaint();\r
642   }\r
643 \r
644   boolean remove = false;\r
645   public void doMouseDraggedDefineMode(MouseEvent evt)\r
646   {\r
647     int res = findRes(evt);\r
648     int y = findSeq(evt);\r
649 \r
650     if(wrappedBlock!=startWrapBlock)\r
651         return;\r
652 \r
653     if(y>=av.alignment.getHeight())\r
654       y = av.alignment.getHeight()-1;\r
655 \r
656     if (stretchGroup == null)\r
657     {\r
658       return;\r
659     }\r
660 \r
661     if (res > av.alignment.getWidth())\r
662     {\r
663       res = av.alignment.getWidth() - 1;\r
664     }\r
665 \r
666     if (stretchGroup.getEndRes() == res)\r
667     {\r
668       // Edit end res position of selected group\r
669       changeEndRes = true;\r
670     }\r
671 \r
672     else if (stretchGroup.getStartRes() == res)\r
673     {\r
674       // Edit start res position of selected group\r
675       changeStartRes = true;\r
676     }\r
677 \r
678     if (res < av.getStartRes())\r
679     {\r
680       res = av.getStartRes();\r
681     }\r
682     else if (res > av.getEndRes() && !av.getWrapAlignment())\r
683     {\r
684       res = av.getEndRes();\r
685     }\r
686 \r
687     if (changeEndRes)\r
688     {\r
689       if (res > stretchGroup.getStartRes() - 1)\r
690       {\r
691         stretchGroup.setEndRes(res);\r
692       }\r
693     }\r
694     else if (changeStartRes)\r
695     {\r
696       if (res < stretchGroup.getEndRes() + 1)\r
697       {\r
698         stretchGroup.setStartRes(res);\r
699       }\r
700     }\r
701 \r
702     int dragDirection = 0;\r
703     if (y > oldSeq)\r
704     {\r
705       dragDirection = 1;\r
706     }\r
707     else if (y < oldSeq)\r
708     {\r
709       dragDirection = -1;\r
710     }\r
711 \r
712     while (y != oldSeq && oldSeq > 0 && y < av.alignment.getHeight())\r
713     {\r
714       // This routine ensures we don't skip any sequences, as the\r
715       // selection is quite slow.\r
716       Sequence seq = (Sequence) av.getAlignment().getSequenceAt(oldSeq);\r
717 \r
718       oldSeq += dragDirection;\r
719       Sequence nextSeq = (Sequence) av.getAlignment().getSequenceAt(oldSeq);\r
720 \r
721       if (stretchGroup.sequences.contains(nextSeq))\r
722       {\r
723         stretchGroup.deleteSequence(seq, false);\r
724       }\r
725       else\r
726       {\r
727         if (seq != null)\r
728         {\r
729           stretchGroup.addSequence(seq, false);\r
730         }\r
731         stretchGroup.addSequence(nextSeq, false);\r
732       }\r
733     }\r
734     oldSeq = y;\r
735     mouseDragging = true;\r
736     if (scrollThread != null)\r
737     {\r
738       scrollThread.setEvent(evt);\r
739     }\r
740 \r
741     seqCanvas.repaint();\r
742   }\r
743 \r
744   public void doMouseEnteredDefineMode(MouseEvent e)\r
745   {\r
746     if (scrollThread != null)\r
747     {\r
748       scrollThread.running = false;\r
749     }\r
750   }\r
751 \r
752   public void doMouseExitedDefineMode(MouseEvent e)\r
753   {\r
754     if (mouseDragging)\r
755     {\r
756       scrollThread = new ScrollThread();\r
757     }\r
758   }\r
759 \r
760   // this class allows scrolling off the bottom of the visible alignment\r
761   class ScrollThread\r
762       extends Thread\r
763   {\r
764     MouseEvent evt;\r
765     boolean running = false;\r
766     public ScrollThread()\r
767     {\r
768       start();\r
769     }\r
770 \r
771     public void setEvent(MouseEvent e)\r
772     {\r
773       evt = e;\r
774     }\r
775 \r
776     public void stopScrolling()\r
777     {\r
778       running = false;\r
779     }\r
780 \r
781     public void run()\r
782     {\r
783       running = true;\r
784       while (running)\r
785       {\r
786         if (evt != null)\r
787         {\r
788 \r
789           if (mouseDragging && evt.getY() < 0 && av.getStartSeq() > 0)\r
790           {\r
791             running = ap.scrollUp(true);\r
792           }\r
793 \r
794           if (mouseDragging && evt.getY() >= getSize().height &&\r
795               av.alignment.getHeight() > av.getEndSeq())\r
796           {\r
797             running = ap.scrollUp(false);\r
798           }\r
799 \r
800           if (mouseDragging && evt.getX() < 0)\r
801           {\r
802             running = ap.scrollRight(true);\r
803           }\r
804 \r
805           else if (mouseDragging && evt.getX() >= getSize().width)\r
806           {\r
807             running = ap.scrollRight(false);\r
808           }\r
809         }\r
810 \r
811         try\r
812         {\r
813           Thread.sleep(75);\r
814         }\r
815         catch (Exception ex)\r
816         {}\r
817       }\r
818     }\r
819   }\r
820 \r
821 }\r