2 # GADGETS/SLIDER.D - Slider Gadget
4 # Here is typical code creating a vertical and horizontal slider for an
5 # area. The main frame is required to be a window. The inner frame (frame2)
6 # may or may not be a window.
8 # sliderH.createSlider(frame, 0, 0, Frame.BELOW|Frame.FILLX);
9 # sliderV.createSlider(frame, 0, 0, Frame.RIGHT|Frame.FILLY);
10 # frame1.createFrame(frame, 0, 0,
11 # Frame.BODY|Frame.FILLX|Frame.FILLY|Frame.WINDOW);
12 # frame2.createFrame(frame1, 1000, 1000, Frame.BODY);
13 # sliderH->setBody(frame1, frame2);
14 # sliderV->setBody(frame1, frame2);
16 public subclass SliderFrame from Frame {
18 int spos; # slider position (x or y dep on expansionMode)
19 int slen; # size of slider
20 int upos; # start position in pixels
21 int umax; # maximum range in pixels
22 Point lpos; # last mouse event
23 Frame @obody; # window on world
24 Frame @ibody; # frame that needs to be scrolled
25 SliderFrame @other; # the other slider, if any
30 SliderFrame.createSlider(
31 lvalue SliderFrame @this,
38 # Minimum slider length in pixels
45 this.createFrame("slider", parent, w, h, mount);
50 this->refreshVisibleFrame();
55 SliderFrame.mouseMoved(Event @ev)
58 int rel; # relative movement on correct axis
59 int max; # maximum movement on correct axis
60 int adj; # out of bounds re-adjustment
62 switch(this.expansionMode & Frame.DIRMASK) {
66 # vertical slider on the left or right
68 rel = ev->pos.y - this.lpos.y;
69 max = this.bounds.h - 4;
74 # horizontal slider on the top or bottom
76 rel = ev->pos.x - this.lpos.x;
77 max = this.bounds.w - 4;
85 } else if (this.spos + this.slen > max) {
86 adj = max - (this.spos + this.slen);
89 # keep the mouse lpos in sync so if we go out of bounds
90 # and then move back the slider does not move until we
95 switch(this.expansionMode & Frame.DIRMASK) {
107 # If some movement occured calculate the user pixel position
108 # change and slide the window for real
110 if (rel + adj != 0 && this.obody != NULL && max > 0) {
111 int upos = this.spos * this.umax / max;
113 if (upos != this.upos) {
115 switch(this.expansionMode & Frame.DIRMASK) {
125 if (this.other != NULL) {
126 this.other->vpos = this.vpos;
128 if (this.ibody->expansionMode & Frame.WINDOW) {
129 this.ibody->vpos = this.vpos;
130 this.ibody->moveWindow();
132 this.ibody->pos = this.vpos;
133 this.ibody->clearArea(
136 this.obody->bounds.w,
137 this.obody->bounds.h);
138 # yuch. this is due to our wpos
139 # optimization. We need a way to
140 # regenerate the optimization on
141 # the fly to avoid having to recalc()
143 # XXX pos not good enough, clip area
144 # must also be cleaned up.
146 this.ibody->recalc();
148 this.refreshVisibleFrame();
156 SliderFrame.refreshBulk()
158 if (this.ibody->expansionMode & Frame.WINDOW) {
159 Frame @body = this.ibody;
161 this.ibody->moveWindow();
163 # XXX recalculate clip area
164 this.ibody->pos = this.vpos;
165 this.ibody->clearArea(-this.vpos.x, -this.vpos.y,
166 this.obody->bounds.w,
167 this.obody->bounds.h);
168 this.ibody->recalc();
174 SliderFrame.buttonPressed(Event @ev)
177 case Event.XK_Pointer_Button1:
178 if (this.mouseInBounds(ev)) {
179 this.holding = ev->keySym;
181 this.setMouseFocus();
183 this.refreshVisibleFrame();
185 case -Event.XK_Pointer_Button1:
186 if (this.holding != 0) {
188 this.refreshVisibleFrame();
189 this.clearMouseFocus();
199 * CALCULATEPOSITIONS()
201 * Intercept the recalculation sequence to adjust our parameters.
202 * This occurs when the windows are created or resized.
206 SliderFrame.frameGeometryChanged()
208 super.frameGeometryChanged();
209 if (this.ibody != NULL && this.obody != NULL)
210 this.setBody(this.obody, this.ibody);
215 SliderFrame.setBody(Frame @obody, Frame @ibody)
220 switch(this.expansionMode & Frame.DIRMASK) {
223 this.setBulk(ibody->bounds.h, doRefresh:0);
227 this.setBulk(ibody->bounds.w, doRefresh:0);
234 SliderFrame.setBulk(int umax, int doRefresh = 1)
240 switch(this.expansionMode & Frame.DIRMASK) {
243 max = this.bounds.h - 4;
244 if (this.obody != NULL)
245 bmax = this.obody->bounds.h;
247 bmax = this.bounds.h;
251 max = this.bounds.w - 4;
252 if (this.obody != NULL)
253 bmax = this.obody->bounds.w;
255 bmax = this.bounds.w;
259 if (this.umax != umax) {
260 this.spos = this.upos * max / umax;
263 this.slen = (max * bmax) / umax;
264 if (this.spos + this.slen > max) {
265 adj = max - (this.spos + this.slen);
269 this.refreshVisibleFrame();
276 SliderFrame.refreshFrame(int x, int y, int w, int h)
288 this.setBulk(this.umax, doRefresh : 0);
289 this.pen = this.mediumPen;
290 this.fillRect(0, 0, this.bounds.w, this.bounds.h);
291 this.drawShadowedBorder(0, 0, w, h, this.darkPen, this.lightPen);
293 if (this.holding == Event.XK_Pointer_Button1) {
295 pen2 = this.lightPen;
297 pen1 = this.lightPen;
300 switch(this.expansionMode & Frame.DIRMASK) {
303 this.drawShadowedBorder(2, this.spos + 2, w - 4,
304 this.slen, pen1, pen2);
305 this.pen = this.textPen;
306 this.fillRect(4, this.spos + 4, w - 8, this.slen - 4);
310 this.drawShadowedBorder(this.spos + 2, 2,
311 this.slen, h - 4, pen1, pen2);
312 this.pen = this.textPen;
313 this.fillRect(this.spos + 4, 4, this.slen - 4, h - 8);
316 # if (this.ibody != NULL) {
317 # Frame @body = this.ibody;
318 # if (body->expansionMode & Frame.CLIP) {
319 # body->expansionMode &= ~Frame.CLIP;
320 # this.refreshBulk();