Pull demo into jar
[nikiroo-utils.git] / src / jexer / TVScroller.java
... / ...
CommitLineData
1/**
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31package jexer;
32
33import jexer.bits.CellAttributes;
34import jexer.bits.GraphicsChars;
35import jexer.event.TMouseEvent;
36
37/**
38 * TVScroller implements a simple vertical scroll bar.
39 */
40public final class TVScroller extends TWidget {
41
42 /**
43 * Value that corresponds to being on the top edge of the scroll bar.
44 */
45 private int topValue = 0;
46
47 /**
48 * Get the value that corresponds to being on the top edge of the scroll
49 * bar.
50 *
51 * @return the scroll value
52 */
53 public int getTopValue() {
54 return topValue;
55 }
56
57 /**
58 * Set the value that corresponds to being on the top edge of the scroll
59 * bar.
60 *
61 * @param topValue the new scroll value
62 */
63 public void setTopValue(final int topValue) {
64 this.topValue = topValue;
65 }
66
67 /**
68 * Value that corresponds to being on the bottom edge of the scroll bar.
69 */
70 private int bottomValue = 100;
71
72 /**
73 * Get the value that corresponds to being on the bottom edge of the
74 * scroll bar.
75 *
76 * @return the scroll value
77 */
78 public int getBottomValue() {
79 return bottomValue;
80 }
81
82 /**
83 * Set the value that corresponds to being on the bottom edge of the
84 * scroll bar.
85 *
86 * @param bottomValue the new scroll value
87 */
88 public void setBottomValue(final int bottomValue) {
89 this.bottomValue = bottomValue;
90 }
91
92 /**
93 * Current value of the scroll.
94 */
95 private int value = 0;
96
97 /**
98 * Get current value of the scroll.
99 *
100 * @return the scroll value
101 */
102 public int getValue() {
103 return value;
104 }
105
106 /**
107 * Set current value of the scroll.
108 *
109 * @param value the new scroll value
110 */
111 public void setValue(final int value) {
112 this.value = value;
113 }
114
115 /**
116 * The increment for clicking on an arrow.
117 */
118 private int smallChange = 1;
119
120 /**
121 * Set the increment for clicking on an arrow.
122 *
123 * @param smallChange the new increment value
124 */
125 public void setSmallChange(final int smallChange) {
126 this.smallChange = smallChange;
127 }
128
129 /**
130 * The increment for clicking in the bar between the box and an arrow.
131 */
132 private int bigChange = 20;
133
134 /**
135 * Set the increment for clicking in the bar between the box and an
136 * arrow.
137 *
138 * @param bigChange the new increment value
139 */
140 public void setBigChange(final int bigChange) {
141 this.bigChange = bigChange;
142 }
143
144 /**
145 * When true, the user is dragging the scroll box.
146 */
147 private boolean inScroll = false;
148
149 /**
150 * Public constructor.
151 *
152 * @param parent parent widget
153 * @param x column relative to parent
154 * @param y row relative to parent
155 * @param height height of scroll bar
156 */
157 public TVScroller(final TWidget parent, final int x, final int y,
158 final int height) {
159
160 // Set parent and window
161 super(parent);
162
163 setX(x);
164 setY(y);
165 setHeight(height);
166 setWidth(1);
167 }
168
169 /**
170 * Compute the position of the scroll box (a.k.a. grip, thumb).
171 *
172 * @return Y position of the box, between 1 and height - 2
173 */
174 private int boxPosition() {
175 return (getHeight() - 3) * (value - topValue) / (bottomValue - topValue) + 1;
176 }
177
178 /**
179 * Draw a vertical scroll bar.
180 */
181 @Override
182 public void draw() {
183 CellAttributes arrowColor = getTheme().getColor("tscroller.arrows");
184 CellAttributes barColor = getTheme().getColor("tscroller.bar");
185 getScreen().putCharXY(0, 0, GraphicsChars.CP437[0x1E], arrowColor);
186 getScreen().putCharXY(0, getHeight() - 1, GraphicsChars.CP437[0x1F],
187 arrowColor);
188
189 // Place the box
190 if (bottomValue > topValue) {
191 getScreen().vLineXY(0, 1, getHeight() - 2,
192 GraphicsChars.CP437[0xB1], barColor);
193 getScreen().putCharXY(0, boxPosition(), GraphicsChars.BOX,
194 arrowColor);
195 } else {
196 getScreen().vLineXY(0, 1, getHeight() - 2, GraphicsChars.HATCH,
197 barColor);
198 }
199
200 }
201
202 /**
203 * Perform a small step change up.
204 */
205 public void decrement() {
206 if (bottomValue == topValue) {
207 return;
208 }
209 value -= smallChange;
210 if (value < topValue) {
211 value = topValue;
212 }
213 }
214
215 /**
216 * Perform a small step change down.
217 */
218 public void increment() {
219 if (bottomValue == topValue) {
220 return;
221 }
222 value += smallChange;
223 if (value > bottomValue) {
224 value = bottomValue;
225 }
226 }
227
228 /**
229 * Perform a big step change up.
230 */
231 public void bigDecrement() {
232 if (bottomValue == topValue) {
233 return;
234 }
235 value -= bigChange;
236 if (value < topValue) {
237 value = topValue;
238 }
239 }
240
241 /**
242 * Perform a big step change down.
243 */
244 public void bigIncrement() {
245 if (bottomValue == topValue) {
246 return;
247 }
248 value += bigChange;
249 if (value > bottomValue) {
250 value = bottomValue;
251 }
252 }
253
254 /**
255 * Go to the top edge of the scroller.
256 */
257 public void toTop() {
258 value = topValue;
259 }
260
261 /**
262 * Go to the bottom edge of the scroller.
263 */
264 public void toBottom() {
265 value = bottomValue;
266 }
267
268 /**
269 * Handle mouse button releases.
270 *
271 * @param mouse mouse button release event
272 */
273 @Override
274 public void onMouseUp(final TMouseEvent mouse) {
275 if (bottomValue == topValue) {
276 return;
277 }
278
279 if (inScroll) {
280 inScroll = false;
281 return;
282 }
283
284 if ((mouse.getX() == 0)
285 && (mouse.getY() == 0)
286 ) {
287 // Clicked on the top arrow
288 decrement();
289 return;
290 }
291
292 if ((mouse.getX() == 0)
293 && (mouse.getY() == getHeight() - 1)
294 ) {
295 // Clicked on the bottom arrow
296 increment();
297 return;
298 }
299
300 if ((mouse.getX() == 0)
301 && (mouse.getY() > 0)
302 && (mouse.getY() < boxPosition())
303 ) {
304 // Clicked between the top arrow and the box
305 value -= bigChange;
306 if (value < topValue) {
307 value = topValue;
308 }
309 return;
310 }
311
312 if ((mouse.getX() == 0)
313 && (mouse.getY() > boxPosition())
314 && (mouse.getY() < getHeight() - 1)
315 ) {
316 // Clicked between the box and the bottom arrow
317 value += bigChange;
318 if (value > bottomValue) {
319 value = bottomValue;
320 }
321 return;
322 }
323 }
324
325 /**
326 * Handle mouse movement events.
327 *
328 * @param mouse mouse motion event
329 */
330 @Override
331 public void onMouseMotion(final TMouseEvent mouse) {
332 if (bottomValue == topValue) {
333 return;
334 }
335
336 if ((mouse.getMouse1()) &&
337 (inScroll) &&
338 (mouse.getY() > 0) &&
339 (mouse.getY() < getHeight() - 1)
340 ) {
341 // Recompute value based on new box position
342 value = (bottomValue - topValue) * (mouse.getY()) / (getHeight() - 3) + topValue;
343 return;
344 }
345
346 inScroll = false;
347 }
348
349 /**
350 * Handle mouse press events.
351 *
352 * @param mouse mouse button press event
353 */
354 @Override
355 public void onMouseDown(final TMouseEvent mouse) {
356 if (bottomValue == topValue) {
357 return;
358 }
359
360 if ((mouse.getX() == 0)
361 && (mouse.getY() == boxPosition())
362 ) {
363 inScroll = true;
364 return;
365 }
366 }
367
368}