Bug fixes
[fanfix.git] / src / jexer / TScrollableWindow.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2017 Kevin Lamonte
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29 package jexer;
30
31 import jexer.event.TMouseEvent;
32 import jexer.event.TResizeEvent;
33
34 /**
35 * TScrollableWindow is a convenience superclass for windows that have
36 * scrollbars.
37 */
38 public class TScrollableWindow extends TWindow implements Scrollable {
39
40 /**
41 * The horizontal scrollbar.
42 */
43 protected THScroller hScroller = null;
44
45 /**
46 * The vertical scrollbar.
47 */
48 protected TVScroller vScroller = null;
49
50 /**
51 * Place the scrollbars on the edge of this widget, and adjust bigChange
52 * to match the new size. This is called by onResize().
53 */
54 protected void placeScrollbars() {
55 if (hScroller != null) {
56 hScroller.setY(getHeight() - 2);
57 hScroller.setWidth(getWidth() - hScroller.getX() - 3);
58 hScroller.setBigChange(getWidth() - hScroller.getX() - 3);
59 }
60 if (vScroller != null) {
61 vScroller.setX(getWidth() - 2);
62 vScroller.setHeight(getHeight() - 2);
63 vScroller.setBigChange(getHeight() - 2);
64 }
65 }
66
67 /**
68 * Recompute whatever data is displayed by this widget.
69 */
70 public void reflowData() {
71 // Default: nothing to do
72 }
73
74 /**
75 * Handle window/screen resize events.
76 *
77 * @param event resize event
78 */
79 @Override
80 public void onResize(final TResizeEvent event) {
81 if (event.getType() == TResizeEvent.Type.WIDGET) {
82 reflowData();
83 placeScrollbars();
84 return;
85 } else {
86 super.onResize(event);
87 }
88 }
89
90 /**
91 * Public constructor. Window will be located at (0, 0).
92 *
93 * @param application TApplication that manages this window
94 * @param title window title, will be centered along the top border
95 * @param width width of window
96 * @param height height of window
97 */
98 public TScrollableWindow(final TApplication application, final String title,
99 final int width, final int height) {
100
101 super(application, title, width, height);
102 }
103
104 /**
105 * Public constructor. Window will be located at (0, 0).
106 *
107 * @param application TApplication that manages this window
108 * @param title window title, will be centered along the top border
109 * @param width width of window
110 * @param height height of window
111 * @param flags bitmask of RESIZABLE, CENTERED, or MODAL
112 */
113 public TScrollableWindow(final TApplication application, final String title,
114 final int width, final int height, final int flags) {
115
116 super(application, title, width, height, flags);
117 }
118
119 /**
120 * Public constructor.
121 *
122 * @param application TApplication that manages this window
123 * @param title window title, will be centered along the top border
124 * @param x column relative to parent
125 * @param y row relative to parent
126 * @param width width of window
127 * @param height height of window
128 */
129 public TScrollableWindow(final TApplication application, final String title,
130 final int x, final int y, final int width, final int height) {
131
132 super(application, title, x, y, width, height);
133 }
134
135 /**
136 * Public constructor.
137 *
138 * @param application TApplication that manages this window
139 * @param title window title, will be centered along the top border
140 * @param x column relative to parent
141 * @param y row relative to parent
142 * @param width width of window
143 * @param height height of window
144 * @param flags mask of RESIZABLE, CENTERED, or MODAL
145 */
146 public TScrollableWindow(final TApplication application, final String title,
147 final int x, final int y, final int width, final int height,
148 final int flags) {
149
150 super(application, title, x, y, width, height, flags);
151 }
152
153 /**
154 * Get the horizontal scrollbar, or null if this Viewport does not
155 * support horizontal scrolling.
156 *
157 * @return the horizontal scrollbar
158 */
159 public THScroller getHorizontalScroller() {
160 return hScroller;
161 }
162
163 /**
164 * Get the vertical scrollbar, or null if this Viewport does not support
165 * vertical scrolling.
166 *
167 * @return the vertical scrollbar
168 */
169 public TVScroller getVerticalScroller() {
170 return vScroller;
171 }
172
173 /**
174 * Get the value that corresponds to being on the top edge of the
175 * vertical scroll bar.
176 *
177 * @return the scroll value
178 */
179 public int getTopValue() {
180 if (vScroller == null) {
181 return 0;
182 } else {
183 return vScroller.getTopValue();
184 }
185 }
186
187 /**
188 * Set the value that corresponds to being on the top edge of the
189 * vertical scroll bar.
190 *
191 * @param topValue the new scroll value
192 */
193 public void setTopValue(final int topValue) {
194 if (vScroller == null) {
195 return;
196 } else {
197 vScroller.setTopValue(topValue);
198 }
199 }
200
201 /**
202 * Get the value that corresponds to being on the bottom edge of the
203 * vertical scroll bar.
204 *
205 * @return the scroll value
206 */
207 public int getBottomValue() {
208 if (vScroller == null) {
209 return 0;
210 } else {
211 return vScroller.getBottomValue();
212 }
213 }
214
215 /**
216 * Set the value that corresponds to being on the bottom edge of the
217 * vertical scroll bar.
218 *
219 * @param bottomValue the new scroll value
220 */
221 public void setBottomValue(final int bottomValue) {
222 if (vScroller == null) {
223 return;
224 } else {
225 vScroller.setBottomValue(bottomValue);
226 }
227 }
228
229 /**
230 * Get current value of the vertical scroll.
231 *
232 * @return the scroll value
233 */
234 public int getVerticalValue() {
235 if (vScroller == null) {
236 return 0;
237 } else {
238 return vScroller.getValue();
239 }
240 }
241
242 /**
243 * Set current value of the vertical scroll.
244 *
245 * @param value the new scroll value
246 */
247 public void setVerticalValue(final int value) {
248 if (vScroller == null) {
249 return;
250 } else {
251 vScroller.setValue(value);
252 }
253 }
254
255 /**
256 * Get the increment for clicking on an arrow on the vertical scrollbar.
257 *
258 * @return the increment value
259 */
260 public int getVerticalSmallChange() {
261 if (vScroller == null) {
262 return 0;
263 } else {
264 return vScroller.getSmallChange();
265 }
266 }
267
268 /**
269 * Set the increment for clicking on an arrow on the vertical scrollbar.
270 *
271 * @param smallChange the new increment value
272 */
273 public void setVerticalSmallChange(final int smallChange) {
274 if (vScroller == null) {
275 return;
276 } else {
277 vScroller.setSmallChange(smallChange);
278 }
279 }
280
281 /**
282 * Get the increment for clicking in the bar between the box and an
283 * arrow on the vertical scrollbar.
284 *
285 * @return the increment value
286 */
287 public int getVerticalBigChange() {
288 if (vScroller == null) {
289 return 0;
290 } else {
291 return vScroller.getBigChange();
292 }
293 }
294
295 /**
296 * Set the increment for clicking in the bar between the box and an
297 * arrow on the vertical scrollbar.
298 *
299 * @param bigChange the new increment value
300 */
301 public void setVerticalBigChange(final int bigChange) {
302 if (vScroller == null) {
303 return;
304 } else {
305 vScroller.setBigChange(bigChange);
306 }
307 }
308
309 /**
310 * Perform a small step change up.
311 */
312 public void verticalDecrement() {
313 if (vScroller == null) {
314 return;
315 } else {
316 vScroller.decrement();
317 }
318 }
319
320 /**
321 * Perform a small step change down.
322 */
323 public void verticalIncrement() {
324 if (vScroller == null) {
325 return;
326 } else {
327 vScroller.increment();
328 }
329 }
330
331 /**
332 * Perform a big step change up.
333 */
334 public void bigVerticalDecrement() {
335 if (vScroller == null) {
336 return;
337 } else {
338 vScroller.bigDecrement();
339 }
340 }
341
342 /**
343 * Perform a big step change down.
344 */
345 public void bigVerticalIncrement() {
346 if (vScroller == null) {
347 return;
348 } else {
349 vScroller.bigIncrement();
350 }
351 }
352
353 /**
354 * Go to the top edge of the vertical scroller.
355 */
356 public void toTop() {
357 if (vScroller == null) {
358 return;
359 } else {
360 vScroller.toTop();
361 }
362 }
363
364 /**
365 * Go to the bottom edge of the vertical scroller.
366 */
367 public void toBottom() {
368 if (vScroller == null) {
369 return;
370 } else {
371 vScroller.toBottom();
372 }
373 }
374
375 /**
376 * Get the value that corresponds to being on the left edge of the
377 * horizontal scroll bar.
378 *
379 * @return the scroll value
380 */
381 public int getLeftValue() {
382 if (hScroller == null) {
383 return 0;
384 } else {
385 return hScroller.getLeftValue();
386 }
387 }
388
389 /**
390 * Set the value that corresponds to being on the left edge of the
391 * horizontal scroll bar.
392 *
393 * @param leftValue the new scroll value
394 */
395 public void setLeftValue(final int leftValue) {
396 if (hScroller == null) {
397 return;
398 } else {
399 hScroller.setLeftValue(leftValue);
400 }
401 }
402
403 /**
404 * Get the value that corresponds to being on the right edge of the
405 * horizontal scroll bar.
406 *
407 * @return the scroll value
408 */
409 public int getRightValue() {
410 if (hScroller == null) {
411 return 0;
412 } else {
413 return hScroller.getRightValue();
414 }
415 }
416
417 /**
418 * Set the value that corresponds to being on the right edge of the
419 * horizontal scroll bar.
420 *
421 * @param rightValue the new scroll value
422 */
423 public void setRightValue(final int rightValue) {
424 if (hScroller == null) {
425 return;
426 } else {
427 hScroller.setRightValue(rightValue);
428 }
429 }
430
431 /**
432 * Get current value of the horizontal scroll.
433 *
434 * @return the scroll value
435 */
436 public int getHorizontalValue() {
437 if (hScroller == null) {
438 return 0;
439 } else {
440 return hScroller.getValue();
441 }
442 }
443
444 /**
445 * Set current value of the horizontal scroll.
446 *
447 * @param value the new scroll value
448 */
449 public void setHorizontalValue(final int value) {
450 if (hScroller == null) {
451 return;
452 } else {
453 hScroller.setValue(value);
454 }
455 }
456
457 /**
458 * Get the increment for clicking on an arrow on the horizontal
459 * scrollbar.
460 *
461 * @return the increment value
462 */
463 public int getHorizontalSmallChange() {
464 if (hScroller == null) {
465 return 0;
466 } else {
467 return hScroller.getSmallChange();
468 }
469 }
470
471 /**
472 * Set the increment for clicking on an arrow on the horizontal
473 * scrollbar.
474 *
475 * @param smallChange the new increment value
476 */
477 public void setHorizontalSmallChange(final int smallChange) {
478 if (hScroller == null) {
479 return;
480 } else {
481 hScroller.setSmallChange(smallChange);
482 }
483 }
484
485 /**
486 * Get the increment for clicking in the bar between the box and an
487 * arrow on the horizontal scrollbar.
488 *
489 * @return the increment value
490 */
491 public int getHorizontalBigChange() {
492 if (hScroller == null) {
493 return 0;
494 } else {
495 return hScroller.getBigChange();
496 }
497 }
498
499 /**
500 * Set the increment for clicking in the bar between the box and an
501 * arrow on the horizontal scrollbar.
502 *
503 * @param bigChange the new increment value
504 */
505 public void setHorizontalBigChange(final int bigChange) {
506 if (hScroller == null) {
507 return;
508 } else {
509 hScroller.setBigChange(bigChange);
510 }
511 }
512
513 /**
514 * Perform a small step change left.
515 */
516 public void horizontalDecrement() {
517 if (hScroller == null) {
518 return;
519 } else {
520 hScroller.decrement();
521 }
522 }
523
524 /**
525 * Perform a small step change right.
526 */
527 public void horizontalIncrement() {
528 if (hScroller == null) {
529 return;
530 } else {
531 hScroller.increment();
532 }
533 }
534
535 /**
536 * Perform a big step change left.
537 */
538 public void bigHorizontalDecrement() {
539 if (hScroller == null) {
540 return;
541 } else {
542 hScroller.bigDecrement();
543 }
544 }
545
546 /**
547 * Perform a big step change right.
548 */
549 public void bigHorizontalIncrement() {
550 if (hScroller == null) {
551 return;
552 } else {
553 hScroller.bigIncrement();
554 }
555 }
556
557 /**
558 * Go to the left edge of the horizontal scroller.
559 */
560 public void toLeft() {
561 if (hScroller == null) {
562 return;
563 } else {
564 hScroller.toLeft();
565 }
566 }
567
568 /**
569 * Go to the right edge of the horizontal scroller.
570 */
571 public void toRight() {
572 if (hScroller == null) {
573 return;
574 } else {
575 hScroller.toRight();
576 }
577 }
578
579 /**
580 * Go to the top-left edge of the horizontal and vertical scrollers.
581 */
582 public void toHome() {
583 if (hScroller != null) {
584 hScroller.toLeft();
585 }
586 if (vScroller != null) {
587 vScroller.toTop();
588 }
589 }
590
591 /**
592 * Go to the bottom-right edge of the horizontal and vertical scrollers.
593 */
594 public void toEnd() {
595 if (hScroller != null) {
596 hScroller.toRight();
597 }
598 if (vScroller != null) {
599 vScroller.toBottom();
600 }
601 }
602
603 /**
604 * Check if a mouse press/release/motion event coordinate is over the
605 * vertical scrollbar.
606 *
607 * @param mouse a mouse-based event
608 * @return whether or not the mouse is on the scrollbar
609 */
610 protected final boolean mouseOnVerticalScroller(final TMouseEvent mouse) {
611 if (vScroller == null) {
612 return false;
613 }
614 if ((mouse.getAbsoluteX() == vScroller.getAbsoluteX())
615 && (mouse.getAbsoluteY() >= vScroller.getAbsoluteY())
616 && (mouse.getAbsoluteY() < vScroller.getAbsoluteY() +
617 vScroller.getHeight())
618 ) {
619 return true;
620 }
621 return false;
622 }
623
624 /**
625 * Check if a mouse press/release/motion event coordinate is over the
626 * horizontal scrollbar.
627 *
628 * @param mouse a mouse-based event
629 * @return whether or not the mouse is on the scrollbar
630 */
631 protected final boolean mouseOnHorizontalScroller(final TMouseEvent mouse) {
632 if (hScroller == null) {
633 return false;
634 }
635 if ((mouse.getAbsoluteY() == hScroller.getAbsoluteY())
636 && (mouse.getAbsoluteX() >= hScroller.getAbsoluteX())
637 && (mouse.getAbsoluteX() < hScroller.getAbsoluteX() +
638 hScroller.getWidth())
639 ) {
640 return true;
641 }
642 return false;
643 }
644
645 }