2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 Kevin Lamonte
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 package jexer
.backend
;
31 import java
.util
.LinkedList
;
32 import java
.util
.List
;
34 import jexer
.bits
.Cell
;
35 import jexer
.bits
.CellAttributes
;
38 * MultiScreen mirrors its I/O to several screens.
40 public class MultiScreen
implements Screen
{
43 * The list of screens to use.
45 private List
<Screen
> screens
= new LinkedList
<Screen
>();
48 * Public constructor requires one screen.
50 * @param screen the screen to add
52 public MultiScreen(final Screen screen
) {
57 * Add a screen to the list.
59 * @param screen the screen to add
61 public void addScreen(final Screen screen
) {
66 * Remove a screen from the list.
68 * @param screen the screen to remove
70 public void removeScreen(final Screen screen
) {
71 if (screens
.size() > 1) {
72 screens
.remove(screen
);
77 * Set drawing offset for x.
79 * @param offsetX new drawing offset
81 public void setOffsetX(final int offsetX
) {
82 for (Screen screen
: screens
) {
83 screen
.setOffsetX(offsetX
);
88 * Set drawing offset for y.
90 * @param offsetY new drawing offset
92 public void setOffsetY(final int offsetY
) {
93 for (Screen screen
: screens
) {
94 screen
.setOffsetY(offsetY
);
99 * Get right drawing clipping boundary.
101 * @return drawing boundary
103 public int getClipRight() {
104 return screens
.get(0).getClipRight();
108 * Set right drawing clipping boundary.
110 * @param clipRight new boundary
112 public void setClipRight(final int clipRight
) {
113 for (Screen screen
: screens
) {
114 screen
.setClipRight(clipRight
);
119 * Get bottom drawing clipping boundary.
121 * @return drawing boundary
123 public int getClipBottom() {
124 return screens
.get(0).getClipBottom();
128 * Set bottom drawing clipping boundary.
130 * @param clipBottom new boundary
132 public void setClipBottom(final int clipBottom
) {
133 for (Screen screen
: screens
) {
134 screen
.setClipBottom(clipBottom
);
139 * Get left drawing clipping boundary.
141 * @return drawing boundary
143 public int getClipLeft() {
144 return screens
.get(0).getClipLeft();
148 * Set left drawing clipping boundary.
150 * @param clipLeft new boundary
152 public void setClipLeft(final int clipLeft
) {
153 for (Screen screen
: screens
) {
154 screen
.setClipLeft(clipLeft
);
159 * Get top drawing clipping boundary.
161 * @return drawing boundary
163 public int getClipTop() {
164 return screens
.get(0).getClipTop();
168 * Set top drawing clipping boundary.
170 * @param clipTop new boundary
172 public void setClipTop(final int clipTop
) {
173 for (Screen screen
: screens
) {
174 screen
.setClipTop(clipTop
);
181 * @return if true, the logical screen is not in sync with the physical
184 public boolean isDirty() {
185 for (Screen screen
: screens
) {
186 if (screen
.isDirty()) {
194 * Get the attributes at one location.
196 * @param x column coordinate. 0 is the left-most column.
197 * @param y row coordinate. 0 is the top-most row.
198 * @return attributes at (x, y)
200 public CellAttributes
getAttrXY(final int x
, final int y
) {
201 return screens
.get(0).getAttrXY(x
, y
);
205 * Get the cell at one location.
207 * @param x column coordinate. 0 is the left-most column.
208 * @param y row coordinate. 0 is the top-most row.
209 * @return the character + attributes
211 public Cell
getCharXY(final int x
, final int y
) {
212 return screens
.get(0).getCharXY(x
, y
);
216 * Set the attributes at one location.
218 * @param x column coordinate. 0 is the left-most column.
219 * @param y row coordinate. 0 is the top-most row.
220 * @param attr attributes to use (bold, foreColor, backColor)
222 public void putAttrXY(final int x
, final int y
,
223 final CellAttributes attr
) {
225 for (Screen screen
: screens
) {
226 screen
.putAttrXY(x
, y
, attr
);
231 * Set the attributes at one location.
233 * @param x column coordinate. 0 is the left-most column.
234 * @param y row coordinate. 0 is the top-most row.
235 * @param attr attributes to use (bold, foreColor, backColor)
236 * @param clip if true, honor clipping/offset
238 public void putAttrXY(final int x
, final int y
,
239 final CellAttributes attr
, final boolean clip
) {
241 for (Screen screen
: screens
) {
242 screen
.putAttrXY(x
, y
, attr
, clip
);
247 * Fill the entire screen with one character with attributes.
249 * @param ch character to draw
250 * @param attr attributes to use (bold, foreColor, backColor)
252 public void putAll(final char ch
, final CellAttributes attr
) {
253 for (Screen screen
: screens
) {
254 screen
.putAll(ch
, attr
);
259 * Render one character with attributes.
261 * @param x column coordinate. 0 is the left-most column.
262 * @param y row coordinate. 0 is the top-most row.
263 * @param ch character + attributes to draw
265 public void putCharXY(final int x
, final int y
, final Cell ch
) {
266 for (Screen screen
: screens
) {
267 screen
.putCharXY(x
, y
, ch
);
272 * Render one character with attributes.
274 * @param x column coordinate. 0 is the left-most column.
275 * @param y row coordinate. 0 is the top-most row.
276 * @param ch character to draw
277 * @param attr attributes to use (bold, foreColor, backColor)
279 public void putCharXY(final int x
, final int y
, final char ch
,
280 final CellAttributes attr
) {
282 for (Screen screen
: screens
) {
283 screen
.putCharXY(x
, y
, ch
, attr
);
288 * Render one character without changing the underlying attributes.
290 * @param x column coordinate. 0 is the left-most column.
291 * @param y row coordinate. 0 is the top-most row.
292 * @param ch character to draw
294 public void putCharXY(final int x
, final int y
, final char ch
) {
295 for (Screen screen
: screens
) {
296 screen
.putCharXY(x
, y
, ch
);
301 * Render a string. Does not wrap if the string exceeds the line.
303 * @param x column coordinate. 0 is the left-most column.
304 * @param y row coordinate. 0 is the top-most row.
305 * @param str string to draw
306 * @param attr attributes to use (bold, foreColor, backColor)
308 public void putStringXY(final int x
, final int y
, final String str
,
309 final CellAttributes attr
) {
311 for (Screen screen
: screens
) {
312 screen
.putStringXY(x
, y
, str
, attr
);
317 * Render a string without changing the underlying attribute. Does not
318 * wrap if the string exceeds the line.
320 * @param x column coordinate. 0 is the left-most column.
321 * @param y row coordinate. 0 is the top-most row.
322 * @param str string to draw
324 public void putStringXY(final int x
, final int y
, final String str
) {
325 for (Screen screen
: screens
) {
326 screen
.putStringXY(x
, y
, str
);
331 * Draw a vertical line from (x, y) to (x, y + n).
333 * @param x column coordinate. 0 is the left-most column.
334 * @param y row coordinate. 0 is the top-most row.
335 * @param n number of characters to draw
336 * @param ch character to draw
337 * @param attr attributes to use (bold, foreColor, backColor)
339 public void vLineXY(final int x
, final int y
, final int n
,
340 final char ch
, final CellAttributes attr
) {
342 for (Screen screen
: screens
) {
343 screen
.vLineXY(x
, y
, n
, ch
, attr
);
348 * Draw a horizontal line from (x, y) to (x + n, y).
350 * @param x column coordinate. 0 is the left-most column.
351 * @param y row coordinate. 0 is the top-most row.
352 * @param n number of characters to draw
353 * @param ch character to draw
354 * @param attr attributes to use (bold, foreColor, backColor)
356 public void hLineXY(final int x
, final int y
, final int n
,
357 final char ch
, final CellAttributes attr
) {
359 for (Screen screen
: screens
) {
360 screen
.hLineXY(x
, y
, n
, ch
, attr
);
365 * Change the width. Everything on-screen will be destroyed and must be
368 * @param width new screen width
370 public void setWidth(final int width
) {
371 for (Screen screen
: screens
) {
372 screen
.setWidth(width
);
377 * Change the height. Everything on-screen will be destroyed and must be
380 * @param height new screen height
382 public void setHeight(final int height
) {
383 for (Screen screen
: screens
) {
384 screen
.setHeight(height
);
389 * Change the width and height. Everything on-screen will be destroyed
390 * and must be redrawn.
392 * @param width new screen width
393 * @param height new screen height
395 public void setDimensions(final int width
, final int height
) {
396 for (Screen screen
: screens
) {
397 screen
.setDimensions(width
, height
);
404 * @return current screen height
406 public int getHeight() {
407 return screens
.get(0).getHeight();
413 * @return current screen width
415 public int getWidth() {
416 return screens
.get(0).getWidth();
420 * Reset screen to not-bold, white-on-black. Also flushes the offset and
423 public void reset() {
424 for (Screen screen
: screens
) {
430 * Flush the offset and clip variables.
432 public void resetClipping() {
433 for (Screen screen
: screens
) {
434 screen
.resetClipping();
439 * Clear the logical screen.
441 public void clear() {
442 for (Screen screen
: screens
) {
448 * Draw a box with a border and empty background.
450 * @param left left column of box. 0 is the left-most row.
451 * @param top top row of the box. 0 is the top-most row.
452 * @param right right column of box
453 * @param bottom bottom row of the box
454 * @param border attributes to use for the border
455 * @param background attributes to use for the background
457 public void drawBox(final int left
, final int top
,
458 final int right
, final int bottom
,
459 final CellAttributes border
, final CellAttributes background
) {
461 for (Screen screen
: screens
) {
462 screen
.drawBox(left
, top
, right
, bottom
, border
, background
);
467 * Draw a box with a border and empty background.
469 * @param left left column of box. 0 is the left-most row.
470 * @param top top row of the box. 0 is the top-most row.
471 * @param right right column of box
472 * @param bottom bottom row of the box
473 * @param border attributes to use for the border
474 * @param background attributes to use for the background
475 * @param borderType if 1, draw a single-line border; if 2, draw a
476 * double-line border; if 3, draw double-line top/bottom edges and
477 * single-line left/right edges (like Qmodem)
478 * @param shadow if true, draw a "shadow" on the box
480 public void drawBox(final int left
, final int top
,
481 final int right
, final int bottom
,
482 final CellAttributes border
, final CellAttributes background
,
483 final int borderType
, final boolean shadow
) {
485 for (Screen screen
: screens
) {
486 screen
.drawBox(left
, top
, right
, bottom
, border
, background
,
494 * @param left left column of box. 0 is the left-most row.
495 * @param top top row of the box. 0 is the top-most row.
496 * @param right right column of box
497 * @param bottom bottom row of the box
499 public void drawBoxShadow(final int left
, final int top
,
500 final int right
, final int bottom
) {
502 for (Screen screen
: screens
) {
503 screen
.drawBoxShadow(left
, top
, right
, bottom
);
508 * Classes must provide an implementation to push the logical screen to
509 * the physical device.
511 public void flushPhysical() {
512 for (Screen screen
: screens
) {
513 screen
.flushPhysical();
518 * Put the cursor at (x,y).
520 * @param visible if true, the cursor should be visible
521 * @param x column coordinate to put the cursor on
522 * @param y row coordinate to put the cursor on
524 public void putCursor(final boolean visible
, final int x
, final int y
) {
525 for (Screen screen
: screens
) {
526 screen
.putCursor(visible
, x
, y
);
533 public void hideCursor() {
534 for (Screen screen
: screens
) {
540 * Get the cursor visibility.
542 * @return true if the cursor is visible
544 public boolean isCursorVisible() {
545 return screens
.get(0).isCursorVisible();
549 * Get the cursor X position.
551 * @return the cursor x column position
553 public int getCursorX() {
554 return screens
.get(0).getCursorX();
558 * Get the cursor Y position.
560 * @return the cursor y row position
562 public int getCursorY() {
563 return screens
.get(0).getCursorY();
567 * Set the window title.
569 * @param title the new title
571 public void setTitle(final String title
) {
572 for (Screen screen
: screens
) {
573 screen
.setTitle(title
);