X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTTerminalWidget.java;h=b1ff8b9b0d8e90995229d94fb3c80242f09f4d5c;hb=8afe8fa7d778da9682b82b6ac56f64d765f6a2d1;hp=6efa6490c6383e81564128fae4a96d4fc2899f73;hpb=4d2c61b46c1e769f2fe69493623446a1ac0e26f0;p=fanfix.git diff --git a/src/jexer/TTerminalWidget.java b/src/jexer/TTerminalWidget.java index 6efa649..b1ff8b9 100644 --- a/src/jexer/TTerminalWidget.java +++ b/src/jexer/TTerminalWidget.java @@ -60,7 +60,7 @@ import jexer.tterminal.ECMA48; import static jexer.TKeypress.*; /** - * TTerminalWindow exposes a ECMA-48 / ANSI X3.64 style terminal in a widget. + * TTerminalWidget exposes a ECMA-48 / ANSI X3.64 style terminal in a widget. */ public class TTerminalWidget extends TScrollableWidget implements DisplayListener { @@ -119,12 +119,7 @@ public class TTerminalWidget extends TScrollableWidget private boolean haveTimer = false; /** - * The last seen scrollback lines. - */ - private List scrollback; - - /** - * The last seen display lines. + * The last seen visible display. */ private List display; @@ -159,6 +154,11 @@ public class TTerminalWidget extends TScrollableWidget */ private String title = ""; + /** + * Action to perform when the terminal exits. + */ + private TAction closeAction = null; + // ------------------------------------------------------------------------ // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -171,8 +171,8 @@ public class TTerminalWidget extends TScrollableWidget * @param y row relative to parent * @param commandLine the command line to execute */ - public TTerminalWidget(final TWidget parent, final int x, - final int y, final String commandLine) { + public TTerminalWidget(final TWidget parent, final int x, final int y, + final String commandLine) { this(parent, x, y, commandLine.split("\\s+")); } @@ -185,10 +185,45 @@ public class TTerminalWidget extends TScrollableWidget * @param y row relative to parent * @param command the command line to execute */ - public TTerminalWidget(final TWidget parent, final int x, - final int y, final String [] command) { + public TTerminalWidget(final TWidget parent, final int x, final int y, + final String [] command) { + + this(parent, x, y, command, null); + } + + /** + * Public constructor spawns a custom command line. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param command the command line to execute + * @param closeAction action to perform when the shell sxits + */ + public TTerminalWidget(final TWidget parent, final int x, final int y, + final String [] command, final TAction closeAction) { + + this(parent, x, y, 80, 24, command, closeAction); + } + + /** + * Public constructor spawns a custom command line. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param width width of widget + * @param height height of widget + * @param command the command line to execute + * @param closeAction action to perform when the shell sxits + */ + public TTerminalWidget(final TWidget parent, final int x, final int y, + final int width, final int height, final String [] command, + final TAction closeAction) { + + super(parent, x, y, width, height); - super(parent, x, y, 80, 24); + this.closeAction = closeAction; String [] fullCommand; @@ -234,8 +269,39 @@ public class TTerminalWidget extends TScrollableWidget * @param y row relative to parent */ public TTerminalWidget(final TWidget parent, final int x, final int y) { + this(parent, x, y, (TAction) null); + } + + /** + * Public constructor spawns a shell. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param closeAction action to perform when the shell sxits + */ + public TTerminalWidget(final TWidget parent, final int x, final int y, + final TAction closeAction) { - super(parent, x, y, 80, 24); + this(parent, x, y, 80, 24, closeAction); + } + + /** + * Public constructor spawns a shell. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param width width of widget + * @param height height of widget + * @param closeAction action to perform when the shell sxits + */ + public TTerminalWidget(final TWidget parent, final int x, final int y, + final int width, final int height, final TAction closeAction) { + + super(parent, x, y, width, height); + + this.closeAction = closeAction; if (System.getProperty("jexer.TTerminal.shell") != null) { String shell = System.getProperty("jexer.TTerminal.shell"); @@ -288,8 +354,9 @@ public class TTerminalWidget extends TScrollableWidget @Override public void draw() { int width = getDisplayWidth(); + boolean syncEmulator = false; - if ((System.currentTimeMillis() - lastUpdateTime >= 25) + if ((System.currentTimeMillis() - lastUpdateTime >= 20) && (dirty == true) ) { // Too much time has passed, draw it all. @@ -303,7 +370,6 @@ public class TTerminalWidget extends TScrollableWidget } if ((syncEmulator == true) - || (scrollback == null) || (display == null) ) { // We want to minimize the amount of time we have the emulator @@ -312,49 +378,27 @@ public class TTerminalWidget extends TScrollableWidget // Update the scroll bars reflowData(); - if ((scrollback == null) || emulator.isReading()) { - scrollback = copyBuffer(emulator.getScrollbackBuffer()); - display = copyBuffer(emulator.getDisplayBuffer()); + if (!isDrawable()) { + // We lost the connection, onShellExit() called an action + // that ultimately removed this widget from the UI + // hierarchy, so no one cares if we update the display. + // Bail out. + return; + } + + if ((display == null) || emulator.isReading()) { + display = emulator.getVisibleDisplay(getHeight(), + -getVerticalValue()); + assert (display.size() == getHeight()); } width = emulator.getWidth(); } dirty = false; } - // Draw the box using my superclass - super.draw(); - - // Put together the visible rows - int visibleHeight = getHeight(); - int visibleBottom = scrollback.size() + display.size() - + getVerticalValue(); - assert (visibleBottom >= 0); - - List preceedingBlankLines = new ArrayList(); - int visibleTop = visibleBottom - visibleHeight; - if (visibleTop < 0) { - for (int i = visibleTop; i < 0; i++) { - preceedingBlankLines.add(emulator.getBlankDisplayLine()); - } - visibleTop = 0; - } - assert (visibleTop >= 0); - - List displayLines = new ArrayList(); - displayLines.addAll(scrollback); - displayLines.addAll(display); - - List visibleLines = new ArrayList(); - visibleLines.addAll(preceedingBlankLines); - visibleLines.addAll(displayLines.subList(visibleTop, - visibleBottom)); - - visibleHeight -= visibleLines.size(); - assert (visibleHeight >= 0); - // Now draw the emulator screen int row = 0; - for (DisplayLine line: visibleLines) { + for (DisplayLine line: display) { int widthMax = width; if (line.isDoubleWidth()) { widthMax /= 2; @@ -394,21 +438,11 @@ public class TTerminalWidget extends TScrollableWidget } } row++; - if (row == getHeight()) { - // Don't overwrite the box edge - break; - } - } - CellAttributes background = new CellAttributes(); - // Fill in the blank lines on bottom - for (int i = 0; i < visibleHeight; i++) { - hLineXY(0, i + row, getWidth(), ' ', background); } - } /** - * Handle window close. + * Handle widget close. */ @Override public void close() { @@ -427,6 +461,8 @@ public class TTerminalWidget extends TScrollableWidget */ @Override public void onResize(final TResizeEvent resize) { + // Let TWidget set my size. + super.onResize(resize); // Synchronize against the emulator so we don't stomp on its reader // thread. @@ -447,6 +483,12 @@ public class TTerminalWidget extends TScrollableWidget emulator.writeRemote("\033[8;" + getHeight() + ";" + getWidth() + "t"); } + + // Pass the correct text cell width/height to the emulator + if (getScreen() != null) { + emulator.setTextWidth(getScreen().getTextWidth()); + emulator.setTextHeight(getScreen().getTextHeight()); + } } return; @@ -492,6 +534,7 @@ public class TTerminalWidget extends TScrollableWidget || keypress.equals(kbAltPgUp) ) { bigVerticalDecrement(); + dirty = true; return; } if (keypress.equals(kbShiftPgDn) @@ -499,6 +542,7 @@ public class TTerminalWidget extends TScrollableWidget || keypress.equals(kbAltPgDn) ) { bigVerticalIncrement(); + dirty = true; return; } @@ -542,10 +586,12 @@ public class TTerminalWidget extends TScrollableWidget if (emulator.getMouseProtocol() == ECMA48.MouseProtocol.OFF) { if (mouse.isMouseWheelUp()) { verticalDecrement(); + dirty = true; return; } if (mouse.isMouseWheelDown()) { verticalIncrement(); + dirty = true; return; } } @@ -615,10 +661,10 @@ public class TTerminalWidget extends TScrollableWidget } /** - * Returns true if this window does not want the application-wide mouse + * Returns true if this widget does not want the application-wide mouse * cursor drawn over it. * - * @return true if this window does not want the application-wide mouse + * @return true if this widget does not want the application-wide mouse * cursor drawn over it */ public boolean hasHiddenMouse() { @@ -696,10 +742,6 @@ public class TTerminalWidget extends TScrollableWidget onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(), getHeight())); - // Pass the correct text cell width/height to the emulator - emulator.setTextWidth(getScreen().getTextWidth()); - emulator.setTextHeight(getScreen().getTextHeight()); - // Hide mouse when typing option if (System.getProperty("jexer.TTerminal.hideMouseWhenTyping", "true").equals("false")) { @@ -745,10 +787,22 @@ public class TTerminalWidget extends TScrollableWidget * Hook for subclasses to be notified of the shell termination. */ public void onShellExit() { - if (getParent() instanceof TTerminalWindow) { - ((TTerminalWindow) getParent()).onShellExit(); + TApplication app = getApplication(); + if (app != null) { + if (closeAction != null) { + // We have to put this action inside invokeLater() because it + // could be executed during draw() when syncing with ECMA48. + app.invokeLater(new Runnable() { + public void run() { + closeAction.DO(TTerminalWidget.this); + } + }); + } + if (getApplication() != null) { + getApplication().postEvent(new TMenuEvent( + TMenu.MID_REPAINT)); + } } - getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT)); } /** @@ -836,20 +890,6 @@ public class TTerminalWidget extends TScrollableWidget return false; } - /** - * Copy a display buffer. - * - * @param buffer the buffer to copy - * @return a deep copy of the buffer's data - */ - private List copyBuffer(final List buffer) { - ArrayList result = new ArrayList(buffer.size()); - for (DisplayLine line: buffer) { - result.add(new DisplayLine(line)); - } - return result; - } - /** * Draw glyphs for a double-width or double-height VT100 cell to two * screen cells.