misc cleanup
[fanfix.git] / src / jexer / io / Screen.java
CommitLineData
df8de03f
KL
1/**
2 * Jexer - Java Text User Interface
3 *
df8de03f
KL
4 * License: LGPLv3 or later
5 *
7b5261bc
KL
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.
df8de03f
KL
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
7b5261bc
KL
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
df8de03f
KL
30 */
31package jexer.io;
32
33import jexer.bits.Cell;
34import jexer.bits.CellAttributes;
35import jexer.bits.GraphicsChars;
36
37/**
38 * This class represents a text-based screen. Drawing operations write to a
39 * logical screen.
40 */
41public abstract class Screen {
42
43 /**
7b5261bc 44 * Width of the visible window.
df8de03f
KL
45 */
46 protected int width;
47
48 /**
7b5261bc 49 * Height of the visible window.
df8de03f
KL
50 */
51 protected int height;
52
53 /**
7b5261bc 54 * Drawing offset for x.
df8de03f 55 */
fca67db0 56 private int offsetX;
48e27807
KL
57
58 /**
59 * Set drawing offset for x.
60 *
61 * @param offsetX new drawing offset
62 */
63 public final void setOffsetX(final int offsetX) {
64 this.offsetX = offsetX;
65 }
df8de03f
KL
66
67 /**
7b5261bc 68 * Drawing offset for y.
df8de03f 69 */
fca67db0 70 private int offsetY;
df8de03f 71
48e27807
KL
72 /**
73 * Set drawing offset for y.
74 *
75 * @param offsetY new drawing offset
76 */
77 public final void setOffsetY(final int offsetY) {
78 this.offsetY = offsetY;
79 }
fca67db0 80
df8de03f 81 /**
7b5261bc 82 * Ignore anything drawn right of clipRight.
df8de03f 83 */
fca67db0 84 private int clipRight;
48e27807
KL
85
86 /**
87 * Get right drawing clipping boundary.
88 *
89 * @return drawing boundary
90 */
91 public final int getClipRight() {
92 return clipRight;
93 }
94
95 /**
96 * Set right drawing clipping boundary.
97 *
98 * @param clipRight new boundary
99 */
100 public final void setClipRight(final int clipRight) {
101 this.clipRight = clipRight;
102 }
df8de03f
KL
103
104 /**
7b5261bc 105 * Ignore anything drawn below clipBottom.
df8de03f 106 */
fca67db0 107 private int clipBottom;
48e27807
KL
108
109 /**
110 * Get bottom drawing clipping boundary.
111 *
112 * @return drawing boundary
113 */
114 public final int getClipBottom() {
115 return clipBottom;
116 }
117
118 /**
119 * Set bottom drawing clipping boundary.
120 *
121 * @param clipBottom new boundary
122 */
123 public final void setClipBottom(final int clipBottom) {
124 this.clipBottom = clipBottom;
125 }
df8de03f
KL
126
127 /**
7b5261bc 128 * Ignore anything drawn left of clipLeft.
df8de03f 129 */
fca67db0 130 private int clipLeft;
48e27807
KL
131
132 /**
133 * Get left drawing clipping boundary.
134 *
135 * @return drawing boundary
136 */
137 public final int getClipLeft() {
138 return clipLeft;
139 }
140
141 /**
142 * Set left drawing clipping boundary.
143 *
144 * @param clipLeft new boundary
145 */
146 public final void setClipLeft(final int clipLeft) {
147 this.clipLeft = clipLeft;
148 }
df8de03f
KL
149
150 /**
7b5261bc 151 * Ignore anything drawn above clipTop.
df8de03f 152 */
fca67db0 153 private int clipTop;
48e27807
KL
154
155 /**
156 * Get top drawing clipping boundary.
157 *
158 * @return drawing boundary
159 */
160 public final int getClipTop() {
161 return clipTop;
162 }
163
164 /**
165 * Set top drawing clipping boundary.
166 *
167 * @param clipTop new boundary
168 */
169 public final void setClipTop(final int clipTop) {
170 this.clipTop = clipTop;
171 }
df8de03f
KL
172
173 /**
7b5261bc 174 * The physical screen last sent out on flush().
df8de03f
KL
175 */
176 protected Cell [][] physical;
177
178 /**
7b5261bc 179 * The logical screen being rendered to.
df8de03f
KL
180 */
181 protected Cell [][] logical;
182
183 /**
7b5261bc 184 * When true, logical != physical.
df8de03f 185 */
48e27807 186 protected boolean dirty;
df8de03f
KL
187
188 /**
189 * Set if the user explicitly wants to redraw everything starting with a
7b5261bc 190 * ECMATerminal.clearAll().
df8de03f
KL
191 */
192 protected boolean reallyCleared;
193
194 /**
195 * If true, the cursor is visible and should be placed onscreen at
7b5261bc 196 * (cursorX, cursorY) during a call to flushPhysical().
df8de03f
KL
197 */
198 protected boolean cursorVisible;
199
200 /**
7b5261bc 201 * Cursor X position if visible.
df8de03f
KL
202 */
203 protected int cursorX;
204
205 /**
7b5261bc 206 * Cursor Y position if visible.
df8de03f
KL
207 */
208 protected int cursorY;
209
210 /**
211 * Get the attributes at one location.
212 *
213 * @param x column coordinate. 0 is the left-most column.
214 * @param y row coordinate. 0 is the top-most row.
215 * @return attributes at (x, y)
216 */
fca67db0 217 public final CellAttributes getAttrXY(final int x, final int y) {
87a17f3c 218
7b5261bc 219 CellAttributes attr = new CellAttributes();
30bd4abd
KL
220 if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
221 attr.setTo(logical[x][y]);
222 }
7b5261bc 223 return attr;
df8de03f
KL
224 }
225
226 /**
227 * Set the attributes at one location.
228 *
229 * @param x column coordinate. 0 is the left-most column.
230 * @param y row coordinate. 0 is the top-most row.
231 * @param attr attributes to use (bold, foreColor, backColor)
df8de03f 232 */
fca67db0
KL
233 public final void putAttrXY(final int x, final int y,
234 final CellAttributes attr) {
235
7b5261bc 236 putAttrXY(x, y, attr, true);
df8de03f 237 }
7b5261bc 238
df8de03f
KL
239 /**
240 * Set the attributes at one location.
241 *
242 * @param x column coordinate. 0 is the left-most column.
243 * @param y row coordinate. 0 is the top-most row.
244 * @param attr attributes to use (bold, foreColor, backColor)
245 * @param clip if true, honor clipping/offset
246 */
87a17f3c
KL
247 public final void putAttrXY(final int x, final int y
248 , final CellAttributes attr, final boolean clip) {
7b5261bc
KL
249
250 int X = x;
251 int Y = y;
252
253 if (clip) {
254 if ((x < clipLeft)
255 || (x >= clipRight)
256 || (y < clipTop)
257 || (y >= clipBottom)
258 ) {
259 return;
260 }
261 X += offsetX;
262 Y += offsetY;
263 }
264
265 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
266 dirty = true;
267 logical[X][Y].setForeColor(attr.getForeColor());
268 logical[X][Y].setBackColor(attr.getBackColor());
269 logical[X][Y].setBold(attr.getBold());
270 logical[X][Y].setBlink(attr.getBlink());
271 logical[X][Y].setReverse(attr.getReverse());
272 logical[X][Y].setUnderline(attr.getUnderline());
273 logical[X][Y].setProtect(attr.getProtect());
274 }
df8de03f
KL
275 }
276
277 /**
278 * Fill the entire screen with one character with attributes.
279 *
280 * @param ch character to draw
281 * @param attr attributes to use (bold, foreColor, backColor)
282 */
fca67db0 283 public final void putAll(final char ch, final CellAttributes attr) {
87a17f3c 284
7b5261bc
KL
285 for (int x = 0; x < width; x++) {
286 for (int y = 0; y < height; y++) {
287 putCharXY(x, y, ch, attr);
288 }
289 }
df8de03f
KL
290 }
291
292 /**
293 * Render one character with attributes.
294 *
295 * @param x column coordinate. 0 is the left-most column.
296 * @param y row coordinate. 0 is the top-most row.
297 * @param ch character + attributes to draw
298 */
fca67db0 299 public final void putCharXY(final int x, final int y, final Cell ch) {
7b5261bc 300 putCharXY(x, y, ch.getChar(), ch);
df8de03f
KL
301 }
302
303 /**
304 * Render one character with attributes.
305 *
306 * @param x column coordinate. 0 is the left-most column.
307 * @param y row coordinate. 0 is the top-most row.
308 * @param ch character to draw
309 * @param attr attributes to use (bold, foreColor, backColor)
310 */
fca67db0 311 public final void putCharXY(final int x, final int y, final char ch,
7b5261bc
KL
312 final CellAttributes attr) {
313
314 if ((x < clipLeft)
315 || (x >= clipRight)
316 || (y < clipTop)
317 || (y >= clipBottom)
318 ) {
319 return;
320 }
321
322 int X = x + offsetX;
323 int Y = y + offsetY;
324
325 // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
326
327 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
328 dirty = true;
329
330 // Do not put control characters on the display
331 assert (ch >= 0x20);
332 assert (ch != 0x7F);
333
334 logical[X][Y].setChar(ch);
335 logical[X][Y].setForeColor(attr.getForeColor());
336 logical[X][Y].setBackColor(attr.getBackColor());
337 logical[X][Y].setBold(attr.getBold());
338 logical[X][Y].setBlink(attr.getBlink());
339 logical[X][Y].setReverse(attr.getReverse());
340 logical[X][Y].setUnderline(attr.getUnderline());
341 logical[X][Y].setProtect(attr.getProtect());
342 }
df8de03f
KL
343 }
344
345 /**
346 * Render one character without changing the underlying attributes.
347 *
348 * @param x column coordinate. 0 is the left-most column.
349 * @param y row coordinate. 0 is the top-most row.
350 * @param ch character to draw
351 */
fca67db0 352 public final void putCharXY(final int x, final int y, final char ch) {
87a17f3c 353
7b5261bc
KL
354 if ((x < clipLeft)
355 || (x >= clipRight)
356 || (y < clipTop)
357 || (y >= clipBottom)
358 ) {
359 return;
360 }
df8de03f 361
7b5261bc
KL
362 int X = x + offsetX;
363 int Y = y + offsetY;
df8de03f 364
7b5261bc 365 // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
df8de03f 366
7b5261bc
KL
367 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
368 dirty = true;
369 logical[X][Y].setChar(ch);
370 }
df8de03f
KL
371 }
372
373 /**
374 * Render a string. Does not wrap if the string exceeds the line.
375 *
376 * @param x column coordinate. 0 is the left-most column.
377 * @param y row coordinate. 0 is the top-most row.
378 * @param str string to draw
379 * @param attr attributes to use (bold, foreColor, backColor)
380 */
fca67db0 381 public final void putStrXY(final int x, final int y, final String str,
7b5261bc
KL
382 final CellAttributes attr) {
383
384 int i = x;
385 for (int j = 0; j < str.length(); j++) {
386 char ch = str.charAt(j);
387 putCharXY(i, y, ch, attr);
388 i++;
389 if (i == width) {
390 break;
391 }
392 }
df8de03f
KL
393 }
394
395 /**
396 * Render a string without changing the underlying attribute. Does not
397 * wrap if the string exceeds the line.
398 *
399 * @param x column coordinate. 0 is the left-most column.
400 * @param y row coordinate. 0 is the top-most row.
401 * @param str string to draw
402 */
fca67db0 403 public final void putStrXY(final int x, final int y, final String str) {
87a17f3c 404
7b5261bc
KL
405 int i = x;
406 for (int j = 0; j < str.length(); j++) {
407 char ch = str.charAt(j);
408 putCharXY(i, y, ch);
409 i++;
410 if (i == width) {
411 break;
412 }
413 }
df8de03f
KL
414 }
415
416 /**
7b5261bc 417 * Draw a vertical line from (x, y) to (x, y + n).
df8de03f
KL
418 *
419 * @param x column coordinate. 0 is the left-most column.
420 * @param y row coordinate. 0 is the top-most row.
421 * @param n number of characters to draw
422 * @param ch character to draw
423 * @param attr attributes to use (bold, foreColor, backColor)
424 */
fca67db0
KL
425 public final void vLineXY(final int x, final int y, final int n,
426 final char ch, final CellAttributes attr) {
7b5261bc
KL
427
428 for (int i = y; i < y + n; i++) {
429 putCharXY(x, i, ch, attr);
430 }
df8de03f
KL
431 }
432
433 /**
7b5261bc 434 * Draw a horizontal line from (x, y) to (x + n, y).
df8de03f
KL
435 *
436 * @param x column coordinate. 0 is the left-most column.
437 * @param y row coordinate. 0 is the top-most row.
438 * @param n number of characters to draw
439 * @param ch character to draw
440 * @param attr attributes to use (bold, foreColor, backColor)
441 */
fca67db0
KL
442 public final void hLineXY(final int x, final int y, final int n,
443 final char ch, final CellAttributes attr) {
7b5261bc
KL
444
445 for (int i = x; i < x + n; i++) {
446 putCharXY(i, y, ch, attr);
447 }
df8de03f
KL
448 }
449
450 /**
451 * Reallocate screen buffers.
452 *
453 * @param width new width
454 * @param height new height
455 */
87a17f3c 456 private synchronized void reallocate(final int width, final int height) {
7b5261bc
KL
457 if (logical != null) {
458 for (int row = 0; row < this.height; row++) {
459 for (int col = 0; col < this.width; col++) {
460 logical[col][row] = null;
461 }
462 }
463 logical = null;
464 }
465 logical = new Cell[width][height];
466 if (physical != null) {
467 for (int row = 0; row < this.height; row++) {
468 for (int col = 0; col < this.width; col++) {
469 physical[col][row] = null;
470 }
471 }
472 physical = null;
473 }
474 physical = new Cell[width][height];
475
476 for (int row = 0; row < height; row++) {
477 for (int col = 0; col < width; col++) {
478 physical[col][row] = new Cell();
479 logical[col][row] = new Cell();
480 }
481 }
482
483 this.width = width;
484 this.height = height;
485
486 clipLeft = 0;
487 clipTop = 0;
488 clipRight = width;
489 clipBottom = height;
490
491 reallyCleared = true;
492 dirty = true;
df8de03f
KL
493 }
494
495 /**
496 * Change the width. Everything on-screen will be destroyed and must be
497 * redrawn.
7b5261bc 498 *
df8de03f
KL
499 * @param width new screen width
500 */
87a17f3c 501 public final synchronized void setWidth(final int width) {
7b5261bc 502 reallocate(width, this.height);
df8de03f
KL
503 }
504
505 /**
506 * Change the height. Everything on-screen will be destroyed and must be
507 * redrawn.
508 *
509 * @param height new screen height
510 */
87a17f3c 511 public final synchronized void setHeight(final int height) {
7b5261bc 512 reallocate(this.width, height);
df8de03f
KL
513 }
514
515 /**
516 * Change the width and height. Everything on-screen will be destroyed
517 * and must be redrawn.
518 *
519 * @param width new screen width
520 * @param height new screen height
521 */
fca67db0 522 public final void setDimensions(final int width, final int height) {
7b5261bc 523 reallocate(width, height);
df8de03f
KL
524 }
525
526 /**
527 * Get the height.
528 *
529 * @return current screen height
530 */
87a17f3c 531 public final synchronized int getHeight() {
7b5261bc 532 return this.height;
df8de03f
KL
533 }
534
535 /**
536 * Get the width.
537 *
538 * @return current screen width
539 */
87a17f3c 540 public final synchronized int getWidth() {
7b5261bc 541 return this.width;
df8de03f
KL
542 }
543
544 /**
545 * Public constructor. Sets everything to not-bold, white-on-black.
546 */
fca67db0 547 protected Screen() {
7b5261bc
KL
548 offsetX = 0;
549 offsetY = 0;
550 width = 80;
551 height = 24;
552 logical = null;
553 physical = null;
554 reallocate(width, height);
df8de03f
KL
555 }
556
557 /**
558 * Reset screen to not-bold, white-on-black. Also flushes the offset and
559 * clip variables.
560 */
87a17f3c 561 public final synchronized void reset() {
7b5261bc
KL
562 dirty = true;
563 for (int row = 0; row < height; row++) {
564 for (int col = 0; col < width; col++) {
565 logical[col][row].reset();
566 }
567 }
568 resetClipping();
df8de03f
KL
569 }
570
571 /**
572 * Flush the offset and clip variables.
573 */
fca67db0 574 public final void resetClipping() {
7b5261bc
KL
575 offsetX = 0;
576 offsetY = 0;
577 clipLeft = 0;
578 clipTop = 0;
579 clipRight = width;
580 clipBottom = height;
df8de03f
KL
581 }
582
583 /**
584 * Force the screen to be fully cleared and redrawn on the next flush().
585 */
fca67db0 586 public final void clear() {
7b5261bc 587 reset();
df8de03f
KL
588 }
589
590 /**
591 * Draw a box with a border and empty background.
592 *
593 * @param left left column of box. 0 is the left-most row.
594 * @param top top row of the box. 0 is the top-most row.
595 * @param right right column of box
596 * @param bottom bottom row of the box
7b5261bc 597 * @param border attributes to use for the border
df8de03f
KL
598 * @param background attributes to use for the background
599 */
fca67db0 600 public final void drawBox(final int left, final int top,
7b5261bc
KL
601 final int right, final int bottom,
602 final CellAttributes border, final CellAttributes background) {
603
604 drawBox(left, top, right, bottom, border, background, 1, false);
df8de03f
KL
605 }
606
607 /**
608 * Draw a box with a border and empty background.
609 *
610 * @param left left column of box. 0 is the left-most row.
611 * @param top top row of the box. 0 is the top-most row.
612 * @param right right column of box
613 * @param bottom bottom row of the box
7b5261bc 614 * @param border attributes to use for the border
df8de03f 615 * @param background attributes to use for the background
7b5261bc
KL
616 * @param borderType if 1, draw a single-line border; if 2, draw a
617 * double-line border; if 3, draw double-line top/bottom edges and
618 * single-line left/right edges (like Qmodem)
df8de03f
KL
619 * @param shadow if true, draw a "shadow" on the box
620 */
fca67db0 621 public final void drawBox(final int left, final int top,
7b5261bc
KL
622 final int right, final int bottom,
623 final CellAttributes border, final CellAttributes background,
624 final int borderType, final boolean shadow) {
625
626 int boxTop = top;
627 int boxLeft = left;
628 int boxWidth = right - left;
629 int boxHeight = bottom - top;
630
631 char cTopLeft;
632 char cTopRight;
633 char cBottomLeft;
634 char cBottomRight;
635 char cHSide;
636 char cVSide;
637
638 switch (borderType) {
639 case 1:
640 cTopLeft = GraphicsChars.ULCORNER;
641 cTopRight = GraphicsChars.URCORNER;
642 cBottomLeft = GraphicsChars.LLCORNER;
643 cBottomRight = GraphicsChars.LRCORNER;
644 cHSide = GraphicsChars.SINGLE_BAR;
645 cVSide = GraphicsChars.WINDOW_SIDE;
646 break;
647
648 case 2:
649 cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE;
650 cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE;
651 cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE;
652 cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE;
653 cHSide = GraphicsChars.DOUBLE_BAR;
654 cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE;
655 break;
656
657 case 3:
658 cTopLeft = GraphicsChars.WINDOW_LEFT_TOP;
659 cTopRight = GraphicsChars.WINDOW_RIGHT_TOP;
660 cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM;
661 cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM;
662 cHSide = GraphicsChars.WINDOW_TOP;
663 cVSide = GraphicsChars.WINDOW_SIDE;
664 break;
665 default:
666 throw new IllegalArgumentException("Invalid border type: "
667 + borderType);
668 }
669
670 // Place the corner characters
671 putCharXY(left, top, cTopLeft, border);
672 putCharXY(left + boxWidth - 1, top, cTopRight, border);
673 putCharXY(left, top + boxHeight - 1, cBottomLeft, border);
674 putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight,
675 border);
676
677 // Draw the box lines
678 hLineXY(left + 1, top, boxWidth - 2, cHSide, border);
679 vLineXY(left, top + 1, boxHeight - 2, cVSide, border);
680 hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border);
681 vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border);
682
683 // Fill in the interior background
684 for (int i = 1; i < boxHeight - 1; i++) {
685 hLineXY(1 + left, i + top, boxWidth - 2, ' ', background);
686 }
687
688 if (shadow) {
689 // Draw a shadow
690 drawBoxShadow(left, top, right, bottom);
691 }
df8de03f
KL
692 }
693
694 /**
fca67db0 695 * Draw a box shadow.
df8de03f
KL
696 *
697 * @param left left column of box. 0 is the left-most row.
698 * @param top top row of the box. 0 is the top-most row.
699 * @param right right column of box
700 * @param bottom bottom row of the box
701 */
fca67db0 702 public final void drawBoxShadow(final int left, final int top,
7b5261bc
KL
703 final int right, final int bottom) {
704
705 int boxTop = top;
706 int boxLeft = left;
707 int boxWidth = right - left;
708 int boxHeight = bottom - top;
709 CellAttributes shadowAttr = new CellAttributes();
710
711 // Shadows do not honor clipping but they DO honor offset.
712 int oldClipRight = clipRight;
713 int oldClipBottom = clipBottom;
714 /*
715 clipRight = boxWidth + 2;
716 clipBottom = boxHeight + 1;
717 */
718 clipRight = width;
719 clipBottom = height;
720
721 for (int i = 0; i < boxHeight; i++) {
722 putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr);
723 putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr);
724 }
725 for (int i = 0; i < boxWidth; i++) {
726 putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr);
727 }
728 clipRight = oldClipRight;
729 clipBottom = oldClipBottom;
df8de03f
KL
730 }
731
732 /**
733 * Subclasses must provide an implementation to push the logical screen
734 * to the physical device.
735 */
30bd4abd 736 public abstract void flushPhysical();
df8de03f
KL
737
738 /**
739 * Put the cursor at (x,y).
740 *
741 * @param visible if true, the cursor should be visible
742 * @param x column coordinate to put the cursor on
743 * @param y row coordinate to put the cursor on
744 */
30bd4abd 745 public void putCursor(final boolean visible, final int x, final int y) {
fca67db0 746
7b5261bc
KL
747 cursorVisible = visible;
748 cursorX = x;
749 cursorY = y;
df8de03f
KL
750 }
751
752 /**
fca67db0 753 * Hide the cursor.
df8de03f 754 */
fca67db0 755 public final void hideCursor() {
7b5261bc 756 cursorVisible = false;
df8de03f
KL
757 }
758}