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