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