xref: /titanic_41/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/awt/WinScrollbar.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * ident	"%Z%%M%	%I%	%E% SMI"
24  *
25  *
26  * Copyright (c) 1994-1995, 2001 by Sun Microsystems, Inc.
27  * All rights reserved.
28  *
29  * Permission to use, copy, modify, and distribute this software
30  * and its documentation for NON-COMMERCIAL purposes and without
31  * fee is hereby granted provided that this copyright notice
32  * appears in all copies. Please refer to the file "copyright.html"
33  * for further important copyright and licensing information.
34  *
35  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
36  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
37  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
39  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
40  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
41  *
42  *
43  *        Copyright (C) 1996  Active Software, Inc.
44  *                  All rights reserved.
45  *
46  * @(#) WinScrollbar.java 1.13 - last change made 05/02/97
47  */
48 
49 package sunsoft.jws.visual.rt.awt;
50 
51 import sunsoft.jws.visual.rt.base.Global;
52 import sunsoft.jws.visual.rt.base.Util;
53 import java.awt.*;
54 
55 
56 public class WinScrollbar extends Canvas implements Runnable {
57 
58     /**
59      * The horizontal Scrollbar variable.
60      */
61     public static final int	HORIZONTAL = Scrollbar.HORIZONTAL;
62 
63     /**
64      * The vertical Scrollbar variable.
65      */
66     public static final int	VERTICAL   = Scrollbar.VERTICAL;
67 
68     /**
69      * The value of the Scrollbar.
70      */
71     int	value;
72 
73     /**
74      * The maximum value of the Scrollbar.
75      */
76     int	maximum;		// doesn't include the visible area
77 
78     /**
79      * The minimum value of the Scrollbar.
80      */
81     int	minimum;
82 
83     /**
84      * The size of the visible portion of the Scrollbar.
85      */
86     int	sVisible;
87 
88     /**
89      * The Scrollbar's orientation--being either horizontal or vertical.
90      */
91     int	orientation;
92 
93     /**
94      * The amount by which the scrollbar value will change when going
95      * up or down by a line.
96      */
97     int lineIncrement = 1;
98 
99     /**
100      * The amount by which the scrollbar value will change when going
101      * up or down by a page.
102      */
103     int pageIncrement = 10;
104 
105     /**
106      * Are we running on WindowsNT
107      */
108     private boolean winNT;
109 
110     private static WinScrollbar threadScrollbar;
111     private static Thread scrollThread;
112     private WinScrollbar currentScrollbar;
113     private int currentScrollAction;
114     private int currentScrollPosition;
115 
116     private static final int SCROLL_DELAY = 250;
117     private static final int SCROLL_INTERVAL = 40;
118 
119     /**
120      * Constructs a new vertical Scrollbar.
121      */
WinScrollbar()122     public WinScrollbar() {
123         this(VERTICAL);
124     }
125 
126 
127     /**
128      * Constructs a new Scrollbar with the specified orientation.
129      * @param orientation either Scrollbar.HORIZONTAL
130      * or Scrollbar.VERTICAL
131      * @exception IllegalArgumentException When an
132      * illegal scrollbar orientation is given.
133     */
WinScrollbar(int orientation)134     public WinScrollbar(int orientation) {
135         switch (orientation) {
136 	case Scrollbar.HORIZONTAL:
137 	case Scrollbar.VERTICAL:
138             this.orientation = orientation;
139             break;
140 
141 	default:
142             /* JSTYLED */
143 	    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.WinScrollbar.IllegalOrientation"));
144         }
145 
146         winNT = Global.isWindowsNT();
147     }
148 
149     /**
150      * Constructs a new Scrollbar with the specified orientation,
151      * value, page size,  and minumum and maximum values.
152      * @param orientation either Scrollbar.HORIZONTAL
153      * or Scrollbar.VERTICAL
154      * @param value the scrollbar's value
155      * @param visible the size of the visible portion of the
156      * scrollable area. The scrollbar will use this value when paging up
157      * or down by a page.
158      * @param minimum the minimum value of the scrollbar
159      * @param maximum the maximum value of the scrollbar
160      */
WinScrollbar(int orientation, int value, int visible, int minimum, int maximum)161     public WinScrollbar(int orientation, int value, int visible,
162 			int minimum, int maximum) {
163         this(orientation);
164         setValues(value, visible, minimum, maximum);
165     }
166 
167     /**
168      * Returns the orientation for this Scrollbar.
169      */
getOrientation()170     public int getOrientation() {
171         return orientation;
172     }
173 
174     /**
175      * Returns the current value of this Scrollbar.
176      * @see #getMinimum
177      * @see #getMaximum
178      */
getValue()179     public int getValue() {
180         return value;
181     }
182 
183     /**
184      * Sets the value of this Scrollbar to the specified value.
185      * @param value the new value of the Scrollbar. If this value is
186      * below the current minimum or above
187      * the current maximum, it becomes the
188      * new one of those values, respectively.
189      * @see #getValue
190      */
setValue(int value)191     public void setValue(int value) {
192         if (value < minimum) {
193             value = minimum;
194         }
195         if (value > (maximum - sVisible)) {
196             value = maximum - sVisible;
197         }
198         if (value != this.value) {
199             this.value = value;
200             if (getPeer() != null)
201                 peerSetValue(value);
202         }
203     }
204 
205     /**
206      * Returns the minimum value of this Scrollbar.
207      * @see #getMaximum
208      * @see #getValue
209      */
getMinimum()210     public int getMinimum() {
211         return minimum;
212     }
213 
214     /**
215      * Returns the maximum value of this Scrollbar.
216      * @see #getMinimum
217      * @see #getValue
218      */
getMaximum()219     public int getMaximum() {
220         return maximum;
221     }
222 
223     /**
224      * Returns the visible amount of the Scrollbar.
225      */
getVisible()226     public int getVisible() {
227         return sVisible;
228     }
229 
230     /**
231      * Sets the line increment for this scrollbar. This is the value
232      * that will be added (subtracted) when the user hits the line down
233      * (up) gadgets.
234      */
setLineIncrement(int l)235     public void setLineIncrement(int l) {
236         lineIncrement = l;
237         if (getPeer() != null)
238             peerSetLineIncrement(l);
239     }
240 
241     /**
242      * Gets the line increment for this scrollbar.
243      */
getLineIncrement()244     public int getLineIncrement() {
245         return lineIncrement;
246     }
247 
248     /**
249      * Sets the page increment for this scrollbar. This is the value
250      * that will be added (subtracted) when the user hits the page down
251      * (up) gadgets.
252      */
setPageIncrement(int l)253     public void setPageIncrement(int l) {
254         pageIncrement = l;
255         if (getPeer() != null)
256             peerSetPageIncrement(l);
257     }
258 
259     /**
260      * Gets the page increment for this scrollbar.
261      */
getPageIncrement()262     public int getPageIncrement() {
263         return pageIncrement;
264     }
265 
266     /**
267      * Sets the values for this Scrollbar.
268      * @param value is the position in the current window.
269      * @param visible is the amount visible per page
270      * @param minimum is the minimum value of the scrollbar
271      * @param maximum is the maximum value of the scrollbar
272      */
setValues(int value, int visible, int minimum, int maximum)273     public void setValues(int value, int visible, int minimum,
274 			  int maximum) {
275         if (visible < 0)
276             visible = 0;
277 
278         if (visible > maximum)
279             visible = maximum;
280 
281         if (maximum < minimum) {
282             maximum = minimum;
283         }
284         if (value < minimum) {
285             value = minimum;
286         }
287         if (value > (maximum - visible)) {
288             value = (maximum - visible);
289         }
290 
291         this.value = value;
292         this.sVisible = visible;
293         this.minimum = minimum;
294         this.maximum = maximum;
295 
296         if (getPeer() != null)
297             peerSetValues(value, sVisible, minimum, maximum);
298     }
299 
300     /**
301      * Returns the String parameters for this Scrollbar.
302      */
paramString()303     protected String paramString() {
304         return super.paramString() +
305 	    /* NOI18N */",val=" + value +
306 	    /* NOI18N */",vis=" + isVisible() +
307 	    /* NOI18N */",min=" + minimum +
308 	    /* NOI18N */",max=" + maximum +
309 	    ((orientation == VERTICAL) ? /* NOI18N */
310 	    ",vert" : /* NOI18N */",horz");
311     }
312 
313     /**
314      * Returns the minimum size for the scrollbar
315      */
minimumSize()316     public Dimension minimumSize() {
317         if (orientation == VERTICAL)
318             return new Dimension(16, 50);
319         else
320             return new Dimension(50, 16);
321     }
322 
323     /**
324      * Returns the preferred size for the scrollbar
325      */
preferredSize()326     public Dimension preferredSize() {
327         return minimumSize();
328     }
329 
330 
331     // The rest of this code does the things
332     // that the peer would normally
333     // if the peer weren't so badly broken.
334 
335     private Image buffer;
336     private int prevWidth = 0;
337     private int prevHeight = 0;
338     private int action = 0;
339 
340     private int anchorPos;
341     private int anchorValue;
342     private int dragSpace;
343 
344     private static final int UP = 10;
345     private static final int DOWN = 11;
346     private static final int LEFT = 12;
347     private static final int RIGHT = 13;
348 
349     private static final int LINEUP = 20;
350     private static final int LINEDOWN = 21;
351     private static final int PAGEUP = 22;
352     private static final int PAGEDOWN = 23;
353     private static final int DRAG = 24;
354 
peerSetValue(int value)355     private void peerSetValue(int value) {
356         repaint();
357     }
358 
peerSetLineIncrement(int l)359     private void peerSetLineIncrement(int l) {
360     }
361 
peerSetPageIncrement(int l)362     private void peerSetPageIncrement(int l) {
363     }
364 
peerSetValues(int value, int sVisible, int minimum, int maximum)365     private void peerSetValues(int value, int sVisible,
366 			       int minimum, int maximum) {
367         repaint();
368     }
369 
reshape(int x, int y, int width, int height)370     public void reshape(int x, int y, int width, int height) {
371         super.reshape(x, y, width, height);
372 
373         if (prevWidth != width || prevHeight != height) {
374             if (width > 0 && height > 0)
375                 buffer = createImage(width, height);
376             else
377                 buffer = null;
378 
379             prevWidth = width;
380             prevHeight = height;
381         }
382     }
383 
update(Graphics g)384     public void update(Graphics g) {
385         if (Global.isWindows())
386             g = getGraphics();
387         draw(g);
388     }
389 
paint(Graphics g)390     public void paint(Graphics g) {
391         if (Global.isWindows())
392             g = getGraphics();
393         draw(g);
394     }
395 
draw(Graphics g)396     private void draw(Graphics g) {
397         if (buffer == null)
398             return;
399 
400         drawScrollbar();
401         g.drawImage(buffer, 0, 0, null);
402     }
403 
drawScrollbar()404     private void drawScrollbar() {
405         Graphics g = buffer.getGraphics();
406         Dimension size = size();
407         int w = size.width;
408         int h = size.height;
409 
410         // Erase the old version
411         g.setColor(getBackground());
412         g.fillRect(0, 0, size.width, size.height);
413 
414         drawOutline(g, w-1, h-1);
415         drawEndBoxes(g, w-1, h-1);
416 
417         int info[] = getDragBoxInfo();
418         fillPageBox(g, w, h, info);
419         drawDragBox(g, w-1, h-1, info);
420     }
421 
drawOutline(Graphics g, int w, int h)422     private void drawOutline(Graphics g, int w, int h) {
423         g.setColor(Global.util.darker(getBackground()));
424         if (orientation == VERTICAL) {
425             g.drawRect(0, 0, w, w);
426             g.drawRect(0, w, w, h-2*w);
427             g.drawRect(0, h-w, w, w);
428         } else {
429             g.drawRect(0, 0, h, h);
430             g.drawRect(h, 0, w-2*h, h);
431             g.drawRect(w-h, 0, h, h);
432         }
433     }
434 
drawEndBoxes(Graphics g, int w, int h)435     private void drawEndBoxes(Graphics g, int w, int h) {
436         if (orientation == VERTICAL) {
437             if (action != LINEUP) {
438                 drawArrow(g, 0, 0, w, w, UP);
439                 drawBox(g, 0, 0, w, w);
440             } else {
441                 drawArrow(g, 1, 1, w, w, UP);
442             }
443 
444             if (action != LINEDOWN) {
445                 drawArrow(g, 0, h-w, w, w, DOWN);
446                 drawBox(g, 0, h-w, w, w);
447             } else {
448                 drawArrow(g, 1, h-w+1, w, w, DOWN);
449             }
450         } else {
451             if (action != LINEUP) {
452                 drawArrow(g, 0, 0, h, h, LEFT);
453                 drawBox(g, 0, 0, h, h);
454             } else {
455                 drawArrow(g, 1, 1, h, h, LEFT);
456             }
457 
458             if (action != LINEDOWN) {
459                 drawArrow(g, w-h, 0, h, h, RIGHT);
460                 drawBox(g, w-h, 0, h, h);
461             } else {
462                 drawArrow(g, w-h+1, 1, h, h, RIGHT);
463             }
464         }
465     }
466 
fillPageBox(Graphics g, int w, int h, int info[])467     private void fillPageBox(Graphics g, int w, int h, int info[]) {
468         g.setColor(pageDarker(getBackground()));
469         if (orientation == VERTICAL) {
470             if (action == PAGEUP) {
471                 g.fillRect(1, w, w-2, info[0]-w);
472             } else if (action == PAGEDOWN) {
473                 g.fillRect(1, info[0]+info[1]+1, w-2,
474 			   h-(w+info[0]+info[1])-1);
475             }
476         } else {
477             if (action == PAGEUP) {
478                 g.fillRect(h, 1, info[0]-h, h-2);
479             } else if (action == PAGEDOWN) {
480                 g.fillRect(info[0]+info[1]+1, 1,
481 			   w-(h+info[0]+info[1])-1, h-2);
482             }
483         }
484     }
485 
drawDragBox(Graphics g, int w, int h, int info[])486     private void drawDragBox(Graphics g, int w, int h, int info[]) {
487         if (orientation == VERTICAL) {
488             drawBox(g, 0, info[0], w, info[1]);
489         } else {
490             drawBox(g, info[0], 0, info[1], h);
491         }
492     }
493 
getDragBoxInfo()494     private int [] getDragBoxInfo() {
495         int info[] = new int[2];
496         int minpix;
497         int deltapix;
498         Dimension size = size();
499 
500         if (orientation == VERTICAL) {
501             minpix = size.width;
502             deltapix = size.height - 2 * size.width;
503         } else {
504             minpix = size.height;
505             deltapix = size.width - 2 * size.height;
506         }
507 
508         int deltaval = maximum - minimum;
509         double d = (double)deltapix/(double)deltaval;
510         double xory = minpix + (value-minimum) * d;
511         double worh = sVisible * d;
512 
513         info[0] = (int)xory;
514         info[1] = (int)worh;
515 
516         return info;
517     }
518 
drawBox(Graphics g, int x, int y, int w, int h)519     private void drawBox(Graphics g, int x, int y, int w, int h) {
520         g.setColor(getBackground());
521         Global.util.draw3DRect(g, x, y, w, h,
522 			       Util.WIN95_WINDOW_BORDER, 2);
523 
524         if (true)
525             return;
526         else {
527             g.setColor(Global.util.brighter(getBackground()));
528             g.drawLine(x, y, x+w-1, y);
529             g.drawLine(x, y, x, y+h-1);
530 
531             g.setColor(Color.white);
532             g.drawLine(x+1, y+1, x+w-2, y+1);
533             g.drawLine(x+1, y+1, x+1, y+h-2);
534 
535             g.setColor(Color.black);
536             g.drawLine(x+w, y, x+w, y+h);
537             g.drawLine(x, y+h, x+w, y+h);
538 
539             g.setColor(Global.util.darker(getBackground()));
540             g.drawLine(x+w-1, y+1, x+w-1, y+h-1);
541             g.drawLine(x+1, y+h-1, x+w-1, y+h-1);
542         }
543     }
544 
drawArrow(Graphics g, int x, int y, int w, int h, int direction)545     private void drawArrow(Graphics g, int x, int y, int w, int h,
546 			   int direction) {
547         Polygon p = new Polygon();
548 
549         // xoff=4 and yoff=4 for the default case where w=15 and y=15
550         int xoff = (w-3)/3;
551         int yoff = (h-3)/3;
552         int bd = 2;
553 
554         g.setColor(Color.black);
555 
556         switch (direction) {
557 	case LEFT:
558             if (winNT) {
559                 x -= xoff/4;
560                 g.fillRect(x+bd+2*xoff-1, y+bd+(5*yoff/4)-1,
561 			   xoff/2+1, yoff/2+1);
562             }
563             p.addPoint(x+bd+xoff-1, y+bd+(3*yoff/2)-1);
564             p.addPoint(x+bd+2*xoff-1, y+bd+yoff-3);
565             p.addPoint(x+bd+2*xoff-1, y+bd+2*yoff+1);
566             break;
567 
568 	case RIGHT:
569             if (winNT) {
570                 x += xoff/4+1;
571                 g.fillRect(x+bd+(xoff/2)-1, y+bd+(5*yoff/4)-1,
572 			   xoff/2+2, yoff/2+1);
573             }
574             p.addPoint(x+bd+xoff, y+bd+yoff-3);
575             p.addPoint(x+bd+xoff*2, y+bd+(3*yoff/2)-1);
576             p.addPoint(x+bd+xoff, y+bd+2*yoff+1);
577             break;
578 
579 	case UP:
580             if (winNT) {
581                 y -= yoff/4+1;
582                 g.fillRect(x+bd+(5*xoff/4)-1, y+bd+2*yoff,
583 			   xoff/2+1, yoff/2+1);
584             }
585             p.addPoint(x+bd+xoff-3, y+bd+2*yoff);
586             p.addPoint(x+bd+(3*xoff/2)-1, y+bd+yoff);
587             p.addPoint(x+bd+(3*xoff/2), y+bd+yoff);
588             p.addPoint(x+bd+2*xoff+2, y+bd+2*yoff);
589             break;
590 
591 	case DOWN:
592             if (winNT) {
593                 y += yoff/4+1;
594                 g.fillRect(x+bd+(5*xoff/4)-1, y+bd+(yoff/2)-1,
595 			   xoff/2+1, yoff/2+2);
596             }
597             p.addPoint(x+bd+xoff-2, y+bd+yoff);
598             p.addPoint(x+bd+2*xoff+1, y+bd+yoff);
599             p.addPoint(x+bd+(3*xoff/2)-1, y+bd+2*yoff);
600             p.addPoint(x+bd+(3*xoff/2)-1, y+bd+2*yoff-1);
601             break;
602         }
603 
604         g.fillPolygon(p);
605     }
606 
607     private static final double PAGE_DFACTOR = 0.8;
608 
609     /**
610      * Returns a darker version of this color used for the paging
611      * highlight color.
612      */
pageDarker(Color c)613     private Color pageDarker(Color c) {
614         return new Color(Math.max((int)(c.getRed()  *PAGE_DFACTOR), 0),
615 			 Math.max((int)(c.getGreen()*PAGE_DFACTOR), 0),
616 			 Math.max((int)(c.getBlue() *PAGE_DFACTOR), 0));
617     }
618 
mouseDown(Event evt, int x, int y)619     public boolean mouseDown(Event evt, int x, int y) {
620         Dimension size = size();
621         int w = size.width;
622         int h = size.height;
623 
624         if (orientation == VERTICAL) {
625             if (y < w) {
626                 lineUp(y);
627             } else if (y >= (h-w)) {
628                 lineDown(y);
629             } else {
630                 int info[] = getDragBoxInfo();
631                 if (y >= (w+1) && y < info[0]) {
632                     pageUp(y);
633                 } else if (y >= info[0]+info[1] && y < (h-w)) {
634                     pageDown(y);
635                 } else if (y >= info[0] && y < info[0]+info[1]) {
636                     dragStart(x, y);
637                 }
638             }
639 
640         } else {
641             if (x < h) {
642                 lineUp(x);
643             } else if (x >= (w-h)) {
644                 lineDown(x);
645             } else {
646                 int info[] = getDragBoxInfo();
647                 if (x >= (h+1) && x < info[0]) {
648                     pageUp(x);
649                 } else if (x >= info[0]+info[1] && x < (w-h)) {
650                     pageDown(x);
651                 } else if (x >= info[0] && x < info[0]+info[1]) {
652                     dragStart(x, y);
653                 }
654             }
655         }
656 
657         return false;
658     }
659 
mouseDrag(Event evt, int x, int y)660     public boolean mouseDrag(Event evt, int x, int y) {
661         if (action == DRAG) {
662             drag(x, y);
663             return true;
664         } else if (threadScrollbar != null &&
665 		   threadScrollbar.currentScrollbar == this) {
666             synchronized (threadScrollbar) {
667                 if (orientation == VERTICAL)
668                     threadScrollbar.currentScrollPosition = y;
669                 else
670                     threadScrollbar.currentScrollPosition = x;
671             }
672         }
673 
674         return false;
675     }
676 
mouseUp(Event evt, int x, int y)677     public boolean mouseUp(Event evt, int x, int y) {
678         cancelAutoScroll();
679 
680         if (action == DRAG) {
681             dragStop(x, y);
682         }
683 
684         action = 0;
685         repaint();
686 
687         return false;
688     }
689 
lineUp(int pos)690     private boolean lineUp(int pos) {
691         boolean status = false;
692         action = LINEUP;
693         initAutoScroll(action, pos);
694 
695         int prevValue = value;
696         value = Math.max(minimum, value-lineIncrement);
697         if (value != prevValue) {
698             status = true;
699             postEvent(new Event(this, Event.SCROLL_LINE_UP,
700 				new Integer(value)));
701         }
702 
703         repaint();
704         return status;
705     }
706 
lineDown(int pos)707     private boolean lineDown(int pos) {
708         boolean status = false;
709         action = LINEDOWN;
710         initAutoScroll(action, pos);
711 
712         int prevValue = value;
713         value = Math.min(maximum-sVisible, value+lineIncrement);
714         if (value != prevValue) {
715             postEvent(new Event(this, Event.SCROLL_LINE_DOWN,
716 				new Integer(value)));
717             status = true;
718         }
719 
720         repaint();
721         return status;
722     }
723 
pageUp(int pos)724     private boolean pageUp(int pos) {
725         boolean status = false;
726         action = PAGEUP;
727         initAutoScroll(action, pos);
728 
729         int prevValue = value;
730         value = Math.max(minimum, value-pageIncrement);
731         if (value != prevValue) {
732             status = true;
733             postEvent(new Event(this, Event.SCROLL_PAGE_UP,
734 				new Integer(value)));
735         }
736 
737         repaint();
738         return status;
739     }
740 
pageDown(int pos)741     private boolean pageDown(int pos) {
742         boolean status = false;
743         action = PAGEDOWN;
744         initAutoScroll(action, pos);
745 
746         int prevValue = value;
747         value = Math.min(maximum-sVisible, value+pageIncrement);
748         if (value != prevValue) {
749             status = true;
750             postEvent(new Event(this, Event.SCROLL_PAGE_DOWN,
751 				new Integer(value)));
752         }
753 
754         repaint();
755         return status;
756     }
757 
dragStart(int x, int y)758     private void dragStart(int x, int y) {
759         action = DRAG;
760 
761         if (orientation == VERTICAL)
762             anchorPos = y;
763         else
764             anchorPos = x;
765 
766         anchorValue = value;
767 
768         Dimension size = size();
769         int info[] = getDragBoxInfo();
770 
771         if (orientation == VERTICAL)
772             dragSpace = size.height - size.width*2 - info[1];
773         else
774             dragSpace = size.width - size.height*2 - info[1];
775     }
776 
drag(int x, int y)777     private void drag(int x, int y) {
778         if (orientation == VERTICAL)
779             newDragValue(y);
780         else
781             newDragValue(x);
782     }
783 
dragStop(int x, int y)784     private void dragStop(int x, int y) {
785         action = 0;
786         drag(x, y);
787     }
788 
newDragValue(int pos)789     private void newDragValue(int pos) {
790         int pixelsDiff = pos - anchorPos;
791         int valDiff = (pixelsDiff * (maximum-minimum) / dragSpace);
792         int prevValue = value;
793 
794         value = anchorValue + valDiff;
795         if (valDiff < 0)
796             value = Math.max(value, minimum);
797         else
798             value = Math.min(value, maximum-sVisible);
799 
800         if (value != prevValue)
801             postEvent(new Event(this, Event.SCROLL_ABSOLUTE,
802 				new Integer(value)));
803 
804         repaint();
805     }
806 
initAutoScroll(int action, int pos)807     private void initAutoScroll(int action, int pos) {
808         if (Thread.currentThread() == scrollThread)
809             return;
810 
811         if (threadScrollbar == null) {
812             threadScrollbar = this;
813             scrollThread = new Thread(threadScrollbar, /* NOI18N */
814 				      "WindowsScrollbarThread");
815             scrollThread.setDaemon(true);
816             scrollThread.start();
817         }
818 
819         synchronized (threadScrollbar) {
820             threadScrollbar.currentScrollbar = this;
821             threadScrollbar.currentScrollAction = action;
822             threadScrollbar.currentScrollPosition = pos;
823             threadScrollbar.notify();
824         }
825     }
826 
cancelAutoScroll()827     private void cancelAutoScroll() {
828         if (threadScrollbar != null) {
829             synchronized (threadScrollbar) {
830                 threadScrollbar.currentScrollbar = null;
831                 threadScrollbar.currentScrollAction = -1;
832                 threadScrollbar.currentScrollPosition = -1;
833                 threadScrollbar.notify();
834             }
835         }
836     }
837 
run()838     public synchronized void run() {
839         boolean scrolling = false;
840         long waitTime;
841 
842         while (scrollThread == Thread.currentThread()) {
843             long startTime = System.currentTimeMillis();
844 
845             if (currentScrollbar == null) {
846                 waitTime = 0;
847                 scrolling = false;
848             } else {
849                 if (scrolling) {
850                     if (!doScroll(currentScrollbar,
851 				  currentScrollAction,
852 				  currentScrollPosition)) {
853                         cancelAutoScroll();
854                         waitTime = 0;
855                     } else {
856                         waitTime = SCROLL_INTERVAL;
857                     }
858                 } else {
859                     waitTime = SCROLL_DELAY;
860                     scrolling = true;
861                 }
862             }
863 
864             // Wait for "waitTime" milliseconds.
865             // But if "waitTime" is zero,
866             // then just wait for a notify.  If
867             // the currentScrollbar changes,
868             // then don't wait any longer.
869             if (waitTime == 0 || currentScrollbar == null) {
870                 try { wait(0); }
871                 catch (InterruptedException ex) {}
872             } else {
873                 WinScrollbar initScrollbar = currentScrollbar;
874                 long targetTime = startTime + waitTime;
875                 long diff = targetTime - System.currentTimeMillis();
876 
877                 while (currentScrollbar == initScrollbar && diff > 0) {
878                     try { wait(diff); }
879                     catch (InterruptedException ex) {}
880                     diff = targetTime - System.currentTimeMillis();
881                 }
882 
883                 if (currentScrollbar != initScrollbar)
884                     scrolling = false;
885             }
886         }
887     }
888 
doScroll(WinScrollbar scrollbar, int action, int pos)889     private boolean doScroll(WinScrollbar scrollbar,
890 			     int action, int pos) {
891         boolean status = false;
892 
893         switch (action) {
894 	case LINEUP:
895             status = scrollbar.lineUp(pos);
896             break;
897 
898 	case LINEDOWN:
899             status = scrollbar.lineDown(pos);
900             break;
901 
902 	case PAGEUP:
903             if (continuePaging(scrollbar, action, pos)) {
904                 status = scrollbar.pageUp(pos);
905             } else {
906                 // Keep trying to scroll for the case
907                 // where the user drags
908                 // the mouse while paging.  We want to
909                 // track the drag position
910                 // in the direction of the original paging action.
911                 status = true;
912             }
913             break;
914 
915 	case PAGEDOWN:
916             if (continuePaging(scrollbar, action, pos)) {
917                 status = scrollbar.pageDown(pos);
918             } else {
919                 // Keep trying to scroll for the case
920                 // where the user drags
921                 // the mouse while paging.  We want to
922                 // track the drag position
923                 // in the direction of the original paging action.
924                 status = true;
925             }
926             break;
927 
928 	default:
929             break;
930         }
931 
932         return status;
933     }
934 
continuePaging(WinScrollbar scrollbar, int action, int pos)935     private boolean continuePaging(WinScrollbar scrollbar, int action,
936 				   int pos) {
937         boolean status = false;
938         int info[] = scrollbar.getDragBoxInfo();
939 
940         if (pos < info[0]) {
941             status = (action == PAGEUP);
942         } else if (pos >= info[0]+info[1]) {
943             status = (action == PAGEDOWN);
944         }
945 
946         return status;
947     }
948 }
949