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 return screens
.get(0).isDirty();
189 * Get the attributes at one location.
191 * @param x column coordinate. 0 is the left-most column.
192 * @param y row coordinate. 0 is the top-most row.
193 * @return attributes at (x, y)
195 public CellAttributes
getAttrXY(final int x
, final int y
) {
196 return screens
.get(0).getAttrXY(x
, y
);
200 * Get the cell at one location.
202 * @param x column coordinate. 0 is the left-most column.
203 * @param y row coordinate. 0 is the top-most row.
204 * @return the character + attributes
206 public Cell
getCharXY(final int x
, final int y
) {
207 return screens
.get(0).getCharXY(x
, y
);
211 * Set the attributes at one location.
213 * @param x column coordinate. 0 is the left-most column.
214 * @param y row coordinate. 0 is the top-most row.
215 * @param attr attributes to use (bold, foreColor, backColor)
217 public void putAttrXY(final int x
, final int y
,
218 final CellAttributes attr
) {
220 for (Screen screen
: screens
) {
221 screen
.putAttrXY(x
, y
, attr
);
226 * Set the attributes at one location.
228 * @param x column coordinate. 0 is the left-most column.
229 * @param y row coordinate. 0 is the top-most row.
230 * @param attr attributes to use (bold, foreColor, backColor)
231 * @param clip if true, honor clipping/offset
233 public void putAttrXY(final int x
, final int y
,
234 final CellAttributes attr
, final boolean clip
) {
236 for (Screen screen
: screens
) {
237 screen
.putAttrXY(x
, y
, attr
, clip
);
242 * Fill the entire screen with one character with attributes.
244 * @param ch character to draw
245 * @param attr attributes to use (bold, foreColor, backColor)
247 public void putAll(final char ch
, final CellAttributes attr
) {
248 for (Screen screen
: screens
) {
249 screen
.putAll(ch
, attr
);
254 * Render one character with attributes.
256 * @param x column coordinate. 0 is the left-most column.
257 * @param y row coordinate. 0 is the top-most row.
258 * @param ch character + attributes to draw
260 public void putCharXY(final int x
, final int y
, final Cell ch
) {
261 for (Screen screen
: screens
) {
262 screen
.putCharXY(x
, y
, ch
);
267 * Render one character with attributes.
269 * @param x column coordinate. 0 is the left-most column.
270 * @param y row coordinate. 0 is the top-most row.
271 * @param ch character to draw
272 * @param attr attributes to use (bold, foreColor, backColor)
274 public void putCharXY(final int x
, final int y
, final char ch
,
275 final CellAttributes attr
) {
277 for (Screen screen
: screens
) {
278 screen
.putCharXY(x
, y
, ch
, attr
);
283 * Render one character without changing the underlying attributes.
285 * @param x column coordinate. 0 is the left-most column.
286 * @param y row coordinate. 0 is the top-most row.
287 * @param ch character to draw
289 public void putCharXY(final int x
, final int y
, final char ch
) {
290 for (Screen screen
: screens
) {
291 screen
.putCharXY(x
, y
, ch
);
296 * Render a string. Does not wrap if the string exceeds the line.
298 * @param x column coordinate. 0 is the left-most column.
299 * @param y row coordinate. 0 is the top-most row.
300 * @param str string to draw
301 * @param attr attributes to use (bold, foreColor, backColor)
303 public void putStringXY(final int x
, final int y
, final String str
,
304 final CellAttributes attr
) {
306 for (Screen screen
: screens
) {
307 screen
.putStringXY(x
, y
, str
, attr
);
312 * Render a string without changing the underlying attribute. Does not
313 * wrap if the string exceeds the line.
315 * @param x column coordinate. 0 is the left-most column.
316 * @param y row coordinate. 0 is the top-most row.
317 * @param str string to draw
319 public void putStringXY(final int x
, final int y
, final String str
) {
320 for (Screen screen
: screens
) {
321 screen
.putStringXY(x
, y
, str
);
326 * Draw a vertical line from (x, y) to (x, y + n).
328 * @param x column coordinate. 0 is the left-most column.
329 * @param y row coordinate. 0 is the top-most row.
330 * @param n number of characters to draw
331 * @param ch character to draw
332 * @param attr attributes to use (bold, foreColor, backColor)
334 public void vLineXY(final int x
, final int y
, final int n
,
335 final char ch
, final CellAttributes attr
) {
337 for (Screen screen
: screens
) {
338 screen
.vLineXY(x
, y
, n
, ch
, attr
);
343 * Draw a horizontal line from (x, y) to (x + n, y).
345 * @param x column coordinate. 0 is the left-most column.
346 * @param y row coordinate. 0 is the top-most row.
347 * @param n number of characters to draw
348 * @param ch character to draw
349 * @param attr attributes to use (bold, foreColor, backColor)
351 public void hLineXY(final int x
, final int y
, final int n
,
352 final char ch
, final CellAttributes attr
) {
354 for (Screen screen
: screens
) {
355 screen
.hLineXY(x
, y
, n
, ch
, attr
);
360 * Change the width. Everything on-screen will be destroyed and must be
363 * @param width new screen width
365 public void setWidth(final int width
) {
366 for (Screen screen
: screens
) {
367 screen
.setWidth(width
);
372 * Change the height. Everything on-screen will be destroyed and must be
375 * @param height new screen height
377 public void setHeight(final int height
) {
378 for (Screen screen
: screens
) {
379 screen
.setHeight(height
);
384 * Change the width and height. Everything on-screen will be destroyed
385 * and must be redrawn.
387 * @param width new screen width
388 * @param height new screen height
390 public void setDimensions(final int width
, final int height
) {
391 for (Screen screen
: screens
) {
392 screen
.setDimensions(width
, height
);
399 * @return current screen height
401 public int getHeight() {
402 return screens
.get(0).getHeight();
408 * @return current screen width
410 public int getWidth() {
411 return screens
.get(0).getWidth();
415 * Reset screen to not-bold, white-on-black. Also flushes the offset and
418 public void reset() {
419 for (Screen screen
: screens
) {
425 * Flush the offset and clip variables.
427 public void resetClipping() {
428 for (Screen screen
: screens
) {
429 screen
.resetClipping();
434 * Clear the logical screen.
436 public void clear() {
437 for (Screen screen
: screens
) {
443 * Draw a box with a border and empty background.
445 * @param left left column of box. 0 is the left-most row.
446 * @param top top row of the box. 0 is the top-most row.
447 * @param right right column of box
448 * @param bottom bottom row of the box
449 * @param border attributes to use for the border
450 * @param background attributes to use for the background
452 public void drawBox(final int left
, final int top
,
453 final int right
, final int bottom
,
454 final CellAttributes border
, final CellAttributes background
) {
456 for (Screen screen
: screens
) {
457 screen
.drawBox(left
, top
, right
, bottom
, border
, background
);
462 * Draw a box with a border and empty background.
464 * @param left left column of box. 0 is the left-most row.
465 * @param top top row of the box. 0 is the top-most row.
466 * @param right right column of box
467 * @param bottom bottom row of the box
468 * @param border attributes to use for the border
469 * @param background attributes to use for the background
470 * @param borderType if 1, draw a single-line border; if 2, draw a
471 * double-line border; if 3, draw double-line top/bottom edges and
472 * single-line left/right edges (like Qmodem)
473 * @param shadow if true, draw a "shadow" on the box
475 public void drawBox(final int left
, final int top
,
476 final int right
, final int bottom
,
477 final CellAttributes border
, final CellAttributes background
,
478 final int borderType
, final boolean shadow
) {
480 for (Screen screen
: screens
) {
481 screen
.drawBox(left
, top
, right
, bottom
, border
, background
,
489 * @param left left column of box. 0 is the left-most row.
490 * @param top top row of the box. 0 is the top-most row.
491 * @param right right column of box
492 * @param bottom bottom row of the box
494 public void drawBoxShadow(final int left
, final int top
,
495 final int right
, final int bottom
) {
497 for (Screen screen
: screens
) {
498 screen
.drawBoxShadow(left
, top
, right
, bottom
);
503 * Classes must provide an implementation to push the logical screen to
504 * the physical device.
506 public void flushPhysical() {
507 for (Screen screen
: screens
) {
508 screen
.flushPhysical();
513 * Put the cursor at (x,y).
515 * @param visible if true, the cursor should be visible
516 * @param x column coordinate to put the cursor on
517 * @param y row coordinate to put the cursor on
519 public void putCursor(final boolean visible
, final int x
, final int y
) {
520 for (Screen screen
: screens
) {
521 screen
.putCursor(visible
, x
, y
);
528 public void hideCursor() {
529 for (Screen screen
: screens
) {
535 * Get the cursor visibility.
537 * @return true if the cursor is visible
539 public boolean isCursorVisible() {
540 return screens
.get(0).isCursorVisible();
544 * Get the cursor X position.
546 * @return the cursor x column position
548 public int getCursorX() {
549 return screens
.get(0).getCursorX();
553 * Get the cursor Y position.
555 * @return the cursor y row position
557 public int getCursorY() {
558 return screens
.get(0).getCursorY();
562 * Set the window title.
564 * @param title the new title
566 public void setTitle(final String title
) {
567 for (Screen screen
: screens
) {
568 screen
.setTitle(title
);