1 /*
2 * wmslib/src/but/slide.c, part of wmslib (Library functions)
3 * Copyright (C) 1994-1997 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #ifdef X11_DISP
10
11 #ifdef STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/slide.h>
28 #include <but/box.h>
29 #include <but/timer.h>
30
31
32 /**********************************************************************
33 * Data Types
34 **********************************************************************/
35 typedef struct Slide_struct {
36 int maxval;
37 int cval;
38 int size;
39 bool horiz;
40 bool grip;
41 int start_mloc, start_val, start_loc;
42 ButTimer *timer;
43 int timer_jump;
44 int oldcur;
45
46 /*
47 * Stuff calculated from dimensions.
48 * w and h are for a horizontal slider. Reverse for vertical!
49 */
50 int boxW, boxH, boxLoc;
51 int lastW, lastH;
52
53 ButOut (*callback)(But *but, int setting, bool newPress);
54 } Slide;
55
56
57 /**********************************************************************
58 * Forward Declarations
59 **********************************************************************/
60 static ButOut mmove(But *but, int x, int y);
61 static ButOut mleave(But *but);
62 static ButOut mpress(But *but, int butnum, int x, int y);
63 static ButOut mrelease(But *but, int butnum, int x, int y);
64 static void draw(But *but, int x, int y, int w, int h);
65 static ButOut destroy(But *but);
66 static void flags(But *but, uint flags);
67 static ButOut slide_now(ButTimer *bt);
68 static void specialDraw(But *but, Slide *slide, int x, int y, int w, int h);
69 static void drawNewLoc(But *but);
70 static void calcBoxLoc(But *but);
71
72
73 /**********************************************************************
74 * Globals
75 **********************************************************************/
76 static const ButAction action = {
77 mmove, mleave, mpress, mrelease,
78 NULL, NULL, draw, destroy, flags, NULL};
79
80
81 /**********************************************************************
82 * Functions
83 **********************************************************************/
butSlide_hCreate(ButOut (* func)(But * but,int setting,bool newPress),void * packet,ButWin * win,int layer,int flags,int maxval,int cval,int size)84 But *butSlide_hCreate(ButOut (*func)(But *but, int setting, bool newPress),
85 void *packet, ButWin *win, int layer, int flags,
86 int maxval, int cval, int size) {
87 Slide *slide;
88 But *but;
89
90 slide = wms_malloc(sizeof(Slide));
91 but = but_create(win, slide, &action);
92 but->uPacket = packet;
93 but->layer = layer;
94 but->flags = flags | BUT_OPAQUE;
95
96 slide->maxval = maxval;
97 slide->cval = cval;
98 slide->size = size;
99 slide->horiz = TRUE;
100 slide->grip = FALSE;
101 slide->start_mloc = 0;
102 slide->start_val = 0;
103 slide->start_loc = 0;
104 slide->timer = NULL;
105 slide->timer_jump = 0;
106 slide->oldcur = butCur_idle;
107 slide->boxW = slide->boxH = slide->boxLoc = 0;
108 slide->lastW = 0;
109 slide->lastH = 0;
110 slide->callback = func;
111 but_init(but);
112 return(but);
113 }
114
115
butSlide_vCreate(ButOut (* func)(But * but,int setting,bool newPress),void * packet,ButWin * win,int layer,int flags,int maxval,int cval,int size)116 But *butSlide_vCreate(ButOut (*func)(But *but, int setting, bool newPress),
117 void *packet, ButWin *win, int layer, int flags,
118 int maxval, int cval, int size) {
119 Slide *slide;
120 But *but;
121
122 slide = wms_malloc(sizeof(Slide));
123 but = but_create(win, slide, &action);
124 but->uPacket = packet;
125 but->layer = layer;
126 but->flags = flags | BUT_OPAQUE;
127
128 slide->maxval = maxval;
129 slide->cval = cval;
130 slide->size = size;
131 slide->horiz = FALSE;
132 slide->grip = FALSE;
133 slide->start_mloc = 0;
134 slide->start_val = 0;
135 slide->start_loc = 0;
136 slide->timer = NULL;
137 slide->timer_jump = 0;
138 slide->oldcur = butCur_idle;
139 slide->boxW = slide->boxH = slide->boxLoc = 0;
140 slide->lastW = 0;
141 slide->lastH = 0;
142 slide->callback = func;
143 but_init(but);
144 return(but);
145 }
146
147
butSlide_set(But * but,int maxval,int cval,int size)148 void butSlide_set(But *but, int maxval, int cval, int size) {
149 Slide *slide = but->iPacket;
150
151 assert(but->action == &action);
152 if (maxval == BUT_NOCHANGE)
153 maxval = slide->maxval;
154 if (cval == BUT_NOCHANGE)
155 cval = slide->cval;
156 if (size == BUT_NOCHANGE)
157 size = slide->size;
158 if ((maxval != slide->maxval) || (cval != slide->cval) ||
159 (size != slide->size)) {
160 slide->maxval = maxval;
161 slide->cval = cval;
162 slide->size = size;
163 drawNewLoc(but);
164 }
165 }
166
167
butSlide_get(But * but)168 int butSlide_get(But *but) {
169 Slide *slide = but->iPacket;
170
171 return(slide->cval);
172 }
173
174
destroy(But * but)175 static ButOut destroy(But *but) {
176 Slide *slide = but->iPacket;
177
178 if (slide->timer != NULL)
179 butTimer_destroy(slide->timer);
180 wms_free(slide);
181 return(0);
182 }
183
184
draw(But * but,int x,int y,int w,int h)185 static void draw(But *but, int x, int y, int w, int h) {
186 ButWin *win = but->win;
187 ButEnv *env = win->env;
188 Slide *slide = but->iPacket;
189 int bw = env->stdButBw;
190
191 if ((w != slide->lastW) || (h != slide->lastH))
192 calcBoxLoc(but);
193 but_drawBox(win, but->x,but->y, but->w,but->h, 1, bw,
194 BUT_SLEFT|BUT_SRIGHT, BUT_LIT, BUT_SHAD, None, None);
195 butEnv_setXFg(env, BUT_PBG);
196 XFillRectangle(env->dpy, win->win, env->gc, but->x+bw,but->y+bw,
197 but->w-2*bw, but->h-2*bw);
198 if (slide->horiz) {
199 but_drawBox(win, but->x+bw+slide->boxLoc, but->y+bw,
200 slide->boxW, slide->boxH,
201 but->flags & BUT_LOCKED, bw,
202 BUT_SLEFT|BUT_SRIGHT, BUT_LIT, BUT_SHAD, None, None);
203 butEnv_setXFg(env, BUT_BG);
204 XFillRectangle(env->dpy, win->win, env->gc,
205 but->x + bw*2 + slide->boxLoc, but->y + bw * 2,
206 slide->boxW - bw * 2, slide->boxH - bw * 2);
207 } else /* !but->horiz */ {
208 but_drawBox(win, but->x+bw, but->y+bw+slide->boxLoc,
209 slide->boxH, slide->boxW,
210 but->flags & BUT_LOCKED, bw,
211 BUT_SLEFT|BUT_SRIGHT, BUT_LIT, BUT_SHAD, None, None);
212 butEnv_setXFg(env, BUT_BG);
213 XFillRectangle(env->dpy, win->win, env->gc,
214 but->x + bw * 2, but->y + bw*2 + slide->boxLoc,
215 slide->boxH - bw * 2, slide->boxW - bw * 2);
216 }
217 }
218
219
calcBoxLoc(But * but)220 static void calcBoxLoc(But *but) {
221 Slide *slide = but->iPacket;
222 ButEnv *env = but->win->env;
223 int allW, allH;
224 int bw;
225
226 bw = butEnv_stdBw(env);
227 if (slide->horiz) {
228 allW = but->w - 2*bw;
229 allH = but->h - 2*bw;
230 } else {
231 allW = but->h - 2*bw;
232 allH = but->w - 2*bw;
233 }
234 if (allW <= allH) {
235 slide->boxW = allW;
236 slide->boxH = allH;
237 slide->boxLoc = 0;
238 } else {
239 slide->boxW = (slide->size * allW + (slide->size + slide->maxval) / 2) /
240 (slide->size + slide->maxval);
241 slide->boxH = allH;
242 if (slide->boxW < slide->boxH)
243 slide->boxW = slide->boxH;
244 if (slide->maxval == 0)
245 slide->boxLoc = 0;
246 else
247 slide->boxLoc = ((allW - slide->boxW) * slide->cval +
248 slide->maxval / 2) / slide->maxval;
249 }
250 slide->lastW = but->w;
251 slide->lastH = but->h;
252 }
253
254
drawNewLoc(But * but)255 static void drawNewLoc(But *but) {
256 ButEnv *env = but->win->env;
257 Slide *slide = but->iPacket;
258 int bw = env->stdButBw;
259 int boxW, boxH, boxLoc;
260 int oldW, oldLoc;
261
262 if ((but->w < 1) || (but->h < 1))
263 return;
264 oldW = slide->boxW;
265 oldLoc = slide->boxLoc;
266 calcBoxLoc(but);
267 boxW = slide->boxW;
268 boxH = slide->boxH;
269 boxLoc = slide->boxLoc;
270 if (boxLoc < oldLoc) {
271 specialDraw(but, slide, boxLoc + bw, bw,
272 oldLoc + bw - boxLoc, boxH);
273 } else if (boxLoc > oldLoc) {
274 specialDraw(but, slide, oldLoc + bw, bw,
275 boxLoc + bw - oldLoc, boxH);
276 }
277 if (boxLoc + boxW < oldLoc + oldW) {
278 specialDraw(but, slide, boxLoc + boxW, bw,
279 oldLoc + oldW + bw - boxLoc - boxW, boxH);
280 } else if (boxLoc + boxW > oldLoc + oldW) {
281 specialDraw(but, slide, oldLoc + oldW, bw,
282 boxLoc + boxW + bw - oldLoc - oldW, boxH);
283 }
284 }
285
286
specialDraw(But * but,Slide * slide,int x,int y,int w,int h)287 static void specialDraw(But *but, Slide *slide, int x, int y, int w, int h) {
288 if (slide->horiz) {
289 butWin_redraw(but->win, but->x + x, but->y + y, w, h);
290 } else {
291 butWin_redraw(but->win, but->x + y, but->y + x, h, w);
292 }
293 }
294
295
flags(But * but,uint flags)296 static void flags(But *but, uint flags) {
297 uint ofl = but->flags;
298
299 but->flags = flags;
300 if ((flags & (BUT_PRESSABLE|BUT_DRAWABLE|BUT_PRESSED|BUT_LOCKED)) !=
301 (ofl & (BUT_PRESSABLE|BUT_DRAWABLE|BUT_PRESSED|BUT_LOCKED)))
302 but_draw(but);
303 }
304
305
mmove(But * but,int x,int y)306 static ButOut mmove(But *but, int x, int y) {
307 ButOut retval = BUTOUT_CAUGHT;
308 int newflags = but->flags;
309 ButEnv *env = butWin_env(but_win(but));
310 Slide *slide = but->iPacket;
311 int newval, newloc, pitmax;
312 int newcur = butCur_idle;
313
314 if (slide->horiz) {
315 if ((newflags & BUT_LOCKED) && slide->grip) {
316 /* Slide it around! */
317 if (x == BUT_NOCHANGE)
318 return(retval);
319 newloc = x - slide->start_mloc + slide->start_loc;
320 if (newloc < 0)
321 newloc = 0;
322 pitmax = but->w - slide->boxW - env->stdButBw*2;
323 if (newloc > pitmax)
324 newloc = pitmax;
325 if (pitmax == 0)
326 newval = 0;
327 else
328 newval = (newloc * slide->maxval + pitmax/2) / pitmax;
329 if (newval != slide->cval) {
330 slide->cval = newval;
331 drawNewLoc(but);
332 if (slide->callback != NULL)
333 return(retval | slide->callback(but, slide->cval, FALSE));
334 }
335 return(retval);
336 }
337 if ((x >= but->x+env->stdButBw) && (x < but->x+but->w-env->stdButBw) &&
338 (y >= but->y+env->stdButBw) && (y < but->y+but->h-env->stdButBw)) {
339 newflags |= BUT_TWITCHED;
340 if (x < but->x + env->stdButBw + slide->boxLoc)
341 newcur = butCur_left;
342 else if (x < but->x + env->stdButBw + slide->boxLoc + slide->boxW)
343 newcur = butCur_lr;
344 else
345 newcur = butCur_right;
346 } else {
347 newflags &= ~BUT_TWITCHED;
348 if (!(newflags & BUT_LOCKED))
349 retval &= ~BUTOUT_CAUGHT;
350 }
351 if (!(newflags & BUT_LOCKED) && (newcur != slide->oldcur)) {
352 butEnv_setCursor(env, but, newcur);
353 slide->oldcur = newcur;
354 }
355 if (newflags != but->flags) {
356 but_newFlags(but, newflags);
357 }
358 return(retval);
359 } else /* !slide->horiz */ {
360 if ((newflags & BUT_LOCKED) && slide->grip) {
361 /* Slide it around! */
362 if (y == BUT_NOCHANGE)
363 return(retval);
364 newloc = y - slide->start_mloc + slide->start_loc;
365 if (newloc < 0)
366 newloc = 0;
367 pitmax = but->h - slide->boxW - env->stdButBw*2;
368 if (newloc > pitmax)
369 newloc = pitmax;
370 if (pitmax == 0)
371 newval = 0;
372 else
373 newval = (newloc * slide->maxval + pitmax/2) / pitmax;
374 if (newval != slide->cval) {
375 slide->cval = newval;
376 drawNewLoc(but);
377 if (slide->callback != NULL)
378 return(retval | slide->callback(but, slide->cval, FALSE));
379 }
380 return(retval);
381 }
382 if ((x >= but->x+env->stdButBw) && (x < but->x+but->w-env->stdButBw) &&
383 (y >= but->y+env->stdButBw) && (y < but->y+but->h-env->stdButBw)) {
384 newflags |= BUT_TWITCHED;
385 if (y < but->y + env->stdButBw + slide->boxLoc)
386 newcur = butCur_up;
387 else if (y < but->y + env->stdButBw + slide->boxLoc + slide->boxW)
388 newcur = butCur_ud;
389 else
390 newcur = butCur_down;
391 } else {
392 newflags &= ~BUT_TWITCHED;
393 if (!(newflags & BUT_LOCKED))
394 retval &= ~BUTOUT_CAUGHT;
395 }
396 if (!(newflags & BUT_LOCKED) && (newcur != slide->oldcur)) {
397 butEnv_setCursor(env, but, newcur);
398 slide->oldcur = newcur;
399 }
400 if (newflags != but->flags) {
401 but_newFlags(but, newflags);
402 }
403 return(retval);
404 }
405 }
406
407
mleave(But * but)408 static ButOut mleave(But *but) {
409 int newflags = but->flags;
410 Slide *slide = but->iPacket;
411
412 newflags &= ~BUT_TWITCHED;
413 butEnv_setCursor(but->win->env, but, butCur_idle);
414 slide->oldcur = butCur_idle;
415 if (newflags != but->flags) {
416 but_newFlags(but, newflags);
417 }
418 return(BUTOUT_CAUGHT);
419 }
420
421
mpress(But * but,int butnum,int x,int y)422 static ButOut mpress(But *but, int butnum, int x, int y) {
423 int retval = BUTOUT_CAUGHT, newflags = but->flags;
424 Slide *slide = but->iPacket;
425 ButEnv *env = but->win->env;
426
427 if (!newflags & BUT_TWITCHED)
428 retval &= ~BUTOUT_CAUGHT;
429 else {
430 if (slide->horiz) {
431 if (but->w <= but->h)
432 return(BUTOUT_CAUGHT | BUTOUT_ERR);
433 if (butnum == 1) {
434 newflags |= BUT_LOCKED;
435 if (x < but->x + env->stdButBw + slide->boxLoc) {
436 butSlide_startSlide(but, TRUE, -slide->size*2, FALSE);
437 } else if (x >= but->x + env->stdButBw + slide->boxLoc +
438 slide->boxW) {
439 butSlide_startSlide(but, TRUE, slide->size*2, FALSE);
440 } else {
441 /* The box has been "gripped." */
442 slide->grip = TRUE;
443 slide->start_mloc = x;
444 slide->start_loc = slide->boxLoc;
445 slide->start_val = slide->cval;
446 }
447 } else
448 return(BUTOUT_CAUGHT | BUTOUT_ERR);
449 } else /* !slide->horiz */ {
450 if (but->h <= but->w)
451 return(BUTOUT_CAUGHT | BUTOUT_ERR);
452 if (butnum == 1) {
453 newflags |= BUT_LOCKED;
454 if (y < but->y + env->stdButBw + slide->boxLoc) {
455 butSlide_startSlide(but, TRUE, -slide->size*2, FALSE);
456 } else if (y >= but->y + env->stdButBw + slide->boxLoc +
457 slide->boxW) {
458 butSlide_startSlide(but, TRUE, slide->size*2, FALSE);
459 } else {
460 /* The box has been "gripped." */
461 slide->grip = TRUE;
462 slide->start_mloc = y;
463 slide->start_loc = slide->boxLoc;
464 slide->start_val = slide->cval;
465 }
466 } else
467 return(BUTOUT_CAUGHT | BUTOUT_ERR);
468 }
469 snd_play(&but_downSnd);
470 if (newflags != but->flags)
471 but_newFlags(but, newflags);
472 if (slide->callback != NULL)
473 return(retval | slide->callback(but, slide->cval, TRUE));
474 }
475 return(retval);
476 }
477
478
butSlide_startSlide(But * but,bool pause,int ssize,bool propagate)479 void butSlide_startSlide(But *but, bool pause, int ssize, bool propagate) {
480 Slide *slide = but->iPacket;
481 struct timeval delay;
482 int atj;
483 bool skipTimer = FALSE;
484
485 if (slide->timer != NULL)
486 butTimer_destroy(slide->timer);
487 if (pause) {
488 slide->cval += ssize/2;
489 if (slide->cval <= 0) {
490 slide->cval = 0;
491 skipTimer = TRUE;
492 } else if (slide->cval >= slide->maxval - 1) {
493 slide->cval = slide->maxval - 1;
494 skipTimer = TRUE;
495 }
496 drawNewLoc(but);
497 if (propagate && slide->callback)
498 slide->callback(but, slide->cval, TRUE);
499 }
500 if (!skipTimer) {
501 slide->timer_jump = ssize;
502 if (pause) {
503 delay.tv_sec = 0;
504 delay.tv_usec = 500000;
505 } else {
506 delay.tv_sec = 0;
507 delay.tv_usec = 0;
508 }
509 if (slide->timer_jump > 0)
510 atj = slide->timer_jump;
511 else
512 atj = -slide->timer_jump;
513 slide->timer = butTimer_fCreate(NULL, but, delay, atj*2, FALSE, slide_now);
514 }
515
516 }
517
518
slide_now(ButTimer * bt)519 static ButOut slide_now(ButTimer *bt) {
520 But *but = bt->but;
521 Slide *slide = but->iPacket;
522
523 if (slide->timer_jump > 0) {
524 slide->cval += bt->eventNum;
525 if (slide->cval > slide->maxval) {
526 slide->cval = slide->maxval;
527 butTimer_destroy(bt);
528 slide->timer = NULL;
529 }
530 } else {
531 slide->cval -= bt->eventNum;
532 if (slide->cval < 0) {
533 slide->cval = 0;
534 butTimer_destroy(bt);
535 slide->timer = NULL;
536 }
537 }
538 bt->eventNum = 0;
539 drawNewLoc(but);
540 if (slide->callback != NULL)
541 return(slide->callback(but, slide->cval, FALSE));
542 return(0);
543 }
544
545
mrelease(But * but,int butnum,int x,int y)546 static ButOut mrelease(But *but, int butnum, int x, int y) {
547 ButOut retval = BUTOUT_CAUGHT;
548 uint newflags = but->flags;
549 Slide *slide = but->iPacket;
550
551 if (!newflags & BUT_TWITCHED)
552 butEnv_setCursor(but->win->env, but, slide->oldcur = butCur_idle);
553 if (slide->timer != NULL) {
554 butTimer_destroy(slide->timer);
555 slide->timer = NULL;
556 }
557 slide->grip = FALSE;
558 newflags &= ~BUT_LOCKED;
559 if (newflags != but->flags)
560 but_newFlags(but, newflags);
561 snd_play(&but_upSnd);
562 return(retval);
563 }
564
565
butSlide_stopSlide(But * but)566 void butSlide_stopSlide(But *but) {
567 Slide *slide = but->iPacket;
568
569 if (slide->timer) {
570 butTimer_destroy(slide->timer);
571 slide->timer = NULL;
572 }
573 }
574
575
576 #endif
577