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