1 /*
2 * IceWM
3 *
4 * Copyright (C) 1997-2002 Marko Macek
5 *
6 * ScrollBar
7 */
8 #include "config.h"
9 #include "yscrollbar.h"
10 #include "yxapp.h"
11 #include "yprefs.h"
12 #include "prefs.h"
13
14 static YColorName scrollBarBg(&clrScrollBar);
15 static YColorName scrollBarSlider(&clrScrollBarSlider);
16 static YColorName scrollBarButton(&clrScrollBarButton);
17 static YColorName scrollBarActiveArrow(&clrScrollBarArrow);
18 static YColorName scrollBarInactiveArrow(&clrScrollBarInactive);
19
20 lazy<YTimer> YScrollBar::fScrollTimer;
21
YScrollBar(Orientation anOrientation,YWindow * aParent)22 YScrollBar::YScrollBar(Orientation anOrientation, YWindow *aParent):
23 YWindow(aParent),
24 fOrientation(anOrientation),
25 fMaximum(0),
26 fMinimum(0),
27 fValue(0),
28 fVisibleAmount(0),
29 fUnitIncrement(1),
30 fBlockIncrement(1),
31 fScrollTo(goNone),
32 fGrabDelta(0),
33 fListener(nullptr),
34 fDNDScroll(false),
35 fConfigured(false),
36 fExposed(false)
37 {
38 setTitle("ScrollBar");
39 }
40
~YScrollBar()41 YScrollBar::~YScrollBar() {
42 if (fScrollTimer)
43 fScrollTimer->disableTimerListener(this);
44 }
45
enable()46 void YScrollBar::enable() {
47 if (visible() == false) {
48 show();
49 raise();
50 }
51 }
52
reverseVideo()53 void YScrollBar::reverseVideo() {
54 scrollBarBg.reverse();
55 scrollBarSlider.reverse();
56 scrollBarButton.reverse();
57 scrollBarActiveArrow.reverse();
58 scrollBarInactiveArrow.reverse();
59 }
60
background()61 YColor YScrollBar::background() {
62 return scrollBarBg;
63 }
64
setOrientation(Orientation anOrientation)65 void YScrollBar::setOrientation(Orientation anOrientation) {
66 if (anOrientation != fOrientation) {
67 fOrientation = anOrientation;
68 repaint();
69 }
70 }
71
setMaximum(int aMaximum)72 void YScrollBar::setMaximum(int aMaximum) {
73 if (aMaximum < fMinimum)
74 aMaximum = fMinimum;
75
76 if (aMaximum != fMaximum) {
77 fMaximum = aMaximum;
78 repaint();
79 }
80 }
81
setMinimum(int aMinimum)82 void YScrollBar::setMinimum(int aMinimum) {
83 if (aMinimum > fMaximum)
84 aMinimum = fMaximum;
85
86 if (aMinimum != fMinimum) {
87 fMinimum = aMinimum;
88 repaint();
89 }
90 }
91
setVisibleAmount(int aVisibleAmount)92 void YScrollBar::setVisibleAmount(int aVisibleAmount) {
93 if (fVisibleAmount > fMaximum - fMinimum)
94 fVisibleAmount = fMaximum - fMinimum;
95 if (fVisibleAmount < 0)
96 fVisibleAmount = 0;
97
98 if (aVisibleAmount != fVisibleAmount) {
99 fVisibleAmount = aVisibleAmount;
100 repaint();
101 }
102 }
103
setUnitIncrement(int anUnitIncrement)104 void YScrollBar::setUnitIncrement(int anUnitIncrement) {
105 fUnitIncrement = anUnitIncrement;
106 }
107
setBlockIncrement(int aBlockIncrement)108 void YScrollBar::setBlockIncrement(int aBlockIncrement) {
109 fBlockIncrement = aBlockIncrement;
110 }
111
setValue(int aValue)112 void YScrollBar::setValue(int aValue) {
113 if (aValue > fMaximum - fVisibleAmount)
114 aValue = fMaximum - fVisibleAmount;
115 if (aValue < fMinimum)
116 aValue = fMinimum;
117
118 if (aValue != fValue) {
119 fValue = aValue;
120 repaint();
121 }
122 }
123
setValues(int aValue,int aVisibleAmount,int aMin,int aMax)124 void YScrollBar::setValues(int aValue, int aVisibleAmount, int aMin, int aMax) {
125 int v = aValue;
126
127 if (aMax < aMin)
128 aMax = aMin;
129 if (aVisibleAmount > aMax - aMin)
130 aVisibleAmount = aMax - aMin;
131 if (aVisibleAmount < 0)
132 aVisibleAmount = 0;
133 if (aValue > aMax - aVisibleAmount)
134 aValue = aMax - aVisibleAmount;
135 if (aValue < aMin)
136 aValue = aMin;
137
138 if (aMax != fMaximum ||
139 aMin != fMinimum ||
140 aValue != fValue ||
141 aVisibleAmount != fVisibleAmount)
142 {
143 fMinimum = aMin;
144 fMaximum = aMax;
145 fValue = aValue;
146 fVisibleAmount = aVisibleAmount;
147 repaint();
148 if (v != fValue)
149 fListener->move(this, fValue);
150 }
151 }
152
getCoord(int & beg,int & end,int & min,int & max,int & nn)153 void YScrollBar::getCoord(int &beg, int &end, int &min, int &max, int &nn) {
154 int dd = (fMaximum - fMinimum);
155
156 if (fOrientation == Vertical) {
157 beg = scrollBarHeight;
158 end = height() - scrollBarHeight - 1;
159 } else {
160 beg = scrollBarHeight;
161 end = width() - scrollBarHeight - 1;
162 }
163
164 nn = end - beg;
165 if (dd <= 0) {
166 min = 0;
167 max = nn;
168 return ;
169 }
170 int aa = nn;
171 int vv = aa * fVisibleAmount / dd;
172 if (vv < SCROLLBAR_MIN) {
173 vv = SCROLLBAR_MIN;
174 aa = nn - vv;
175 if (aa < 0) aa = 0;
176 dd -= fVisibleAmount;
177 if (dd <= 0) {
178 min = 0;
179 max = nn;
180 return ;
181 }
182 }
183 if (vv > nn)
184 vv = nn;
185 min = aa * fValue / dd;
186 max = min + vv;
187 }
188
189 // !!!! TODO: Warp3, Warp4, Motif borders
190
paint(Graphics & g,const YRect &)191 void YScrollBar::paint(Graphics &g, const YRect &/*r*/) {
192 int beg, end, min, max, nn;
193
194 getCoord(beg, end, min, max, nn);
195
196 /// !!! optimize this
197 if (fOrientation == Vertical) { // ============================ vertical ===
198 const int y(beg + min), h(max - min);
199
200 g.setColor(scrollBarBg); // -------------------- background, buttons ---
201
202 switch(wmLook) {
203 case lookWin95:
204 g.fillRect(0, beg, width(), min);
205 g.fillRect(0, y + h + 2, width(), ::max(0, end - h - y - 1));
206
207 g.setColor(scrollBarButton);
208 g.drawBorderW(0, 0, width() - 1, beg - 1, fScrollTo != goUp);
209 g.fillRect(1, 1, width() - 3, beg - 3);
210
211 g.drawBorderW(0, end + 1, width() - 1, beg - 1, fScrollTo != goDown);
212 g.fillRect(1, end + 2, width() - 3, beg - 3);
213 break;
214
215 case lookWarp3:
216 g.fillRect(0, beg, width(), min);
217 g.fillRect(0, y + h + 2, width(), ::max(0, end - h - y - 1));
218
219 g.setColor(scrollBarButton);
220 g.draw3DRect(0, 0, width() - 1, beg - 1, fScrollTo != goUp);
221 g.fillRect(1, 1, width() - 2, beg - 2);
222
223 g.draw3DRect(0, end + 1, width() - 1, beg - 1, fScrollTo != goDown);
224 g.fillRect(1, end + 2, width() - 2, beg - 2);
225 break;
226
227 case lookNice:
228 case lookPixmap:
229 case lookWarp4:
230 g.draw3DRect(0, 0, width() - 1, height() - 1, false);
231 g.fillRect(1, beg, width() - 2, min);
232 g.fillRect(1, y + h + 1, width() - 2, ::max(0, end - h - y));
233
234 g.setColor(scrollBarButton);
235 g.drawBorderW(1, 1, width() - 3, beg - 2, fScrollTo != goUp);
236 g.fillRect(2, 2, width() - 5, beg - 4);
237
238 g.drawBorderW(1, end + 1, width() - 3, beg - 2, fScrollTo != goDown);
239 g.fillRect(2, end + 2, width() - 5, beg - 4);
240 break;
241
242 case lookMotif:
243 g.drawBorderW(0, 0, width() - 1, height() - 1, false);
244 g.fillRect(2, 2, width() - 3, y - 3);
245 g.drawLine(width() - 2, y - 1, width() - 2, y + h + 1);
246 g.fillRect(2, y + h + 2, width() - 3, height() - h - y - 3);
247 break;
248
249 case lookGtk:
250 g.drawBorderG(0, 0, width() - 1, height() - 1, false);
251 g.fillRect(2, 2, width() - 3, y - 3);
252 g.drawLine(width() - 2, y - 1, width() - 2, y + h + 1);
253 g.fillRect(2, y + h + 2, width() - 3, height() - h - y - 3);
254 break;
255
256 case lookFlat:
257 case lookMetal:
258 g.fillRect(0, beg, width(), min);
259 g.fillRect(0, y + h + 2, width(), end - h - y - 1);
260
261 g.setColor(scrollBarButton);
262 g.drawBorderM(0, 0, width() - 1, beg - 1, fScrollTo != goUp);
263 g.fillRect(2, 2, width() - 4, beg - 4);
264 g.drawBorderM(0, end + 1, width() - 1, beg - 1, fScrollTo != goDown);
265 g.fillRect(2, end + 3, width() - 4, beg - 4);
266 break;
267 }
268 // --------------------- upper arrow ---
269 g.setColor(fValue > fMinimum ? scrollBarActiveArrow
270 : scrollBarInactiveArrow);
271 switch(wmLook) {
272 case lookWin95:
273 case lookWarp3:
274 case lookWarp4:
275 g.drawArrow(Up, 3, (beg - width() + 10) / 2,
276 width() - 8, fScrollTo == goUp);
277 break;
278
279 case lookNice:
280 case lookPixmap:
281 g.drawArrow(Up, 4, (beg - width() + 10) / 2,
282 width() - 10, fScrollTo == goUp);
283 break;
284
285 case lookMotif:
286 case lookGtk:
287 g.drawArrow(Up, 2, 2, width() - 5, fScrollTo == goUp);
288 break;
289
290 case lookFlat:
291 case lookMetal:
292 g.drawArrow(Up, 4, (beg - width() + 12) / 2,
293 width() - 8, fScrollTo == goUp);
294 break;
295 }
296 // --------------------- lower arrow ---
297 g.setColor(fValue < fMaximum - fVisibleAmount ? scrollBarActiveArrow
298 : scrollBarInactiveArrow);
299 switch(wmLook) {
300 case lookWin95:
301 case lookWarp3:
302 case lookWarp4:
303 g.drawArrow(Down, 3, end + (beg - width() + 12) / 2,
304 width() - 8, fScrollTo == goDown);
305 break;
306
307 case lookNice:
308 case lookPixmap:
309 g.drawArrow(Down, 4, end + (beg - width() + 12) / 2,
310 width() - 10, fScrollTo == goDown);
311 break;
312
313 case lookMotif:
314 case lookGtk:
315 g.drawArrow(Down, 2, end + 2, width() - 5, fScrollTo == goDown);
316 break;
317
318 case lookFlat:
319 case lookMetal:
320 g.drawArrow(Down, 4, end + (beg - width() + 14) / 2,
321 width() - 8, fScrollTo == goDown);
322 break;
323 }
324
325 g.setColor(scrollBarSlider); // ----------------------------- slider ---
326
327 switch(wmLook) {
328 case lookWin95:
329 g.drawBorderW(0, y, width() - 1, h + 1, true);
330 g.fillRect(1, y + 1, width() - 3, h - 1);
331 break;
332
333 case lookWarp3:
334 g.draw3DRect(0, y, width() - 1, h + 1, true);
335 g.fillRect(1, y + 1, width() - 2, h);
336 break;
337
338 case lookNice:
339 case lookPixmap:
340 case lookWarp4:
341 g.drawBorderW(1, y, width() - 3, h, true);
342 g.fillRect(2, y + 1, width() - 5, h - 2);
343
344 g.setColor(scrollBarSlider->darker());
345 for (int hy = y + h / 2 - 6; hy < (y + h / 2 + 5); hy+= 2)
346 g.drawLine(4, hy, width() - 6, hy);
347 g.setColor(scrollBarSlider->brighter());
348 for (int hy = y + h / 2 - 5; hy < (y + h / 2 + 6); hy+= 2)
349 g.drawLine(4, hy, width() - 6, hy);
350 break;
351
352 case lookMotif:
353 g.drawBorderW(2, y - 1, width() - 5, h + 2, true);
354 g.fillRect(3, y, width() - 7, h);
355 break;
356
357 case lookGtk:
358 g.drawBorderG(2, y - 1, width() - 5, h + 2, true);
359 g.fillRect(3, y, width() - 7, h);
360 break;
361
362 case lookFlat:
363 case lookMetal:
364 g.drawBorderM(0, y, width() - 1, h + 1, true);
365 g.fillRect(2, y + 2, width() - 4, h - 2);
366 break;
367 }
368 } else { // ================================================= horizontal ===
369 const int x(beg + min), w(max - min);
370
371 g.setColor(scrollBarBg); // -------------------- background, buttons ---
372
373 switch(wmLook) {
374 case lookWin95:
375 g.fillRect(beg, 0, min, height());
376 g.fillRect(x + w + 2, 0, ::max(0, end - w - x - 1), height());
377
378 g.setColor(scrollBarButton);
379 g.drawBorderW(0, 0, beg - 1, height() - 1, fScrollTo != goUp);
380 g.fillRect(1, 1, beg - 3, height() - 3);
381
382 g.drawBorderW(end + 1, 0, beg - 1, height() - 1, fScrollTo != goDown);
383 g.fillRect(end + 2, 1, beg - 3, height() - 3);
384 break;
385
386 case lookWarp3:
387 g.fillRect(beg, 0, min, height());
388 g.fillRect(x + w + 2, 0, ::max(0, end - w - x - 1), height());
389
390 g.setColor(scrollBarButton);
391 g.draw3DRect(0, 0, beg - 1, height() - 1, fScrollTo != goUp);
392 g.fillRect(1, 1, beg - 2, height() - 2);
393
394 g.draw3DRect(end + 1, 0, beg - 1, height() - 1, fScrollTo != goDown);
395 g.fillRect(end + 2, 1, beg - 2, height() - 2);
396 break;
397
398 case lookNice:
399 case lookPixmap:
400 case lookWarp4:
401 g.draw3DRect(0, 0, width() - 1, height() - 1, false);
402 g.fillRect(beg, 1, min, height() - 2);
403 g.fillRect(x + w + 2, 1, ::max(0, end - w - x), height() - 2);
404
405 g.setColor(scrollBarButton);
406 g.drawBorderW(1, 1, beg - 2, height() - 3, fScrollTo != goUp);
407 g.fillRect(2, 2, beg - 4, height() - 5);
408
409 g.drawBorderW(end + 1, 1, beg - 2, height() - 3, fScrollTo != goDown);
410 g.fillRect(end + 2, 2, beg - 4, height() - 5);
411 break;
412
413 case lookMotif:
414 g.drawBorderW(0, 0, width() - 1, height() - 1, false);
415 g.fillRect(2, 2, x - 3, height() - 3);
416 g.drawLine(x - 1, height() - 2, x + w + 1, height() - 2);
417 g.fillRect(x + w + 2, 2, width() - w - x - 3, height() - 3);
418 break;
419
420 case lookGtk:
421 g.drawBorderG(0, 0, width() - 1, height() - 1, false);
422 g.fillRect(2, 2, x - 3, height() - 3);
423 g.drawLine(x - 1, height() - 2, x + w + 1, height() - 2);
424 g.fillRect(x + w + 2, 2, width() - w - x - 3, height() - 3);
425 break;
426
427 case lookFlat:
428 case lookMetal:
429 g.fillRect(beg, 0, min, height());
430 g.fillRect(x + w + 2, 0, end - w - x - 1, height());
431
432 g.setColor(scrollBarButton);
433 g.drawBorderM(0, 0, beg - 1, height() - 1, fScrollTo != goUp);
434 g.fillRect(2, 2, beg - 4, height() - 4);
435 g.drawBorderM(end + 1, 0, beg - 1, height() - 1, fScrollTo != goDown);
436 g.fillRect(end + 3, 2, beg - 4, height() - 4);
437 break;
438 }
439 // ---------------------- left arrow ---
440 g.setColor(fValue > fMinimum ? scrollBarActiveArrow
441 : scrollBarInactiveArrow);
442 switch(wmLook) {
443 case lookWin95:
444 case lookWarp3:
445 case lookWarp4:
446 g.drawArrow(Left, (beg - height() + 10) / 2, 3,
447 height() - 8, fScrollTo == goUp);
448 break;
449
450 case lookNice:
451 case lookPixmap:
452 g.drawArrow(Left, (beg - height() + 10) / 2, 4,
453 height() - 10, fScrollTo == goUp);
454 break;
455
456 case lookMotif:
457 case lookGtk:
458 g.drawArrow(Left, 2, 2, height() - 5, fScrollTo == goUp);
459 break;
460
461 case lookFlat:
462 case lookMetal:
463 g.drawArrow(Left, (beg - height() + 12) / 2, 4,
464 height() - 8, fScrollTo == goUp);
465 break;
466 }
467 // --------------------- right arrow ---
468 g.setColor(fValue < fMaximum - fVisibleAmount ? scrollBarActiveArrow
469 : scrollBarInactiveArrow);
470 switch(wmLook) {
471 case lookWin95:
472 case lookWarp3:
473 case lookWarp4:
474 g.drawArrow(Right, end + (beg - height() + 12) / 2, 3,
475 height() - 8, fScrollTo == goDown);
476 break;
477
478 case lookNice:
479 case lookPixmap:
480 g.drawArrow(Right, end + (beg - height() + 12) / 2, 4,
481 height() - 10, fScrollTo == goDown);
482 break;
483
484 case lookMotif:
485 case lookGtk:
486 g.drawArrow(Right, end + 2, 2, height() - 5,
487 fScrollTo == goDown);
488 break;
489
490 case lookFlat:
491 case lookMetal:
492 g.drawArrow(Right, end + (beg - height() + 14) / 2, 4,
493 height() - 8, fScrollTo == goDown);
494 break;
495 }
496
497 g.setColor(scrollBarSlider); // ----------------------------- slider ---
498
499 switch(wmLook) {
500 case lookWin95:
501 g.drawBorderW(x, 0, w + 1, height() - 1, true);
502 g.fillRect(x + 1, 1, w - 1, height() - 3);
503 break;
504
505 case lookWarp3:
506 g.draw3DRect(x, 0, w + 1, height() - 1, true);
507 g.fillRect(x + 1, 1, w, height() - 2);
508 break;
509
510 case lookNice:
511 case lookPixmap:
512 case lookWarp4:
513 g.drawBorderW(x, 1, w + 1, height() - 3, true);
514 g.fillRect(x + 1, 2, w - 1, height() - 5);
515
516 g.setColor(scrollBarSlider->darker());
517 for (int hx = x + w / 2 - 6; hx < (x + w / 2 + 5); hx+= 2)
518 g.drawLine(hx, 4, hx, height() - 6);
519 g.setColor(scrollBarSlider->brighter());
520 for (int hx = x + w / 2 - 5; hx < (x + w / 2 + 6); hx+= 2)
521 g.drawLine(hx, 4, hx, height() - 6);
522
523 break;
524
525 case lookMotif:
526 g.drawBorderW(x - 1, 2, w + 3, height() - 5, true);
527 g.fillRect(x, 3, w + 1, height() - 7);
528 break;
529
530 case lookGtk:
531 g.drawBorderG(x - 1, 2, w + 3, height() - 5, true);
532 g.fillRect(x, 3, w + 1, height() - 7);
533 break;
534
535 case lookFlat:
536 case lookMetal:
537 g.drawBorderM(x, 0, w + 1, height() - 1, true);
538 g.fillRect(x + 2, 2, w - 2, height() - 4);
539 break;
540 }
541 }
542 }
543
scroll(int delta)544 void YScrollBar::scroll(int delta) {
545 int fNewPos = fValue;
546
547 if (delta == 0)
548 return ;
549
550 fNewPos += delta;
551
552 if (fNewPos >= fMaximum - fVisibleAmount)
553 fNewPos = fMaximum - fVisibleAmount;
554 if (fNewPos < fMinimum)
555 fNewPos = fMinimum;
556 if (fNewPos != fValue) {
557 delta = fNewPos - fValue;
558 fValue = fNewPos;
559 repaint();
560 fListener->scroll(this, delta);
561 }
562 }
563
move(int pos)564 void YScrollBar::move(int pos) {
565 int fNewPos = pos;
566
567 if (fNewPos >= fMaximum - fVisibleAmount)
568 fNewPos = fMaximum - fVisibleAmount;
569 if (fNewPos < fMinimum)
570 fNewPos = fMinimum;
571 if (fValue != fNewPos) {
572 fValue = fNewPos;
573 repaint();
574 fListener->move(this, fValue);
575 }
576 }
577
handleButton(const XButtonEvent & button)578 void YScrollBar::handleButton(const XButtonEvent &button) {
579 if (handleScrollMouse(button) == true)
580 return ;
581
582 if (button.button != Button1)
583 return ;
584
585 if (fMinimum >= fMaximum)
586 return ;
587
588 if (button.type == ButtonPress) {
589 fScrollTo = getOp(button.x, button.y);
590 doScroll();
591 fScrollTimer->setTimer(scrollBarStartDelay, this, true);
592 repaint();
593 } else if (button.type == ButtonRelease) {
594 fScrollTo = goNone;
595 if (fScrollTimer)
596 fScrollTimer->disableTimerListener(this);
597 repaint();
598 }
599 }
600
handleMotion(const XMotionEvent & motion)601 void YScrollBar::handleMotion(const XMotionEvent &motion) {
602 if (xapp->buttonMask(motion.state) != Button1Mask)
603 return;
604
605 if (fOrientation == Vertical) {
606 int h = height() - 2 * width();
607
608 if (h <= 0 || fMinimum >= fMaximum)
609 return ;
610
611 if (fScrollTo == goPosition) {
612 int y = motion.y - fGrabDelta - width();
613 if (y < 0) y = 0;
614 int pos = y * (fMaximum - fMinimum) / h;
615 move(pos);
616 }
617 } else {
618 int w = width() - 2 * height();
619
620 if (w <= 0 || fMinimum >= fMaximum)
621 return ;
622
623 if (fScrollTo == goPosition) {
624 int x = motion.x - fGrabDelta - height();
625 if (x < 0) x = 0;
626 int pos = x * (fMaximum - fMinimum) / w;
627 move(pos);
628 }
629 }
630 }
631
handleScrollKeys(const XKeyEvent & key)632 bool YScrollBar::handleScrollKeys(const XKeyEvent &key) {
633 if (key.type == KeyPress) {
634 KeySym k = keyCodeToKeySym(key.keycode);
635 int m = KEY_MODMASK(key.state);
636
637 if (fOrientation == Vertical) {
638 switch (k) {
639 case XK_Up:
640 case XK_KP_Up:
641 if (m == 0) {
642 scroll(-fUnitIncrement);
643 return true;
644 }
645 if (m == ShiftMask) {
646 scroll(-fUnitIncrement * 4);
647 return true;
648 }
649 if (m == ControlMask) {
650 scroll(-fUnitIncrement * 16);
651 return true;
652 }
653 break;
654 case XK_Home:
655 case XK_KP_Home:
656 if (m == 0) {
657 move(0);
658 return true;
659 }
660 break;
661 case XK_Prior:
662 case XK_KP_Prior:
663 if (m == ControlMask) {
664 move(0);
665 return true;
666 }
667 if (m == ShiftMask) {
668 scroll(-fBlockIncrement * 4);
669 return true;
670 }
671 if (m == 0) {
672 scroll(-fBlockIncrement);
673 return true;
674 }
675 break;
676 case XK_Down:
677 case XK_KP_Down:
678 if (m == 0) {
679 scroll(+fUnitIncrement);
680 return true;
681 }
682 if (m == ShiftMask) {
683 scroll(+fUnitIncrement * 4);
684 return true;
685 }
686 if (m == ControlMask) {
687 scroll(+fUnitIncrement * 16);
688 return true;
689 }
690 break;
691 case XK_End:
692 case XK_KP_End:
693 if (m == 0) {
694 move(fMaximum - fVisibleAmount);
695 return true;
696 }
697 break;
698 case XK_Next:
699 case XK_KP_Next:
700 if (m == ControlMask) {
701 move(fMaximum - fVisibleAmount);
702 return true;
703 }
704 if (m == ShiftMask) {
705 scroll(+fBlockIncrement * 4);
706 return true;
707 }
708 if (m == 0) {
709 scroll(+fBlockIncrement);
710 return true;
711 }
712 break;
713 default:
714 break;
715 }
716 }
717 else if (m == 0 && fOrientation == Horizontal) {
718 switch (k) {
719 case XK_Left:
720 case XK_KP_Left:
721 scroll(-fUnitIncrement);
722 return true;
723 case XK_Right:
724 case XK_KP_Right:
725 scroll(+fUnitIncrement);
726 return true;
727 case XK_Home:
728 case XK_KP_Home:
729 move(0);
730 return true;
731 case XK_End:
732 case XK_KP_End:
733 move(fMaximum - fVisibleAmount);
734 return true;
735 default:
736 break;
737 }
738 }
739 }
740 return false;
741 }
742
handleScrollMouse(const XButtonEvent & button)743 bool YScrollBar::handleScrollMouse(const XButtonEvent &button) {
744 if (button.type == ButtonPress) {
745 if (button.button == Button4) {
746 scroll(-fBlockIncrement);
747 return true;
748 } else if (button.button == Button5) {
749 scroll(+fBlockIncrement);
750 return true;
751 }
752 }
753 return false;
754 }
755
doScroll()756 void YScrollBar::doScroll() {
757 switch (fScrollTo) {
758 case goNone:
759 break;
760 case goUp:
761 scroll(-fUnitIncrement);
762 break;
763 case goDown:
764 scroll(+fUnitIncrement);
765 break;
766 case goPageUp:
767 scroll(-fBlockIncrement);
768 break;
769 case goPageDown:
770 scroll(+fBlockIncrement);
771 break;
772 case goPosition:
773 break;
774 }
775 }
776
handleTimer(YTimer * timer)777 bool YScrollBar::handleTimer(YTimer *timer) {
778 if (timer != fScrollTimer)
779 return false;
780 doScroll();
781 if (!fDNDScroll || (fScrollTo != goPageUp && fScrollTo != goPageDown))
782 timer->setInterval(scrollBarDelay);
783 return true;
784 }
785
getOp(int x,int y)786 YScrollBar::ScrollOp YScrollBar::getOp(int x, int y) {
787 int beg, end, min, max, nn;
788 ScrollOp fScrollTo;
789
790 getCoord(beg, end, min, max, nn);
791
792 fScrollTo = goNone;
793 if (fOrientation == Vertical) {
794
795 if (y > end) {
796 if (fValue < fMaximum - fVisibleAmount)
797 fScrollTo = goDown;
798 } else if (y < beg) {
799 if (fValue > 0)
800 fScrollTo = goUp;
801 } else {
802 if (y < beg + min) {
803 fScrollTo = goPageUp;
804 } else if (y > beg + max) {
805 fScrollTo = goPageDown;
806 } else {
807 fScrollTo = goPosition;
808 fGrabDelta = y - min - beg;
809 }
810 }
811 } else {
812 if (x > end) {
813 if (fValue < fMaximum - fVisibleAmount)
814 fScrollTo = goDown;
815 } else if (x < beg) {
816 if (fValue > 0)
817 fScrollTo = goUp;
818 } else {
819 if (x < beg + min) {
820 fScrollTo = goPageUp;
821 } else if (x > beg + max) {
822 fScrollTo = goPageDown;
823 } else {
824 fScrollTo = goPosition;
825 fGrabDelta = x - min - beg;
826 }
827 }
828 }
829 return fScrollTo;
830 }
831
handleDNDEnter()832 void YScrollBar::handleDNDEnter() {
833 fScrollTo = goNone;
834 fDNDScroll = true;
835 if (fScrollTimer)
836 fScrollTimer->disableTimerListener(this);
837 }
838
handleDNDLeave()839 void YScrollBar::handleDNDLeave() {
840 fScrollTo = goNone;
841 fDNDScroll = false;
842 repaint();
843 if (fScrollTimer)
844 fScrollTimer->disableTimerListener(this);
845 }
846
handleDNDPosition(int x,int y)847 void YScrollBar::handleDNDPosition(int x, int y) {
848 fScrollTo = getOp(x, y);
849 fScrollTimer->setTimer(scrollBarStartDelay, this, true);
850 repaint();
851 }
852
configure(const YRect2 & r)853 void YScrollBar::configure(const YRect2& r) {
854 if (r.width() > 1 && r.height() > 1) {
855 fConfigured = true;
856 repaint();
857 }
858 }
859
handleExpose(const XExposeEvent & expose)860 void YScrollBar::handleExpose(const XExposeEvent &expose) {
861 if (fExposed == false && expose.count == 0) {
862 fExposed = true;
863 repaint();
864 }
865 }
866
repaint()867 void YScrollBar::repaint() {
868 if (fConfigured && fExposed) {
869 GraphicsBuffer(this).paint();
870 }
871 }
872
873 // vim: set sw=4 ts=4 et:
874