9b69f691593a4ed0ae9c78d65039eb968c40b0d7
[nikiroo-utils.git] / src / jexer / TVScroller.java
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 */
31 package jexer;
32
33 import jexer.bits.CellAttributes;
34 import jexer.bits.GraphicsChars;
35 import jexer.event.TMouseEvent;
36
37 /**
38 * TVScroller implements a simple vertical scroll bar.
39 */
40 public 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, x, y, 1, height);
162 }
163
164 /**
165 * Compute the position of the scroll box (a.k.a. grip, thumb).
166 *
167 * @return Y position of the box, between 1 and height - 2
168 */
169 private int boxPosition() {
170 return (getHeight() - 3) * (value - topValue) / (bottomValue - topValue) + 1;
171 }
172
173 /**
174 * Draw a vertical scroll bar.
175 */
176 @Override
177 public void draw() {
178 CellAttributes arrowColor = getTheme().getColor("tscroller.arrows");
179 CellAttributes barColor = getTheme().getColor("tscroller.bar");
180 getScreen().putCharXY(0, 0, GraphicsChars.CP437[0x1E], arrowColor);
181 getScreen().putCharXY(0, getHeight() - 1, GraphicsChars.CP437[0x1F],
182 arrowColor);
183
184 // Place the box
185 if (bottomValue > topValue) {
186 getScreen().vLineXY(0, 1, getHeight() - 2,
187 GraphicsChars.CP437[0xB1], barColor);
188 getScreen().putCharXY(0, boxPosition(), GraphicsChars.BOX,
189 arrowColor);
190 } else {
191 getScreen().vLineXY(0, 1, getHeight() - 2, GraphicsChars.HATCH,
192 barColor);
193 }
194
195 }
196
197 /**
198 * Perform a small step change up.
199 */
200 public void decrement() {
201 if (bottomValue == topValue) {
202 return;
203 }
204 value -= smallChange;
205 if (value < topValue) {
206 value = topValue;
207 }
208 }
209
210 /**
211 * Perform a small step change down.
212 */
213 public void increment() {
214 if (bottomValue == topValue) {
215 return;
216 }
217 value += smallChange;
218 if (value > bottomValue) {
219 value = bottomValue;
220 }
221 }
222
223 /**
224 * Perform a big step change up.
225 */
226 public void bigDecrement() {
227 if (bottomValue == topValue) {
228 return;
229 }
230 value -= bigChange;
231 if (value < topValue) {
232 value = topValue;
233 }
234 }
235
236 /**
237 * Perform a big step change down.
238 */
239 public void bigIncrement() {
240 if (bottomValue == topValue) {
241 return;
242 }
243 value += bigChange;
244 if (value > bottomValue) {
245 value = bottomValue;
246 }
247 }
248
249 /**
250 * Go to the top edge of the scroller.
251 */
252 public void toTop() {
253 value = topValue;
254 }
255
256 /**
257 * Go to the bottom edge of the scroller.
258 */
259 public void toBottom() {
260 value = bottomValue;
261 }
262
263 /**
264 * Handle mouse button releases.
265 *
266 * @param mouse mouse button release event
267 */
268 @Override
269 public void onMouseUp(final TMouseEvent mouse) {
270 if (bottomValue == topValue) {
271 return;
272 }
273
274 if (inScroll) {
275 inScroll = false;
276 return;
277 }
278
279 if ((mouse.getX() == 0)
280 && (mouse.getY() == 0)
281 ) {
282 // Clicked on the top arrow
283 decrement();
284 return;
285 }
286
287 if ((mouse.getX() == 0)
288 && (mouse.getY() == getHeight() - 1)
289 ) {
290 // Clicked on the bottom arrow
291 increment();
292 return;
293 }
294
295 if ((mouse.getX() == 0)
296 && (mouse.getY() > 0)
297 && (mouse.getY() < boxPosition())
298 ) {
299 // Clicked between the top arrow and the box
300 value -= bigChange;
301 if (value < topValue) {
302 value = topValue;
303 }
304 return;
305 }
306
307 if ((mouse.getX() == 0)
308 && (mouse.getY() > boxPosition())
309 && (mouse.getY() < getHeight() - 1)
310 ) {
311 // Clicked between the box and the bottom arrow
312 value += bigChange;
313 if (value > bottomValue) {
314 value = bottomValue;
315 }
316 return;
317 }
318 }
319
320 /**
321 * Handle mouse movement events.
322 *
323 * @param mouse mouse motion event
324 */
325 @Override
326 public void onMouseMotion(final TMouseEvent mouse) {
327 if (bottomValue == topValue) {
328 return;
329 }
330
331 if ((mouse.isMouse1())
332 && (inScroll)
333 && (mouse.getY() > 0)
334 && (mouse.getY() < getHeight() - 1)
335 ) {
336 // Recompute value based on new box position
337 value = (bottomValue - topValue)
338 * (mouse.getY()) / (getHeight() - 3) + topValue;
339 return;
340 }
341
342 inScroll = false;
343 }
344
345 /**
346 * Handle mouse press events.
347 *
348 * @param mouse mouse button press event
349 */
350 @Override
351 public void onMouseDown(final TMouseEvent mouse) {
352 if (bottomValue == topValue) {
353 return;
354 }
355
356 if ((mouse.getX() == 0)
357 && (mouse.getY() == boxPosition())
358 ) {
359 inScroll = true;
360 return;
361 }
362 }
363
364 }