color chooser widget
[fanfix.git] / src / jexer / io / Screen.java
CommitLineData
daa4106c 1/*
df8de03f
KL
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 */
bd8d51fa 186 protected volatile boolean dirty;
df8de03f 187
92554d64
KL
188 /**
189 * Get dirty flag.
190 *
191 * @return if true, the logical screen is not in sync with the physical
192 * screen
193 */
194 public final boolean isDirty() {
195 return dirty;
196 }
197
df8de03f
KL
198 /**
199 * Set if the user explicitly wants to redraw everything starting with a
7b5261bc 200 * ECMATerminal.clearAll().
df8de03f
KL
201 */
202 protected boolean reallyCleared;
203
204 /**
205 * If true, the cursor is visible and should be placed onscreen at
7b5261bc 206 * (cursorX, cursorY) during a call to flushPhysical().
df8de03f
KL
207 */
208 protected boolean cursorVisible;
209
210 /**
7b5261bc 211 * Cursor X position if visible.
df8de03f
KL
212 */
213 protected int cursorX;
214
215 /**
7b5261bc 216 * Cursor Y position if visible.
df8de03f
KL
217 */
218 protected int cursorY;
219
220 /**
221 * Get the attributes at one location.
222 *
223 * @param x column coordinate. 0 is the left-most column.
224 * @param y row coordinate. 0 is the top-most row.
225 * @return attributes at (x, y)
226 */
fca67db0 227 public final CellAttributes getAttrXY(final int x, final int y) {
7b5261bc 228 CellAttributes attr = new CellAttributes();
30bd4abd
KL
229 if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
230 attr.setTo(logical[x][y]);
231 }
7b5261bc 232 return attr;
df8de03f
KL
233 }
234
235 /**
236 * Set the attributes at one location.
237 *
238 * @param x column coordinate. 0 is the left-most column.
239 * @param y row coordinate. 0 is the top-most row.
240 * @param attr attributes to use (bold, foreColor, backColor)
df8de03f 241 */
fca67db0
KL
242 public final void putAttrXY(final int x, final int y,
243 final CellAttributes attr) {
244
7b5261bc 245 putAttrXY(x, y, attr, true);
df8de03f 246 }
7b5261bc 247
df8de03f
KL
248 /**
249 * Set the attributes at one location.
250 *
251 * @param x column coordinate. 0 is the left-most column.
252 * @param y row coordinate. 0 is the top-most row.
253 * @param attr attributes to use (bold, foreColor, backColor)
254 * @param clip if true, honor clipping/offset
255 */
87a17f3c
KL
256 public final void putAttrXY(final int x, final int y
257 , final CellAttributes attr, final boolean clip) {
7b5261bc
KL
258
259 int X = x;
260 int Y = y;
261
262 if (clip) {
263 if ((x < clipLeft)
264 || (x >= clipRight)
265 || (y < clipTop)
266 || (y >= clipBottom)
267 ) {
268 return;
269 }
270 X += offsetX;
271 Y += offsetY;
272 }
273
274 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
275 dirty = true;
276 logical[X][Y].setForeColor(attr.getForeColor());
277 logical[X][Y].setBackColor(attr.getBackColor());
7c870d89
KL
278 logical[X][Y].setBold(attr.isBold());
279 logical[X][Y].setBlink(attr.isBlink());
280 logical[X][Y].setReverse(attr.isReverse());
281 logical[X][Y].setUnderline(attr.isUnderline());
282 logical[X][Y].setProtect(attr.isProtect());
7b5261bc 283 }
df8de03f
KL
284 }
285
286 /**
287 * Fill the entire screen with one character with attributes.
288 *
289 * @param ch character to draw
290 * @param attr attributes to use (bold, foreColor, backColor)
291 */
fca67db0 292 public final void putAll(final char ch, final CellAttributes attr) {
87a17f3c 293
7b5261bc
KL
294 for (int x = 0; x < width; x++) {
295 for (int y = 0; y < height; y++) {
296 putCharXY(x, y, ch, attr);
297 }
298 }
df8de03f
KL
299 }
300
301 /**
302 * Render one character with attributes.
303 *
304 * @param x column coordinate. 0 is the left-most column.
305 * @param y row coordinate. 0 is the top-most row.
306 * @param ch character + attributes to draw
307 */
fca67db0 308 public final void putCharXY(final int x, final int y, final Cell ch) {
7b5261bc 309 putCharXY(x, y, ch.getChar(), ch);
df8de03f
KL
310 }
311
312 /**
313 * Render one character with attributes.
314 *
315 * @param x column coordinate. 0 is the left-most column.
316 * @param y row coordinate. 0 is the top-most row.
317 * @param ch character to draw
318 * @param attr attributes to use (bold, foreColor, backColor)
319 */
fca67db0 320 public final void putCharXY(final int x, final int y, final char ch,
7b5261bc
KL
321 final CellAttributes attr) {
322
323 if ((x < clipLeft)
324 || (x >= clipRight)
325 || (y < clipTop)
326 || (y >= clipBottom)
327 ) {
328 return;
329 }
330
331 int X = x + offsetX;
332 int Y = y + offsetY;
333
334 // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
335
336 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
337 dirty = true;
338
339 // Do not put control characters on the display
340 assert (ch >= 0x20);
341 assert (ch != 0x7F);
342
343 logical[X][Y].setChar(ch);
344 logical[X][Y].setForeColor(attr.getForeColor());
345 logical[X][Y].setBackColor(attr.getBackColor());
7c870d89
KL
346 logical[X][Y].setBold(attr.isBold());
347 logical[X][Y].setBlink(attr.isBlink());
348 logical[X][Y].setReverse(attr.isReverse());
349 logical[X][Y].setUnderline(attr.isUnderline());
350 logical[X][Y].setProtect(attr.isProtect());
7b5261bc 351 }
df8de03f
KL
352 }
353
354 /**
355 * Render one character without changing the underlying attributes.
356 *
357 * @param x column coordinate. 0 is the left-most column.
358 * @param y row coordinate. 0 is the top-most row.
359 * @param ch character to draw
360 */
fca67db0 361 public final void putCharXY(final int x, final int y, final char ch) {
87a17f3c 362
7b5261bc
KL
363 if ((x < clipLeft)
364 || (x >= clipRight)
365 || (y < clipTop)
366 || (y >= clipBottom)
367 ) {
368 return;
369 }
df8de03f 370
7b5261bc
KL
371 int X = x + offsetX;
372 int Y = y + offsetY;
df8de03f 373
7b5261bc 374 // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
df8de03f 375
7b5261bc
KL
376 if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
377 dirty = true;
378 logical[X][Y].setChar(ch);
379 }
df8de03f
KL
380 }
381
382 /**
383 * Render a string. Does not wrap if the string exceeds the line.
384 *
385 * @param x column coordinate. 0 is the left-most column.
386 * @param y row coordinate. 0 is the top-most row.
387 * @param str string to draw
388 * @param attr attributes to use (bold, foreColor, backColor)
389 */
0d47c546 390 public final void putStringXY(final int x, final int y, final String str,
7b5261bc
KL
391 final CellAttributes attr) {
392
393 int i = x;
394 for (int j = 0; j < str.length(); j++) {
395 char ch = str.charAt(j);
396 putCharXY(i, y, ch, attr);
397 i++;
398 if (i == width) {
399 break;
400 }
401 }
df8de03f
KL
402 }
403
404 /**
405 * Render a string without changing the underlying attribute. Does not
406 * wrap if the string exceeds the line.
407 *
408 * @param x column coordinate. 0 is the left-most column.
409 * @param y row coordinate. 0 is the top-most row.
410 * @param str string to draw
411 */
0d47c546 412 public final void putStringXY(final int x, final int y, final String str) {
87a17f3c 413
7b5261bc
KL
414 int i = x;
415 for (int j = 0; j < str.length(); j++) {
416 char ch = str.charAt(j);
417 putCharXY(i, y, ch);
418 i++;
419 if (i == width) {
420 break;
421 }
422 }
df8de03f
KL
423 }
424
425 /**
7b5261bc 426 * Draw a vertical line from (x, y) to (x, y + n).
df8de03f
KL
427 *
428 * @param x column coordinate. 0 is the left-most column.
429 * @param y row coordinate. 0 is the top-most row.
430 * @param n number of characters to draw
431 * @param ch character to draw
432 * @param attr attributes to use (bold, foreColor, backColor)
433 */
fca67db0
KL
434 public final void vLineXY(final int x, final int y, final int n,
435 final char ch, final CellAttributes attr) {
7b5261bc
KL
436
437 for (int i = y; i < y + n; i++) {
438 putCharXY(x, i, ch, attr);
439 }
df8de03f
KL
440 }
441
442 /**
7b5261bc 443 * Draw a horizontal line from (x, y) to (x + n, y).
df8de03f
KL
444 *
445 * @param x column coordinate. 0 is the left-most column.
446 * @param y row coordinate. 0 is the top-most row.
447 * @param n number of characters to draw
448 * @param ch character to draw
449 * @param attr attributes to use (bold, foreColor, backColor)
450 */
fca67db0
KL
451 public final void hLineXY(final int x, final int y, final int n,
452 final char ch, final CellAttributes attr) {
7b5261bc
KL
453
454 for (int i = x; i < x + n; i++) {
455 putCharXY(i, y, ch, attr);
456 }
df8de03f
KL
457 }
458
459 /**
460 * Reallocate screen buffers.
461 *
462 * @param width new width
463 * @param height new height
464 */
87a17f3c 465 private synchronized void reallocate(final int width, final int height) {
7b5261bc
KL
466 if (logical != null) {
467 for (int row = 0; row < this.height; row++) {
468 for (int col = 0; col < this.width; col++) {
469 logical[col][row] = null;
470 }
471 }
472 logical = null;
473 }
474 logical = new Cell[width][height];
475 if (physical != null) {
476 for (int row = 0; row < this.height; row++) {
477 for (int col = 0; col < this.width; col++) {
478 physical[col][row] = null;
479 }
480 }
481 physical = null;
482 }
483 physical = new Cell[width][height];
484
485 for (int row = 0; row < height; row++) {
486 for (int col = 0; col < width; col++) {
487 physical[col][row] = new Cell();
488 logical[col][row] = new Cell();
489 }
490 }
491
492 this.width = width;
493 this.height = height;
494
495 clipLeft = 0;
496 clipTop = 0;
497 clipRight = width;
498 clipBottom = height;
499
500 reallyCleared = true;
501 dirty = true;
df8de03f
KL
502 }
503
504 /**
505 * Change the width. Everything on-screen will be destroyed and must be
506 * redrawn.
7b5261bc 507 *
df8de03f
KL
508 * @param width new screen width
509 */
87a17f3c 510 public final synchronized void setWidth(final int width) {
7b5261bc 511 reallocate(width, this.height);
df8de03f
KL
512 }
513
514 /**
515 * Change the height. Everything on-screen will be destroyed and must be
516 * redrawn.
517 *
518 * @param height new screen height
519 */
87a17f3c 520 public final synchronized void setHeight(final int height) {
7b5261bc 521 reallocate(this.width, height);
df8de03f
KL
522 }
523
524 /**
525 * Change the width and height. Everything on-screen will be destroyed
526 * and must be redrawn.
527 *
528 * @param width new screen width
529 * @param height new screen height
530 */
fca67db0 531 public final void setDimensions(final int width, final int height) {
7b5261bc 532 reallocate(width, height);
df8de03f
KL
533 }
534
535 /**
536 * Get the height.
537 *
538 * @return current screen height
539 */
87a17f3c 540 public final synchronized int getHeight() {
7b5261bc 541 return this.height;
df8de03f
KL
542 }
543
544 /**
545 * Get the width.
546 *
547 * @return current screen width
548 */
87a17f3c 549 public final synchronized int getWidth() {
7b5261bc 550 return this.width;
df8de03f
KL
551 }
552
553 /**
554 * Public constructor. Sets everything to not-bold, white-on-black.
555 */
fca67db0 556 protected Screen() {
7b5261bc
KL
557 offsetX = 0;
558 offsetY = 0;
559 width = 80;
560 height = 24;
561 logical = null;
562 physical = null;
563 reallocate(width, height);
df8de03f
KL
564 }
565
566 /**
567 * Reset screen to not-bold, white-on-black. Also flushes the offset and
568 * clip variables.
569 */
87a17f3c 570 public final synchronized void reset() {
7b5261bc
KL
571 dirty = true;
572 for (int row = 0; row < height; row++) {
573 for (int col = 0; col < width; col++) {
574 logical[col][row].reset();
575 }
576 }
577 resetClipping();
df8de03f
KL
578 }
579
580 /**
581 * Flush the offset and clip variables.
582 */
fca67db0 583 public final void resetClipping() {
7b5261bc
KL
584 offsetX = 0;
585 offsetY = 0;
586 clipLeft = 0;
587 clipTop = 0;
588 clipRight = width;
589 clipBottom = height;
df8de03f
KL
590 }
591
592 /**
bd8d51fa 593 * Clear the logical screen.
df8de03f 594 */
fca67db0 595 public final void clear() {
7b5261bc 596 reset();
df8de03f
KL
597 }
598
bd8d51fa
KL
599 /**
600 * Clear the physical screen.
601 */
602 public final void clearPhysical() {
603 dirty = true;
604 for (int row = 0; row < height; row++) {
605 for (int col = 0; col < width; col++) {
606 physical[col][row].reset();
607 }
608 }
609 }
610
df8de03f
KL
611 /**
612 * Draw a box with a border and empty background.
613 *
614 * @param left left column of box. 0 is the left-most row.
615 * @param top top row of the box. 0 is the top-most row.
616 * @param right right column of box
617 * @param bottom bottom row of the box
7b5261bc 618 * @param border attributes to use for the border
df8de03f
KL
619 * @param background attributes to use for the background
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
625 drawBox(left, top, right, bottom, border, background, 1, false);
df8de03f
KL
626 }
627
628 /**
629 * Draw a box with a border and empty background.
630 *
631 * @param left left column of box. 0 is the left-most row.
632 * @param top top row of the box. 0 is the top-most row.
633 * @param right right column of box
634 * @param bottom bottom row of the box
7b5261bc 635 * @param border attributes to use for the border
df8de03f 636 * @param background attributes to use for the background
7b5261bc
KL
637 * @param borderType if 1, draw a single-line border; if 2, draw a
638 * double-line border; if 3, draw double-line top/bottom edges and
639 * single-line left/right edges (like Qmodem)
df8de03f
KL
640 * @param shadow if true, draw a "shadow" on the box
641 */
fca67db0 642 public final void drawBox(final int left, final int top,
7b5261bc
KL
643 final int right, final int bottom,
644 final CellAttributes border, final CellAttributes background,
645 final int borderType, final boolean shadow) {
646
7b5261bc
KL
647 int boxWidth = right - left;
648 int boxHeight = bottom - top;
649
650 char cTopLeft;
651 char cTopRight;
652 char cBottomLeft;
653 char cBottomRight;
654 char cHSide;
655 char cVSide;
656
657 switch (borderType) {
658 case 1:
659 cTopLeft = GraphicsChars.ULCORNER;
660 cTopRight = GraphicsChars.URCORNER;
661 cBottomLeft = GraphicsChars.LLCORNER;
662 cBottomRight = GraphicsChars.LRCORNER;
663 cHSide = GraphicsChars.SINGLE_BAR;
664 cVSide = GraphicsChars.WINDOW_SIDE;
665 break;
666
667 case 2:
668 cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE;
669 cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE;
670 cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE;
671 cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE;
672 cHSide = GraphicsChars.DOUBLE_BAR;
673 cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE;
674 break;
675
676 case 3:
677 cTopLeft = GraphicsChars.WINDOW_LEFT_TOP;
678 cTopRight = GraphicsChars.WINDOW_RIGHT_TOP;
679 cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM;
680 cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM;
681 cHSide = GraphicsChars.WINDOW_TOP;
682 cVSide = GraphicsChars.WINDOW_SIDE;
683 break;
684 default:
685 throw new IllegalArgumentException("Invalid border type: "
686 + borderType);
687 }
688
689 // Place the corner characters
690 putCharXY(left, top, cTopLeft, border);
691 putCharXY(left + boxWidth - 1, top, cTopRight, border);
692 putCharXY(left, top + boxHeight - 1, cBottomLeft, border);
693 putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight,
694 border);
695
696 // Draw the box lines
697 hLineXY(left + 1, top, boxWidth - 2, cHSide, border);
698 vLineXY(left, top + 1, boxHeight - 2, cVSide, border);
699 hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border);
700 vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border);
701
702 // Fill in the interior background
703 for (int i = 1; i < boxHeight - 1; i++) {
704 hLineXY(1 + left, i + top, boxWidth - 2, ' ', background);
705 }
706
707 if (shadow) {
708 // Draw a shadow
709 drawBoxShadow(left, top, right, bottom);
710 }
df8de03f
KL
711 }
712
713 /**
fca67db0 714 * Draw a box shadow.
df8de03f
KL
715 *
716 * @param left left column of box. 0 is the left-most row.
717 * @param top top row of the box. 0 is the top-most row.
718 * @param right right column of box
719 * @param bottom bottom row of the box
720 */
fca67db0 721 public final void drawBoxShadow(final int left, final int top,
7b5261bc
KL
722 final int right, final int bottom) {
723
724 int boxTop = top;
725 int boxLeft = left;
726 int boxWidth = right - left;
727 int boxHeight = bottom - top;
728 CellAttributes shadowAttr = new CellAttributes();
729
730 // Shadows do not honor clipping but they DO honor offset.
731 int oldClipRight = clipRight;
732 int oldClipBottom = clipBottom;
733 /*
734 clipRight = boxWidth + 2;
735 clipBottom = boxHeight + 1;
736 */
737 clipRight = width;
738 clipBottom = height;
739
740 for (int i = 0; i < boxHeight; i++) {
741 putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr);
742 putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr);
743 }
744 for (int i = 0; i < boxWidth; i++) {
745 putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr);
746 }
747 clipRight = oldClipRight;
748 clipBottom = oldClipBottom;
df8de03f
KL
749 }
750
751 /**
752 * Subclasses must provide an implementation to push the logical screen
753 * to the physical device.
754 */
30bd4abd 755 public abstract void flushPhysical();
df8de03f
KL
756
757 /**
758 * Put the cursor at (x,y).
759 *
760 * @param visible if true, the cursor should be visible
761 * @param x column coordinate to put the cursor on
762 * @param y row coordinate to put the cursor on
763 */
30bd4abd 764 public void putCursor(final boolean visible, final int x, final int y) {
fca67db0 765
7b5261bc
KL
766 cursorVisible = visible;
767 cursorX = x;
768 cursorY = y;
df8de03f
KL
769 }
770
771 /**
fca67db0 772 * Hide the cursor.
df8de03f 773 */
fca67db0 774 public final void hideCursor() {
7b5261bc 775 cursorVisible = false;
df8de03f
KL
776 }
777}