initial checkin
[org.ibex.widgets.git] / src / ibex / lib / scrollbar.t
1 <!-- Copyleft 2004 - see COPYING for details [LGPL] -->
2
3 <ibex>
4     <meta:doc>
5         Author: Charles Goodwin
6     </meta:doc>
7
8     <ui:box>
9
10         // public variables
11         thisbox.amount;
12         thisbox.hide;
13         thisbox.page;
14         thisbox.shift;
15         thisbox.slave;
16         thisbox.smart;
17
18         // theme box variables
19         thisbox.th_back;
20         thisbox.th_next;
21         thisbox.th_thumb;
22         thisbox.th_track;
23
24         // private variables
25         var listeners = {};
26         var motion;
27         var movefun1 = function(v) { th_thumb.action = true; }
28         var movefun2 = function(v) { recall["track"] = th_track.mouse[pos]; }
29         var recall = {};
30         var percent;
31
32         // attempt to shift slave by given amount
33         shift ++= function(v) {
34             motion = true;
35             slave[0][pos] = ibex.math.min(0, ibex.math.max(slave[dim] - slave[0][dim], slave[0][pos] - v));
36             syncThumb();
37             motion = false;
38         }
39
40         // set up slave
41         slave ++= function(v) {
42             v.SizeChange ++= slaveFunc;
43             v[0].PosChange ++= slaveFunc;
44             v[0].SizeChange ++= slaveFunc;
45
46             cascade = v;
47             syncThumb();
48         }
49
50         smart ++= function(v) { cascade = v; syncThumb(); }
51
52         th_back ++= function(v) { v.action ++= function(w) { shift = -1*amount; } }
53         th_next ++= function(v) { v.action ++= function(w) { shift = amount; } }
54
55         th_track ++= function(v) {
56             v.action ++= function(w) {
57                 if (th_thumb[pos] > recall["track"]) shift = -1*page;
58                 else if (recall["track"] > th_thumb[pos] + th_thumb[dim]) shift = page; 
59             }
60
61             v.repeat ++= function(w) {
62                 if (w) { Move ++= movefun2; movefun2(); }
63                 else { Move --= movefun2; recall["track"] = null; }
64             }
65
66             v.SizeChange ++= function(w) { syncThumb(); }
67         }
68
69         th_thumb ++= function(v) {
70             v.action ++= function(w) {
71                 th_thumb[pos] = ibex.math.max(0,
72                                     ibex.math.min(th_track[dim] - th_thumb[dim],
73                                         recall["thumb"] + (surface.mouse[pos] - recall["start"])));
74                 syncSlave();
75             }
76
77             v.Press1 ++= function(w) {
78                 motion = true;
79                 recall["start"] = surface.mouse[pos];
80                 recall["thumb"] = th_thumb[pos];
81                 surface.Move ++= movefun1;
82                 surface.Release1 ++= function(w) {
83                     motion = false;
84                     surface.Move --= movefun1;
85                     surface.Release1 --= callee;
86                 }
87             }
88         }
89
90         // public functions
91
92         thisbox.addListener = function(v) {
93             listeners[v] = [v, v[0]];
94             v.SizeChange ++= listenerFunc;
95             v[0].PosChange ++= listenerFunc;
96             v[0].SizeChange ++= listenerFunc;
97             syncAllListeners();
98         }
99
100         thisbox.removeListener = function(v) {
101             if (listeners[v] != null) {
102                 listeners[v][0].SizeChange --= listenerFunc;
103                 listeners[v][1].PosChange --= listenerFunc;
104                 listeners[v][1].SizeChange --= listenerFunc;
105                 listeners[v] = null;
106             }
107         }
108
109         // sync functions
110
111         var syncAllListeners = function(v) {
112             if (motion) {
113                 for (key in listeners) {
114                     if (v == listeners[key][0]) continue;
115                     syncListener(listeners[key][0]);
116                 }
117             }
118         }
119
120         var syncListener = function(v) {
121             percent = slave[0][pos] / (slave[dim] - slave[0][dim]);
122             if (v and v[0]) v[0][pos] = percent * (v[dim] - v[0][dim]);
123         }
124
125         var syncSlave = function() {
126             if (slave) {
127                 percent = th_thumb[pos] / (th_track[dim] - th_thumb[dim]);
128                 slave[0][pos] = percent * (slave[dim] - slave[0][dim]);
129             }
130         }
131
132         var syncThumb = function() {
133             if (slave == null || slave[0] == null || slave[dim] >= slave[0][dim]) {
134                 if (enabled) enabled = false;
135                 th_thumb[dim] = th_track[dim];
136                 th_thumb[pos] = 0;
137             }
138             else {
139                 if (!enabled) enabled = true;
140                 th_thumb[dim] = ibex.math.min(th_track[dim], (slave[dim] / slave[0][dim]) * th_track[dim]);
141                 percent = slave[0][pos] / (slave[dim] - slave[0][dim]);
142                 th_thumb[pos] = ibex.math.max(0, (th_track[dim] - th_thumb[dim]) * percent);
143             }
144         }
145
146         // reusable functions
147
148         var listenerFunc = function(v) {
149             if (!motion and trapee.constrain) {
150                 motion = true;
151                 syncAllListeners(trapee);
152                 syncSlave();
153                 motion = false;
154             }
155         }
156
157         var slaveFunc = function(v) {
158             if (!motion) {
159                 motion = true;
160                 syncThumb();
161                 syncAllListeners();
162                 motion = false;
163             }
164         }
165
166     </ui:box>
167 </ibex>