LICENSE CHANGED TO MIT
[nikiroo-utils.git] / src / jexer / TVScroller.java
CommitLineData
daa4106c 1/*
48e27807
KL
2 * Jexer - Java Text User Interface
3 *
e16dda65 4 * The MIT License (MIT)
48e27807 5 *
e16dda65 6 * Copyright (C) 2016 Kevin Lamonte
48e27807 7 *
e16dda65
KL
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:
48e27807 14 *
e16dda65
KL
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
48e27807 17 *
e16dda65
KL
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.
48e27807
KL
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
cc99cba8
KL
31import jexer.bits.CellAttributes;
32import jexer.bits.GraphicsChars;
33import jexer.event.TMouseEvent;
34
48e27807
KL
35/**
36 * TVScroller implements a simple vertical scroll bar.
37 */
2b9c27db 38public final class TVScroller extends TWidget {
48e27807 39
cc99cba8
KL
40 /**
41 * Value that corresponds to being on the top edge of the scroll bar.
42 */
43 private int topValue = 0;
44
45 /**
46 * Get the value that corresponds to being on the top edge of the scroll
47 * bar.
48 *
49 * @return the scroll value
50 */
51 public int getTopValue() {
52 return topValue;
53 }
54
55 /**
56 * Set the value that corresponds to being on the top edge of the scroll
57 * bar.
58 *
59 * @param topValue the new scroll value
60 */
61 public void setTopValue(final int topValue) {
62 this.topValue = topValue;
63 }
64
65 /**
66 * Value that corresponds to being on the bottom edge of the scroll bar.
67 */
68 private int bottomValue = 100;
69
70 /**
71 * Get the value that corresponds to being on the bottom edge of the
72 * scroll bar.
73 *
74 * @return the scroll value
75 */
76 public int getBottomValue() {
77 return bottomValue;
78 }
79
80 /**
81 * Set the value that corresponds to being on the bottom edge of the
82 * scroll bar.
83 *
84 * @param bottomValue the new scroll value
85 */
86 public void setBottomValue(final int bottomValue) {
87 this.bottomValue = bottomValue;
88 }
89
90 /**
91 * Current value of the scroll.
92 */
93 private int value = 0;
94
95 /**
96 * Get current value of the scroll.
97 *
98 * @return the scroll value
99 */
100 public int getValue() {
101 return value;
102 }
103
104 /**
105 * Set current value of the scroll.
106 *
107 * @param value the new scroll value
108 */
109 public void setValue(final int value) {
110 this.value = value;
111 }
112
113 /**
114 * The increment for clicking on an arrow.
115 */
116 private int smallChange = 1;
117
118 /**
119 * Set the increment for clicking on an arrow.
120 *
121 * @param smallChange the new increment value
122 */
123 public void setSmallChange(final int smallChange) {
124 this.smallChange = smallChange;
125 }
126
127 /**
128 * The increment for clicking in the bar between the box and an arrow.
129 */
130 private int bigChange = 20;
131
132 /**
133 * Set the increment for clicking in the bar between the box and an
134 * arrow.
135 *
136 * @param bigChange the new increment value
137 */
138 public void setBigChange(final int bigChange) {
139 this.bigChange = bigChange;
140 }
141
142 /**
143 * When true, the user is dragging the scroll box.
144 */
145 private boolean inScroll = false;
146
147 /**
148 * Public constructor.
149 *
150 * @param parent parent widget
151 * @param x column relative to parent
152 * @param y row relative to parent
06fc7969 153 * @param height height of scroll bar
cc99cba8
KL
154 */
155 public TVScroller(final TWidget parent, final int x, final int y,
156 final int height) {
157
158 // Set parent and window
a83fea2b 159 super(parent, x, y, 1, height);
cc99cba8
KL
160 }
161
162 /**
163 * Compute the position of the scroll box (a.k.a. grip, thumb).
164 *
06fc7969 165 * @return Y position of the box, between 1 and height - 2
cc99cba8
KL
166 */
167 private int boxPosition() {
168 return (getHeight() - 3) * (value - topValue) / (bottomValue - topValue) + 1;
169 }
170
171 /**
172 * Draw a vertical scroll bar.
173 */
174 @Override
175 public void draw() {
176 CellAttributes arrowColor = getTheme().getColor("tscroller.arrows");
177 CellAttributes barColor = getTheme().getColor("tscroller.bar");
178 getScreen().putCharXY(0, 0, GraphicsChars.CP437[0x1E], arrowColor);
179 getScreen().putCharXY(0, getHeight() - 1, GraphicsChars.CP437[0x1F],
180 arrowColor);
181
182 // Place the box
183 if (bottomValue > topValue) {
184 getScreen().vLineXY(0, 1, getHeight() - 2,
185 GraphicsChars.CP437[0xB1], barColor);
186 getScreen().putCharXY(0, boxPosition(), GraphicsChars.BOX,
187 arrowColor);
188 } else {
189 getScreen().vLineXY(0, 1, getHeight() - 2, GraphicsChars.HATCH,
190 barColor);
191 }
192
193 }
194
195 /**
196 * Perform a small step change up.
197 */
198 public void decrement() {
199 if (bottomValue == topValue) {
200 return;
201 }
202 value -= smallChange;
203 if (value < topValue) {
204 value = topValue;
205 }
206 }
207
208 /**
209 * Perform a small step change down.
210 */
211 public void increment() {
212 if (bottomValue == topValue) {
213 return;
214 }
215 value += smallChange;
216 if (value > bottomValue) {
217 value = bottomValue;
218 }
219 }
220
221 /**
222 * Perform a big step change up.
223 */
224 public void bigDecrement() {
225 if (bottomValue == topValue) {
226 return;
227 }
228 value -= bigChange;
229 if (value < topValue) {
230 value = topValue;
231 }
232 }
233
234 /**
235 * Perform a big step change down.
236 */
237 public void bigIncrement() {
238 if (bottomValue == topValue) {
239 return;
240 }
241 value += bigChange;
242 if (value > bottomValue) {
243 value = bottomValue;
244 }
245 }
246
247 /**
248 * Go to the top edge of the scroller.
249 */
250 public void toTop() {
251 value = topValue;
252 }
253
254 /**
255 * Go to the bottom edge of the scroller.
256 */
257 public void toBottom() {
258 value = bottomValue;
259 }
260
261 /**
262 * Handle mouse button releases.
263 *
264 * @param mouse mouse button release event
265 */
266 @Override
267 public void onMouseUp(final TMouseEvent mouse) {
268 if (bottomValue == topValue) {
269 return;
270 }
271
272 if (inScroll) {
273 inScroll = false;
274 return;
275 }
276
277 if ((mouse.getX() == 0)
278 && (mouse.getY() == 0)
279 ) {
280 // Clicked on the top arrow
281 decrement();
282 return;
283 }
284
285 if ((mouse.getX() == 0)
286 && (mouse.getY() == getHeight() - 1)
287 ) {
288 // Clicked on the bottom arrow
289 increment();
290 return;
291 }
292
293 if ((mouse.getX() == 0)
294 && (mouse.getY() > 0)
295 && (mouse.getY() < boxPosition())
296 ) {
297 // Clicked between the top arrow and the box
298 value -= bigChange;
299 if (value < topValue) {
300 value = topValue;
301 }
302 return;
303 }
304
305 if ((mouse.getX() == 0)
306 && (mouse.getY() > boxPosition())
307 && (mouse.getY() < getHeight() - 1)
308 ) {
309 // Clicked between the box and the bottom arrow
310 value += bigChange;
311 if (value > bottomValue) {
312 value = bottomValue;
313 }
314 return;
315 }
316 }
317
318 /**
319 * Handle mouse movement events.
320 *
321 * @param mouse mouse motion event
322 */
323 @Override
324 public void onMouseMotion(final TMouseEvent mouse) {
325 if (bottomValue == topValue) {
326 return;
327 }
328
329fd62e
KL
329 if ((mouse.isMouse1())
330 && (inScroll)
331 && (mouse.getY() > 0)
332 && (mouse.getY() < getHeight() - 1)
cc99cba8
KL
333 ) {
334 // Recompute value based on new box position
329fd62e
KL
335 value = (bottomValue - topValue)
336 * (mouse.getY()) / (getHeight() - 3) + topValue;
cc99cba8
KL
337 return;
338 }
339
340 inScroll = false;
341 }
342
343 /**
344 * Handle mouse press events.
345 *
346 * @param mouse mouse button press event
347 */
348 @Override
349 public void onMouseDown(final TMouseEvent mouse) {
350 if (bottomValue == topValue) {
351 return;
352 }
353
354 if ((mouse.getX() == 0)
355 && (mouse.getY() == boxPosition())
356 ) {
357 inScroll = true;
358 return;
359 }
360 }
361
48e27807 362}