2 // A drop-in replacement for the AWT scrollbar class, with callbacks
3 // and a nicer look. This scrollbar is typically used to display some
4 // fraction of a list of items, with values ranging from min to max.
5 // The lvisible parameter determines how many of the list are lvisible
6 // at any one time. The value of the scrollbar ranges from min to
7 // max-lvisible+1 (the highest position in the list to start displaying)
10 public class CbScrollbar extends Panel
12 static final int VERTICAL = 0;
13 static final int HORIZONTAL = 1;
14 CbScrollbarCallback callback; // who to call back to
15 boolean inside, indent;
16 int orient; // horizontal or vertical?
17 int value; // position
18 int lvisible; // the number of lines lvisible
19 int num; // total number of lines
20 int lineinc = 1; // how much the arrow buttons move by
21 Color lc1 = Util.light_edge, lc2 = Util.body, lc3 = Util.dark_edge;
22 Color hc1 = Util.light_edge_hi, hc2 = Util.body_hi, hc3 = Util.dark_edge_hi;
23 Color bc = Util.dark_bg;
24 int y1, y2, x1, x2, drag;
26 CbScrollbarArrow arrow1, arrow2;
28 CbScrollbar(int o, CbScrollbarCallback cb)
33 /**Create a new scrollbar
35 CbScrollbar(int o, int v, int vis, int n, CbScrollbarCallback cb)
41 if (orient == VERTICAL) {
42 add(arrow1 = new CbScrollbarArrow(this, 0));
43 add(arrow2 = new CbScrollbarArrow(this, 1));
46 add(arrow1 = new CbScrollbarArrow(this, 2));
47 add(arrow2 = new CbScrollbarArrow(this, 3));
51 /**Set the current scrollbar parameters
52 * @param v Current position
53 * @param vis Number of lines lvisible
54 * @param n Total number of lines
56 public void setValues(int v, int vis, int n)
61 if (lvisible > num) lvisible = num;
66 public int getValue() { return value; }
68 public void setValue(int v)
75 private void checkValue()
77 if (value < 0) value = 0;
78 else if (value > num-lvisible) value = num-lvisible;
81 public void paint(Graphics g)
84 int w = size().width, h = size().height;
85 boolean ins = inside && !(arrow1.inside || arrow2.inside);
86 Color c1 = ins ? hc1 : lc1, c2 = ins ? hc2 : lc2,
89 g.fillRect(0, 0, w, h);
91 g.drawLine(0, 0, w-1, 0); g.drawLine(0, 0, 0, h-1);
93 g.drawLine(w-1, h-1, w-1, 0); g.drawLine(w-1, h-1, 0, h-1);
95 if (orient == VERTICAL) {
98 y2 = w+va*(value+lvisible)/num-1;
100 g.fillRect(1, y1, w-2, y2-y1);
101 g.setColor(indent ? c3 : c1);
102 g.drawLine(1, y1, w-2, y1);
103 g.drawLine(1, y1, 1, y2-1);
104 g.setColor(indent ? c1 : c3);
105 g.drawLine(w-2, y2-1, w-2, y1);
106 g.drawLine(w-2, y2-1, 1, y2-1);
108 g.drawLine(w-3, y2-2, w-3, y1+1);
109 g.drawLine(w-3, y2-2, 2, y2-2);
112 else if (orient == HORIZONTAL) {
115 x2 = h+va*(value+lvisible)/num-1;
117 g.fillRect(x1, 1, x2-x1, h-2);
118 g.setColor(indent ? c3 : c1);
119 g.drawLine(x1, 1, x1, h-2);
120 g.drawLine(x1, 1, x2-1, 1);
121 g.setColor(indent ? c1 : c3);
122 g.drawLine(x2-1, h-2, x1, h-2);
123 g.drawLine(x2-1, h-2, x2-1, 1);
125 g.drawLine(x2-2, h-3, x1+1, h-3);
126 g.drawLine(x2-2, h-3, x2-2, 2);
131 /**Called by arrows to move the slider
133 void arrowClick(int d)
135 int oldvalue = value;
138 if (value != oldvalue) {
139 callback.moved(this, value);
144 public void reshape(int nx, int ny, int nw, int nh)
146 super.reshape(nx, ny, nw, nh);
147 if (orient == VERTICAL) {
148 arrow1.reshape(1, 1, nw-2, nw-1);
149 arrow2.reshape(1, nh-nw-1, nw-2, nw-1);
152 arrow1.reshape(1, 1, nh-1, nh-2);
153 arrow2.reshape(nw-nh-1, 1, nh-1, nh-2);
158 public Dimension preferredSize()
160 return orient==VERTICAL ? new Dimension(16, 100)
161 : new Dimension(100, 16);
164 public Dimension minimumSize()
166 return preferredSize();
169 public boolean mouseDown(Event e, int mx, int my)
171 if (orient == VERTICAL) {
172 // move up/down one page, or start dragging
173 if (my < y1) arrowClick(-lvisible);
174 else if (my > y2) arrowClick(lvisible);
182 // move left/right one page, or start dragging
183 if (mx < x1) arrowClick(-lvisible);
184 else if (mx > x2) arrowClick(lvisible);
194 public boolean mouseDrag(Event e, int mx, int my)
197 int w = size().width, h = size().height;
198 int oldvalue = value;
199 if (orient == VERTICAL) {
200 int va = h-w*2, ny = my-drag-w;
204 int va = w-h*2, nx = mx-drag-h;
208 if (value != oldvalue) {
209 callback.moving(this, value);
216 public boolean mouseUp(Event e, int mx, int my)
221 callback.moved(this, value);
228 public boolean mouseEnter(Event e, int mx, int my)
235 public boolean mouseExit(Event e, int mx, int my)
244 class CbScrollbarArrow extends Canvas implements Runnable
247 CbScrollbar scrollbar;
248 boolean inside, indent;
251 CbScrollbarArrow(CbScrollbar p, int m)
257 public void paint(Graphics g)
259 int w = size().width, h = size().height;
260 Color c1 = inside ? scrollbar.hc1 : scrollbar.lc1,
261 c2 = inside ? scrollbar.hc2 : scrollbar.lc2,
262 c3 = inside ? scrollbar.hc3 : scrollbar.lc3;
263 g.setColor(scrollbar.bc);
264 g.fillRect(0, 0, w, h);
265 int xp[] = new int[3], yp[] = new int[3];
266 // blank, dark, light
269 xp[0] = w/2; xp[1] = w-1; xp[2] = 0;
270 yp[0] = 0; yp[1] = h-1; yp[2] = h-1;
272 else if (mode == 1) {
274 xp[0] = 0; xp[1] = w/2; xp[2] = w-1;
275 yp[0] = 0; yp[1] = h-1; yp[2] = 0;
277 else if (mode == 2) {
279 xp[0] = 0; xp[1] = w-1; xp[2] = w-1;
280 yp[0] = h/2; yp[1] = h-1; yp[2] = 0;
282 else if (mode == 3) {
284 xp[0] = 0; xp[1] = w-1; xp[2] = 0;
285 yp[0] = 0; yp[1] = h/2; yp[2] = h-1;
288 g.fillPolygon(xp, yp, 3);
289 g.setColor(indent ? c1 : c3);
290 g.drawLine(xp[1], yp[1], xp[2], yp[2]);
291 g.setColor(indent ? c3 : c1);
292 g.drawLine(xp[0], yp[0], xp[2], yp[2]);
295 public boolean mouseDown(Event e, int mx, int my)
299 (th = new Thread(this)).start();
303 public boolean mouseUp(Event e, int mx, int my)
307 if (th != null) th.stop();
311 /**Thread for doing repeated scrolling
317 scrollbar.arrowClick(mode%2 == 0 ? -1 : 1);
318 try { Thread.sleep(stime); } catch(Exception e) { }
325 // CbScrollbarCallback
326 // Methods for reporting the movement of the scrollbar to another object
327 interface CbScrollbarCallback
329 /**Called when the scrollbar stops moving. This happens when an
330 * arrow is clicked, the scrollbar is moved by a page, or the user
331 * lets go of the scrollbar after dragging it.
332 * @param sb The scrollar that has been moved
333 * @param v The new value
335 void moved(CbScrollbar sb, int v);
337 /**Called upon every pixel movement of the scrollbar when it is
338 * being dragged, but NOT when moved() is called.
339 * @param sb The scrollar that has been moved
340 * @param v The new value
342 void moving(CbScrollbar sb, int v);