X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2Fbackend%2FMultiScreen.java;h=45741c05f15853eb336738267508cd1fd62e32ee;hb=505be508ae7d3fb48122be548b310a238cfb91eb;hp=735faace1a130576b28e6fd8d8f667a9acc36510;hpb=be72cb5ccbd42fe304c0acafc380c5636f0d03a2;p=fanfix.git diff --git a/src/jexer/backend/MultiScreen.java b/src/jexer/backend/MultiScreen.java index 735faac..45741c0 100644 --- a/src/jexer/backend/MultiScreen.java +++ b/src/jexer/backend/MultiScreen.java @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (C) 2017 Kevin Lamonte + * Copyright (C) 2019 Kevin Lamonte * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,21 +28,30 @@ */ package jexer.backend; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import jexer.bits.Cell; import jexer.bits.CellAttributes; +import jexer.bits.Clipboard; /** * MultiScreen mirrors its I/O to several screens. */ public class MultiScreen implements Screen { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The list of screens to use. */ - private List screens = new LinkedList(); + private List screens = new ArrayList(); + + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor requires one screen. @@ -53,25 +62,9 @@ public class MultiScreen implements Screen { screens.add(screen); } - /** - * Add a screen to the list. - * - * @param screen the screen to add - */ - public void addScreen(final Screen screen) { - screens.add(screen); - } - - /** - * Remove a screen from the list. - * - * @param screen the screen to remove - */ - public void removeScreen(final Screen screen) { - if (screens.size() > 1) { - screens.remove(screen); - } - } + // ------------------------------------------------------------------------ + // Screen ----------------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Set drawing offset for x. @@ -101,7 +94,10 @@ public class MultiScreen implements Screen { * @return drawing boundary */ public int getClipRight() { - return screens.get(0).getClipRight(); + if (screens.size() > 0) { + return screens.get(0).getClipRight(); + } + return 0; } /** @@ -121,7 +117,10 @@ public class MultiScreen implements Screen { * @return drawing boundary */ public int getClipBottom() { - return screens.get(0).getClipBottom(); + if (screens.size() > 0) { + return screens.get(0).getClipBottom(); + } + return 0; } /** @@ -141,7 +140,10 @@ public class MultiScreen implements Screen { * @return drawing boundary */ public int getClipLeft() { - return screens.get(0).getClipLeft(); + if (screens.size() > 0) { + return screens.get(0).getClipLeft(); + } + return 0; } /** @@ -161,7 +163,10 @@ public class MultiScreen implements Screen { * @return drawing boundary */ public int getClipTop() { - return screens.get(0).getClipTop(); + if (screens.size() > 0) { + return screens.get(0).getClipTop(); + } + return 0; } /** @@ -198,7 +203,10 @@ public class MultiScreen implements Screen { * @return attributes at (x, y) */ public CellAttributes getAttrXY(final int x, final int y) { - return screens.get(0).getAttrXY(x, y); + if (screens.size() > 0) { + return screens.get(0).getAttrXY(x, y); + } + return new CellAttributes(); } /** @@ -209,7 +217,10 @@ public class MultiScreen implements Screen { * @return the character + attributes */ public Cell getCharXY(final int x, final int y) { - return screens.get(0).getCharXY(x, y); + if (screens.size() > 0) { + return screens.get(0).getCharXY(x, y); + } + return new Cell(); } /** @@ -249,7 +260,7 @@ public class MultiScreen implements Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void putAll(final char ch, final CellAttributes attr) { + public void putAll(final int ch, final CellAttributes attr) { for (Screen screen: screens) { screen.putAll(ch, attr); } @@ -276,7 +287,7 @@ public class MultiScreen implements Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void putCharXY(final int x, final int y, final char ch, + public void putCharXY(final int x, final int y, final int ch, final CellAttributes attr) { for (Screen screen: screens) { @@ -291,7 +302,7 @@ public class MultiScreen implements Screen { * @param y row coordinate. 0 is the top-most row. * @param ch character to draw */ - public void putCharXY(final int x, final int y, final char ch) { + public void putCharXY(final int x, final int y, final int ch) { for (Screen screen: screens) { screen.putCharXY(x, y, ch); } @@ -337,7 +348,7 @@ public class MultiScreen implements Screen { * @param attr attributes to use (bold, foreColor, backColor) */ public void vLineXY(final int x, final int y, final int n, - final char ch, final CellAttributes attr) { + final int ch, final CellAttributes attr) { for (Screen screen: screens) { screen.vLineXY(x, y, n, ch, attr); @@ -354,7 +365,7 @@ public class MultiScreen implements Screen { * @param attr attributes to use (bold, foreColor, backColor) */ public void hLineXY(final int x, final int y, final int n, - final char ch, final CellAttributes attr) { + final int ch, final CellAttributes attr) { for (Screen screen: screens) { screen.hLineXY(x, y, n, ch, attr); @@ -394,7 +405,20 @@ public class MultiScreen implements Screen { */ public void setDimensions(final int width, final int height) { for (Screen screen: screens) { - screen.setDimensions(width, height); + // Do not blindly call setDimension() on every screen. Instead + // call it only on those screens that do not already have the + // requested dimension. With this very small check, we have the + // ability for ANY screen in the MultiBackend to resize ALL of + // the screens. + if ((screen.getWidth() != width) + || (screen.getHeight() != height) + ) { + screen.setDimensions(width, height); + } else { + // The screen that didn't change is probably the one that + // prompted the resize. Force it to repaint. + screen.clearPhysical(); + } } } @@ -404,7 +428,17 @@ public class MultiScreen implements Screen { * @return current screen height */ public int getHeight() { - return screens.get(0).getHeight(); + // Return the smallest height of the screens. + int height = 25; + if (screens.size() > 0) { + height = screens.get(0).getHeight(); + } + for (Screen screen: screens) { + if (screen.getHeight() < height) { + height = screen.getHeight(); + } + } + return height; } /** @@ -413,7 +447,17 @@ public class MultiScreen implements Screen { * @return current screen width */ public int getWidth() { - return screens.get(0).getWidth(); + // Return the smallest width of the screens. + int width = 80; + if (screens.size() > 0) { + width = screens.get(0).getWidth(); + } + for (Screen screen: screens) { + if (screen.getWidth() < width) { + width = screen.getWidth(); + } + } + return width; } /** @@ -504,6 +548,27 @@ public class MultiScreen implements Screen { } } + /** + * Clear the physical screen. + */ + public void clearPhysical() { + for (Screen screen: screens) { + screen.clearPhysical(); + } + } + + /** + * Unset every image cell on one row of the physical screen, forcing + * images on that row to be redrawn. + * + * @param y row coordinate. 0 is the top-most row. + */ + public final void unsetImageRow(final int y) { + for (Screen screen: screens) { + screen.unsetImageRow(y); + } + } + /** * Classes must provide an implementation to push the logical screen to * the physical device. @@ -542,7 +607,10 @@ public class MultiScreen implements Screen { * @return true if the cursor is visible */ public boolean isCursorVisible() { - return screens.get(0).isCursorVisible(); + if (screens.size() > 0) { + return screens.get(0).isCursorVisible(); + } + return true; } /** @@ -551,7 +619,10 @@ public class MultiScreen implements Screen { * @return the cursor x column position */ public int getCursorX() { - return screens.get(0).getCursorX(); + if (screens.size() > 0) { + return screens.get(0).getCursorX(); + } + return 0; } /** @@ -560,7 +631,10 @@ public class MultiScreen implements Screen { * @return the cursor y row position */ public int getCursorY() { - return screens.get(0).getCursorY(); + if (screens.size() > 0) { + return screens.get(0).getCursorY(); + } + return 0; } /** @@ -574,4 +648,126 @@ public class MultiScreen implements Screen { } } + // ------------------------------------------------------------------------ + // MultiScreen ------------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Add a screen to the list. + * + * @param screen the screen to add + */ + public void addScreen(final Screen screen) { + screens.add(screen); + } + + /** + * Remove a screen from the list. + * + * @param screen the screen to remove + */ + public void removeScreen(final Screen screen) { + if (screens.size() > 1) { + screens.remove(screen); + } + } + + /** + * Get the width of a character cell in pixels. + * + * @return the width in pixels of a character cell + */ + public int getTextWidth() { + int textWidth = 16; + for (Screen screen: screens) { + int newTextWidth = screen.getTextWidth(); + if (newTextWidth < textWidth) { + textWidth = newTextWidth; + } + } + return textWidth; + } + + /** + * Get the height of a character cell in pixels. + * + * @return the height in pixels of a character cell + */ + public int getTextHeight() { + int textHeight = 20; + for (Screen screen: screens) { + int newTextHeight = screen.getTextHeight(); + if (newTextHeight < textHeight) { + textHeight = newTextHeight; + } + } + return textHeight; + } + + /** + * Invert the cell color at a position, including both halves of a + * double-width cell. + * + * @param x column position + * @param y row position + */ + public void invertCell(final int x, final int y) { + for (Screen screen: screens) { + screen.invertCell(x, y); + } + } + + /** + * Invert the cell color at a position. + * + * @param x column position + * @param y row position + * @param onlyThisCell if true, only invert this cell, otherwise invert + * both halves of a double-width cell if necessary + */ + public void invertCell(final int x, final int y, + final boolean onlyThisCell) { + + for (Screen screen: screens) { + screen.invertCell(x, y, onlyThisCell); + } + } + + /** + * Set a selection area on the screen. + * + * @param x0 the starting X position of the selection + * @param y0 the starting Y position of the selection + * @param x1 the ending X position of the selection + * @param y1 the ending Y position of the selection + * @param rectangle if true, this is a rectangle select + */ + public void setSelection(final int x0, final int y0, + final int x1, final int y1, final boolean rectangle) { + + for (Screen screen: screens) { + screen.setSelection(x0, y0, x1, y1, rectangle); + } + } + + /** + * Copy the screen selection area to the clipboard. + * + * @param clipboard the clipboard to use + * @param x0 the starting X position of the selection + * @param y0 the starting Y position of the selection + * @param x1 the ending X position of the selection + * @param y1 the ending Y position of the selection + * @param rectangle if true, this is a rectangle select + */ + public void copySelection(final Clipboard clipboard, + final int x0, final int y0, final int x1, final int y1, + final boolean rectangle) { + + // Only copy from the first screen. + if (screens.size() > 0) { + screens.get(0).copySelection(clipboard, x0, y0, x1, y1, rectangle); + } + } + }