From 615a0d99fd0aa4437116dd083147f9150d5e6527 Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Wed, 9 May 2018 14:04:42 -0400 Subject: [PATCH] Finish code sweep --- src/jexer/TCheckBox.java | 6 +- src/jexer/TDesktop.java | 8 + src/jexer/TDirectoryList.java | 88 ++-- src/jexer/TEditorWidget.java | 202 ++++---- src/jexer/TEditorWindow.java | 162 +++--- src/jexer/TInputBox.java | 32 +- src/jexer/TKeypress.java | 1 - src/jexer/TMessageBox.java | 39 +- src/jexer/TPasswordField.java | 8 + src/jexer/TRadioGroup.java | 64 ++- src/jexer/TScrollableWidget.java | 100 ++-- src/jexer/TScrollableWindow.java | 112 ++-- src/jexer/TTerminalWindow.java | 704 +++++++++++++------------- src/jexer/TText.java | 313 ++++++------ src/jexer/demos/DemoMsgBoxWindow.java | 3 +- src/jexer/event/TCommandEvent.java | 33 +- src/jexer/event/TInputEvent.java | 27 +- src/jexer/event/TKeypressEvent.java | 51 +- src/jexer/event/TMenuEvent.java | 33 +- src/jexer/io/TimeoutInputStream.java | 37 +- src/jexer/teditor/Document.java | 48 +- src/jexer/teditor/Highlighter.java | 13 +- src/jexer/teditor/Line.java | 68 ++- src/jexer/teditor/Word.java | 68 ++- 24 files changed, 1282 insertions(+), 938 deletions(-) diff --git a/src/jexer/TCheckBox.java b/src/jexer/TCheckBox.java index 2b35843..188db7e 100644 --- a/src/jexer/TCheckBox.java +++ b/src/jexer/TCheckBox.java @@ -44,7 +44,7 @@ public class TCheckBox extends TWidget { // ------------------------------------------------------------------------ /** - * Checkbox state, true means checked. + * CheckBox state, true means checked. */ private boolean checked = false; @@ -89,7 +89,7 @@ public class TCheckBox extends TWidget { * @param mouse mouse event * @return true if the mouse is currently on the checkbox */ - private boolean mouseOnCheckbox(final TMouseEvent mouse) { + private boolean mouseOnCheckBox(final TMouseEvent mouse) { if ((mouse.getY() == 0) && (mouse.getX() >= 0) && (mouse.getX() <= 2) @@ -106,7 +106,7 @@ public class TCheckBox extends TWidget { */ @Override public void onMouseDown(final TMouseEvent mouse) { - if ((mouseOnCheckbox(mouse)) && (mouse.isMouse1())) { + if ((mouseOnCheckBox(mouse)) && (mouse.isMouse1())) { // Switch state checked = !checked; } diff --git a/src/jexer/TDesktop.java b/src/jexer/TDesktop.java index 1167e0c..23edfb8 100644 --- a/src/jexer/TDesktop.java +++ b/src/jexer/TDesktop.java @@ -51,6 +51,10 @@ import jexer.event.TMouseEvent; */ public class TDesktop extends TWindow { + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Public constructor. * @@ -64,6 +68,10 @@ public class TDesktop extends TWindow { setActive(false); } + // ------------------------------------------------------------------------ + // TWindow ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The default TDesktop draws a hatch character across everything. */ diff --git a/src/jexer/TDirectoryList.java b/src/jexer/TDirectoryList.java index c47b330..9ff0b6b 100644 --- a/src/jexer/TDirectoryList.java +++ b/src/jexer/TDirectoryList.java @@ -30,6 +30,7 @@ package jexer; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -37,6 +38,10 @@ import java.util.List; */ public class TDirectoryList extends TList { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Files in the directory. */ @@ -47,6 +52,53 @@ public class TDirectoryList extends TList { */ private File path; + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Public constructor. + * + * @param parent parent widget + * @param path directory path, must be a directory + * @param x column relative to parent + * @param y row relative to parent + * @param width width of text area + * @param height height of text area + */ + public TDirectoryList(final TWidget parent, final String path, final int x, + final int y, final int width, final int height) { + + this(parent, path, x, y, width, height, null); + } + + /** + * Public constructor. + * + * @param parent parent widget + * @param path directory path, must be a directory + * @param x column relative to parent + * @param y row relative to parent + * @param width width of text area + * @param height height of text area + * @param action action to perform when an item is selected + */ + public TDirectoryList(final TWidget parent, final String path, final int x, + final int y, final int width, final int height, final TAction action) { + + super(parent, null, x, y, width, height, action); + files = new ArrayList(); + setPath(path); + } + + // ------------------------------------------------------------------------ + // TList ------------------------------------------------------------------ + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // TDirectoryList --------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Set the new path to display. * @@ -72,6 +124,7 @@ public class TDirectoryList extends TList { newStrings.add(renderFile(files.size() - 1)); } } + Collections.sort(newStrings); setList(newStrings); // Select the first entry @@ -105,39 +158,4 @@ public class TDirectoryList extends TList { return String.format("%-20s %5dk", name, (file.length() / 1024)); } - /** - * Public constructor. - * - * @param parent parent widget - * @param path directory path, must be a directory - * @param x column relative to parent - * @param y row relative to parent - * @param width width of text area - * @param height height of text area - */ - public TDirectoryList(final TWidget parent, final String path, final int x, - final int y, final int width, final int height) { - - this(parent, path, x, y, width, height, null); - } - - /** - * Public constructor. - * - * @param parent parent widget - * @param path directory path, must be a directory - * @param x column relative to parent - * @param y row relative to parent - * @param width width of text area - * @param height height of text area - * @param action action to perform when an item is selected - */ - public TDirectoryList(final TWidget parent, final String path, final int x, - final int y, final int width, final int height, final TAction action) { - - super(parent, null, x, y, width, height, action); - files = new ArrayList(); - setPath(path); - } - } diff --git a/src/jexer/TEditorWidget.java b/src/jexer/TEditorWidget.java index dcf5e9e..94f1a3b 100644 --- a/src/jexer/TEditorWidget.java +++ b/src/jexer/TEditorWidget.java @@ -45,11 +45,19 @@ import static jexer.TKeypress.*; */ public class TEditorWidget extends TWidget { + // ------------------------------------------------------------------------ + // Constants -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The number of lines to scroll on mouse wheel up/down. */ private static final int wheelScrollSize = 3; + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The document being edited. */ @@ -70,6 +78,10 @@ public class TEditorWidget extends TWidget { */ private int leftColumn = 0; + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Public constructor. * @@ -92,6 +104,10 @@ public class TEditorWidget extends TWidget { document = new Document(text, defaultColor); } + // ------------------------------------------------------------------------ + // TWidget ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Draw the text box. */ @@ -178,97 +194,6 @@ public class TEditorWidget extends TWidget { super.onMouseDown(mouse); } - /** - * Align visible area with document current line. - * - * @param topLineIsTop if true, make the top visible line the document - * current line if it was off-screen. If false, make the bottom visible - * line the document current line. - */ - private void alignTopLine(final boolean topLineIsTop) { - int line = document.getLineNumber(); - - if ((line < topLine) || (line > topLine + getHeight() - 1)) { - // Need to move topLine to bring document back into view. - if (topLineIsTop) { - topLine = line - (getHeight() - 1); - if (topLine < 0) { - topLine = 0; - } - assert (topLine >= 0); - } else { - topLine = line; - assert (topLine >= 0); - } - } - - /* - System.err.println("line " + line + " topLine " + topLine); - */ - - // Document is in view, let's set cursorY - assert (line >= topLine); - setCursorY(line - topLine); - alignCursor(); - } - - /** - * Align document current line with visible area. - * - * @param topLineIsTop if true, make the top visible line the document - * current line if it was off-screen. If false, make the bottom visible - * line the document current line. - */ - private void alignDocument(final boolean topLineIsTop) { - int line = document.getLineNumber(); - int cursor = document.getCursor(); - - if ((line < topLine) || (line > topLine + getHeight() - 1)) { - // Need to move document to ensure it fits view. - if (topLineIsTop) { - document.setLineNumber(topLine); - } else { - document.setLineNumber(topLine + (getHeight() - 1)); - } - if (cursor < document.getCurrentLine().getDisplayLength()) { - document.setCursor(cursor); - } - } - - /* - System.err.println("getLineNumber() " + document.getLineNumber() + - " topLine " + topLine); - */ - - // Document is in view, let's set cursorY - setCursorY(document.getLineNumber() - topLine); - alignCursor(); - } - - /** - * Align visible cursor with document cursor. - */ - private void alignCursor() { - int width = getWidth(); - - int desiredX = document.getCursor() - leftColumn; - if (desiredX < 0) { - // We need to push the screen to the left. - leftColumn = document.getCursor(); - } else if (desiredX > width - 1) { - // We need to push the screen to the right. - leftColumn = document.getCursor() - (width - 1); - } - - /* - System.err.println("document cursor " + document.getCursor() + - " leftColumn " + leftColumn); - */ - - - setCursorX(document.getCursor() - leftColumn); - } - /** * Handle keystrokes. * @@ -376,6 +301,101 @@ public class TEditorWidget extends TWidget { } } + // ------------------------------------------------------------------------ + // TEditorWidget ---------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Align visible area with document current line. + * + * @param topLineIsTop if true, make the top visible line the document + * current line if it was off-screen. If false, make the bottom visible + * line the document current line. + */ + private void alignTopLine(final boolean topLineIsTop) { + int line = document.getLineNumber(); + + if ((line < topLine) || (line > topLine + getHeight() - 1)) { + // Need to move topLine to bring document back into view. + if (topLineIsTop) { + topLine = line - (getHeight() - 1); + if (topLine < 0) { + topLine = 0; + } + assert (topLine >= 0); + } else { + topLine = line; + assert (topLine >= 0); + } + } + + /* + System.err.println("line " + line + " topLine " + topLine); + */ + + // Document is in view, let's set cursorY + assert (line >= topLine); + setCursorY(line - topLine); + alignCursor(); + } + + /** + * Align document current line with visible area. + * + * @param topLineIsTop if true, make the top visible line the document + * current line if it was off-screen. If false, make the bottom visible + * line the document current line. + */ + private void alignDocument(final boolean topLineIsTop) { + int line = document.getLineNumber(); + int cursor = document.getCursor(); + + if ((line < topLine) || (line > topLine + getHeight() - 1)) { + // Need to move document to ensure it fits view. + if (topLineIsTop) { + document.setLineNumber(topLine); + } else { + document.setLineNumber(topLine + (getHeight() - 1)); + } + if (cursor < document.getCurrentLine().getDisplayLength()) { + document.setCursor(cursor); + } + } + + /* + System.err.println("getLineNumber() " + document.getLineNumber() + + " topLine " + topLine); + */ + + // Document is in view, let's set cursorY + setCursorY(document.getLineNumber() - topLine); + alignCursor(); + } + + /** + * Align visible cursor with document cursor. + */ + private void alignCursor() { + int width = getWidth(); + + int desiredX = document.getCursor() - leftColumn; + if (desiredX < 0) { + // We need to push the screen to the left. + leftColumn = document.getCursor(); + } else if (desiredX > width - 1) { + // We need to push the screen to the right. + leftColumn = document.getCursor() - (width - 1); + } + + /* + System.err.println("document cursor " + document.getCursor() + + " leftColumn " + leftColumn); + */ + + + setCursorX(document.getCursor() - leftColumn); + } + /** * Get the number of lines in the underlying Document. * diff --git a/src/jexer/TEditorWindow.java b/src/jexer/TEditorWindow.java index 9f1ae67..4a638fc 100644 --- a/src/jexer/TEditorWindow.java +++ b/src/jexer/TEditorWindow.java @@ -59,6 +59,10 @@ public class TEditorWindow extends TScrollableWindow { */ private static final ResourceBundle i18n = ResourceBundle.getBundle(TEditorWindow.class.getName()); + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Hang onto my TEditor so I can resize it with the window. */ @@ -69,29 +73,9 @@ public class TEditorWindow extends TScrollableWindow { */ private String filename = ""; - /** - * Setup other fields after the editor is created. - */ - private void setupAfterEditor() { - hScroller = new THScroller(this, 17, getHeight() - 2, getWidth() - 20); - vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2); - setMinimumWindowWidth(25); - setMinimumWindowHeight(10); - setTopValue(1); - setBottomValue(editField.getMaximumRowNumber()); - setLeftValue(1); - setRightValue(editField.getMaximumColumnNumber()); - - statusBar = newStatusBar(i18n.getString("statusBar")); - statusBar.addShortcutKeypress(kbF1, cmHelp, - i18n.getString("statusBarHelp")); - statusBar.addShortcutKeypress(kbF2, cmSave, - i18n.getString("statusBarSave")); - statusBar.addShortcutKeypress(kbF3, cmOpen, - i18n.getString("statusBarOpen")); - statusBar.addShortcutKeypress(kbF10, cmMenu, - i18n.getString("statusBarMenu")); - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor sets window title. @@ -154,38 +138,9 @@ public class TEditorWindow extends TScrollableWindow { this(parent, i18n.getString("newTextDocument")); } - /** - * Read file data into a string. - * - * @param file the file to open - * @return the file contents - * @throws IOException if a java.io operation throws - */ - private String readFileData(final File file) throws IOException { - StringBuilder fileContents = new StringBuilder(); - Scanner scanner = new Scanner(file); - String EOL = System.getProperty("line.separator"); - - try { - while (scanner.hasNextLine()) { - fileContents.append(scanner.nextLine() + EOL); - } - return fileContents.toString(); - } finally { - scanner.close(); - } - } - - /** - * Read file data into a string. - * - * @param filename the file to open - * @return the file contents - * @throws IOException if a java.io operation throws - */ - private String readFileData(final String filename) throws IOException { - return readFileData(new File(filename)); - } + // ------------------------------------------------------------------------ + // TWindow ---------------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Draw the window. @@ -208,24 +163,6 @@ public class TEditorWindow extends TScrollableWindow { } } - /** - * Check if a mouse press/release/motion event coordinate is over the - * editor. - * - * @param mouse a mouse-based event - * @return whether or not the mouse is on the editor - */ - private final boolean mouseOnEditor(final TMouseEvent mouse) { - if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1) - && (mouse.getAbsoluteX() < getAbsoluteX() + getWidth() - 1) - && (mouse.getAbsoluteY() >= getAbsoluteY() + 1) - && (mouse.getAbsoluteY() < getAbsoluteY() + getHeight() - 1) - ) { - return true; - } - return false; - } - /** * Handle mouse press events. * @@ -381,4 +318,83 @@ public class TEditorWindow extends TScrollableWindow { super.onCommand(command); } + // ------------------------------------------------------------------------ + // TEditorWindow ---------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Setup other fields after the editor is created. + */ + private void setupAfterEditor() { + hScroller = new THScroller(this, 17, getHeight() - 2, getWidth() - 20); + vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2); + setMinimumWindowWidth(25); + setMinimumWindowHeight(10); + setTopValue(1); + setBottomValue(editField.getMaximumRowNumber()); + setLeftValue(1); + setRightValue(editField.getMaximumColumnNumber()); + + statusBar = newStatusBar(i18n.getString("statusBar")); + statusBar.addShortcutKeypress(kbF1, cmHelp, + i18n.getString("statusBarHelp")); + statusBar.addShortcutKeypress(kbF2, cmSave, + i18n.getString("statusBarSave")); + statusBar.addShortcutKeypress(kbF3, cmOpen, + i18n.getString("statusBarOpen")); + statusBar.addShortcutKeypress(kbF10, cmMenu, + i18n.getString("statusBarMenu")); + } + + /** + * Read file data into a string. + * + * @param file the file to open + * @return the file contents + * @throws IOException if a java.io operation throws + */ + private String readFileData(final File file) throws IOException { + StringBuilder fileContents = new StringBuilder(); + Scanner scanner = new Scanner(file); + String EOL = System.getProperty("line.separator"); + + try { + while (scanner.hasNextLine()) { + fileContents.append(scanner.nextLine() + EOL); + } + return fileContents.toString(); + } finally { + scanner.close(); + } + } + + /** + * Read file data into a string. + * + * @param filename the file to open + * @return the file contents + * @throws IOException if a java.io operation throws + */ + private String readFileData(final String filename) throws IOException { + return readFileData(new File(filename)); + } + + /** + * Check if a mouse press/release/motion event coordinate is over the + * editor. + * + * @param mouse a mouse-based event + * @return whether or not the mouse is on the editor + */ + private final boolean mouseOnEditor(final TMouseEvent mouse) { + if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1) + && (mouse.getAbsoluteX() < getAbsoluteX() + getWidth() - 1) + && (mouse.getAbsoluteY() >= getAbsoluteY() + 1) + && (mouse.getAbsoluteY() < getAbsoluteY() + getHeight() - 1) + ) { + return true; + } + return false; + } + } diff --git a/src/jexer/TInputBox.java b/src/jexer/TInputBox.java index 6ade42f..02a468f 100644 --- a/src/jexer/TInputBox.java +++ b/src/jexer/TInputBox.java @@ -44,19 +44,18 @@ package jexer; */ public class TInputBox extends TMessageBox { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The input field. */ private TField field; - /** - * Retrieve the answer text. - * - * @return the answer text - */ - public String getText() { - return field.getText(); - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor. The input box will be centered on screen. @@ -116,4 +115,21 @@ public class TInputBox extends TMessageBox { getApplication().yield(); } + // ------------------------------------------------------------------------ + // TMessageBox ------------------------------------------------------------ + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // TInputBox -------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Retrieve the answer text. + * + * @return the answer text + */ + public String getText() { + return field.getText(); + } + } diff --git a/src/jexer/TKeypress.java b/src/jexer/TKeypress.java index 5ba3484..e0aa3b3 100644 --- a/src/jexer/TKeypress.java +++ b/src/jexer/TKeypress.java @@ -174,7 +174,6 @@ public class TKeypress { */ public static final int ESC = 43; - // Special "no-key" keypress, used to ignore undefined keystrokes public static final TKeypress kbNoKey = new TKeypress(true, TKeypress.NONE, ' ', false, false, false); diff --git a/src/jexer/TMessageBox.java b/src/jexer/TMessageBox.java index 0e5cf7d..4c45379 100644 --- a/src/jexer/TMessageBox.java +++ b/src/jexer/TMessageBox.java @@ -58,6 +58,10 @@ public class TMessageBox extends TWindow { */ private static final ResourceBundle i18n = ResourceBundle.getBundle(TMessageBox.class.getName()); + // ------------------------------------------------------------------------ + // Constants -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Message boxes have these supported types. */ @@ -83,16 +87,6 @@ public class TMessageBox extends TWindow { YESNOCANCEL }; - /** - * The type of this message box. - */ - private Type type; - - /** - * My buttons. - */ - private List buttons; - /** * Message boxes have these possible results. */ @@ -118,6 +112,20 @@ public class TMessageBox extends TWindow { NO }; + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * The type of this message box. + */ + private Type type; + + /** + * My buttons. + */ + private List buttons; + /** * Which button was clicked: OK, CANCEL, YES, or NO. */ @@ -132,6 +140,10 @@ public class TMessageBox extends TWindow { return result; } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Public constructor. The message box will be centered on screen. * @@ -337,6 +349,10 @@ public class TMessageBox extends TWindow { } } + // ------------------------------------------------------------------------ + // TWindow ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Handle keystrokes. * @@ -395,7 +411,8 @@ public class TMessageBox extends TWindow { break; default: - throw new IllegalArgumentException("Invalid message box type: " + type); + throw new IllegalArgumentException("Invalid message box type: " + + type); } super.onKeypress(keypress); diff --git a/src/jexer/TPasswordField.java b/src/jexer/TPasswordField.java index 696f5e2..696598b 100644 --- a/src/jexer/TPasswordField.java +++ b/src/jexer/TPasswordField.java @@ -36,6 +36,10 @@ import jexer.bits.GraphicsChars; */ public class TPasswordField extends TField { + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Public constructor. * @@ -87,6 +91,10 @@ public class TPasswordField extends TField { super(parent, x, y, width, fixed, text, enterAction, updateAction); } + // ------------------------------------------------------------------------ + // TField ----------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Draw the text field. */ diff --git a/src/jexer/TRadioGroup.java b/src/jexer/TRadioGroup.java index d811f27..6e6f39d 100644 --- a/src/jexer/TRadioGroup.java +++ b/src/jexer/TRadioGroup.java @@ -35,6 +35,10 @@ import jexer.bits.CellAttributes; */ public class TRadioGroup extends TWidget { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Label for this radio button group. */ @@ -45,30 +49,9 @@ public class TRadioGroup extends TWidget { */ private TRadioButton selectedButton = null; - /** - * Get the radio button ID that was selected. - * - * @return ID of the selected button, or 0 if no button is selected - */ - public int getSelected() { - if (selectedButton == null) { - return 0; - } - return selectedButton.getId(); - } - - /** - * Set the new selected radio button. Note package private access. - * - * @param button new button that became selected - */ - void setSelected(final TRadioButton button) { - assert (button.isSelected()); - if (selectedButton != null) { - selectedButton.setSelected(false); - } - selectedButton = button; - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor. @@ -87,6 +70,10 @@ public class TRadioGroup extends TWidget { this.label = label; } + // ------------------------------------------------------------------------ + // TWidget ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Draw a radio button with label. */ @@ -107,6 +94,35 @@ public class TRadioGroup extends TWidget { getScreen().putStringXY(2, 0, label, radioGroupColor); } + // ------------------------------------------------------------------------ + // TRadioGroup ------------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Get the radio button ID that was selected. + * + * @return ID of the selected button, or 0 if no button is selected + */ + public int getSelected() { + if (selectedButton == null) { + return 0; + } + return selectedButton.getId(); + } + + /** + * Set the new selected radio button. Note package private access. + * + * @param button new button that became selected + */ + void setSelected(final TRadioButton button) { + assert (button.isSelected()); + if (selectedButton != null) { + selectedButton.setSelected(false); + } + selectedButton = button; + } + /** * Convenience function to add a radio button to this group. * diff --git a/src/jexer/TScrollableWidget.java b/src/jexer/TScrollableWidget.java index a4ba70a..85be9ed 100644 --- a/src/jexer/TScrollableWidget.java +++ b/src/jexer/TScrollableWidget.java @@ -36,6 +36,10 @@ import jexer.event.TResizeEvent; */ public class TScrollableWidget extends TWidget implements Scrollable { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The horizontal scrollbar. */ @@ -46,48 +50,9 @@ public class TScrollableWidget extends TWidget implements Scrollable { */ protected TVScroller vScroller = null; - /** - * Place the scrollbars on the edge of this widget, and adjust bigChange - * to match the new size. This is called by onResize(). - */ - protected void placeScrollbars() { - if (hScroller != null) { - hScroller.setY(getHeight() - 1); - hScroller.setWidth(getWidth() - 1); - hScroller.setBigChange(getWidth() - 1); - } - if (vScroller != null) { - vScroller.setX(getWidth() - 1); - vScroller.setHeight(getHeight() - 1); - vScroller.setBigChange(getHeight() - 1); - } - } - - /** - * Recompute whatever data is displayed by this widget. - */ - public void reflowData() { - // Default: nothing to do - } - - /** - * Handle window/screen resize events. - * - * @param event resize event - */ - @Override - public void onResize(final TResizeEvent event) { - if (event.getType() == TResizeEvent.Type.WIDGET) { - setWidth(event.getWidth()); - setHeight(event.getHeight()); - - reflowData(); - placeScrollbars(); - return; - } else { - super.onResize(event); - } - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Protected constructor. @@ -140,6 +105,57 @@ public class TScrollableWidget extends TWidget implements Scrollable { super(parent, enabled, x, y, width, height); } + // ------------------------------------------------------------------------ + // TWidget ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Handle window/screen resize events. + * + * @param event resize event + */ + @Override + public void onResize(final TResizeEvent event) { + if (event.getType() == TResizeEvent.Type.WIDGET) { + setWidth(event.getWidth()); + setHeight(event.getHeight()); + + reflowData(); + placeScrollbars(); + return; + } else { + super.onResize(event); + } + } + + // ------------------------------------------------------------------------ + // TScrollableWidget ------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Place the scrollbars on the edge of this widget, and adjust bigChange + * to match the new size. This is called by onResize(). + */ + protected void placeScrollbars() { + if (hScroller != null) { + hScroller.setY(getHeight() - 1); + hScroller.setWidth(getWidth() - 1); + hScroller.setBigChange(getWidth() - 1); + } + if (vScroller != null) { + vScroller.setX(getWidth() - 1); + vScroller.setHeight(getHeight() - 1); + vScroller.setBigChange(getHeight() - 1); + } + } + + /** + * Recompute whatever data is displayed by this widget. + */ + public void reflowData() { + // Default: nothing to do + } + /** * Get the horizontal scrollbar, or null if this Viewport does not * support horizontal scrolling. diff --git a/src/jexer/TScrollableWindow.java b/src/jexer/TScrollableWindow.java index ae5f50c..c5f122b 100644 --- a/src/jexer/TScrollableWindow.java +++ b/src/jexer/TScrollableWindow.java @@ -37,6 +37,10 @@ import jexer.event.TResizeEvent; */ public class TScrollableWindow extends TWindow implements Scrollable { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The horizontal scrollbar. */ @@ -47,45 +51,9 @@ public class TScrollableWindow extends TWindow implements Scrollable { */ protected TVScroller vScroller = null; - /** - * Place the scrollbars on the edge of this widget, and adjust bigChange - * to match the new size. This is called by onResize(). - */ - protected void placeScrollbars() { - if (hScroller != null) { - hScroller.setY(getHeight() - 2); - hScroller.setWidth(getWidth() - hScroller.getX() - 3); - hScroller.setBigChange(getWidth() - hScroller.getX() - 3); - } - if (vScroller != null) { - vScroller.setX(getWidth() - 2); - vScroller.setHeight(getHeight() - 2); - vScroller.setBigChange(getHeight() - 2); - } - } - - /** - * Recompute whatever data is displayed by this widget. - */ - public void reflowData() { - // Default: nothing to do - } - - /** - * Handle window/screen resize events. - * - * @param event resize event - */ - @Override - public void onResize(final TResizeEvent event) { - if (event.getType() == TResizeEvent.Type.WIDGET) { - reflowData(); - placeScrollbars(); - return; - } else { - super.onResize(event); - } - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor. Window will be located at (0, 0). @@ -150,6 +118,72 @@ public class TScrollableWindow extends TWindow implements Scrollable { super(application, title, x, y, width, height, flags); } + // ------------------------------------------------------------------------ + // TWindow ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Handle window/screen resize events. + * + * @param event resize event + */ + @Override + public void onResize(final TResizeEvent event) { + if (event.getType() == TResizeEvent.Type.WIDGET) { + reflowData(); + placeScrollbars(); + return; + } else { + super.onResize(event); + } + } + + /** + * Maximize window. + */ + @Override + public void maximize() { + super.maximize(); + placeScrollbars(); + } + + /** + * Restore (unmaximize) window. + */ + @Override + public void restore() { + super.restore(); + placeScrollbars(); + } + + // ------------------------------------------------------------------------ + // TScrollableWindow ------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Place the scrollbars on the edge of this widget, and adjust bigChange + * to match the new size. This is called by onResize(). + */ + protected void placeScrollbars() { + if (hScroller != null) { + hScroller.setY(getHeight() - 2); + hScroller.setWidth(getWidth() - hScroller.getX() - 3); + hScroller.setBigChange(getWidth() - hScroller.getX() - 3); + } + if (vScroller != null) { + vScroller.setX(getWidth() - 2); + vScroller.setHeight(getHeight() - 2); + vScroller.setBigChange(getHeight() - 2); + } + } + + /** + * Recompute whatever data is displayed by this widget. + */ + public void reflowData() { + // Default: nothing to do + } + /** * Get the horizontal scrollbar, or null if this Viewport does not * support horizontal scrolling. diff --git a/src/jexer/TTerminalWindow.java b/src/jexer/TTerminalWindow.java index 415a1a0..93d0fa1 100644 --- a/src/jexer/TTerminalWindow.java +++ b/src/jexer/TTerminalWindow.java @@ -60,6 +60,10 @@ public class TTerminalWindow extends TScrollableWindow */ private static final ResourceBundle i18n = ResourceBundle.getBundle(TTerminalWindow.class.getName()); + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The emulator. */ @@ -77,138 +81,9 @@ public class TTerminalWindow extends TScrollableWindow */ private boolean ptypipe = false; - /** - * Claim the keystrokes the emulator will need. - */ - private void addShortcutKeys() { - addShortcutKeypress(kbCtrlA); - addShortcutKeypress(kbCtrlB); - addShortcutKeypress(kbCtrlC); - addShortcutKeypress(kbCtrlD); - addShortcutKeypress(kbCtrlE); - addShortcutKeypress(kbCtrlF); - addShortcutKeypress(kbCtrlG); - addShortcutKeypress(kbCtrlH); - addShortcutKeypress(kbCtrlU); - addShortcutKeypress(kbCtrlJ); - addShortcutKeypress(kbCtrlK); - addShortcutKeypress(kbCtrlL); - addShortcutKeypress(kbCtrlM); - addShortcutKeypress(kbCtrlN); - addShortcutKeypress(kbCtrlO); - addShortcutKeypress(kbCtrlP); - addShortcutKeypress(kbCtrlQ); - addShortcutKeypress(kbCtrlR); - addShortcutKeypress(kbCtrlS); - addShortcutKeypress(kbCtrlT); - addShortcutKeypress(kbCtrlU); - addShortcutKeypress(kbCtrlV); - addShortcutKeypress(kbCtrlW); - addShortcutKeypress(kbCtrlX); - addShortcutKeypress(kbCtrlY); - addShortcutKeypress(kbCtrlZ); - addShortcutKeypress(kbF1); - addShortcutKeypress(kbF2); - addShortcutKeypress(kbF3); - addShortcutKeypress(kbF4); - addShortcutKeypress(kbF5); - addShortcutKeypress(kbF6); - addShortcutKeypress(kbF7); - addShortcutKeypress(kbF8); - addShortcutKeypress(kbF9); - addShortcutKeypress(kbF10); - addShortcutKeypress(kbF11); - addShortcutKeypress(kbF12); - addShortcutKeypress(kbAltA); - addShortcutKeypress(kbAltB); - addShortcutKeypress(kbAltC); - addShortcutKeypress(kbAltD); - addShortcutKeypress(kbAltE); - addShortcutKeypress(kbAltF); - addShortcutKeypress(kbAltG); - addShortcutKeypress(kbAltH); - addShortcutKeypress(kbAltU); - addShortcutKeypress(kbAltJ); - addShortcutKeypress(kbAltK); - addShortcutKeypress(kbAltL); - addShortcutKeypress(kbAltM); - addShortcutKeypress(kbAltN); - addShortcutKeypress(kbAltO); - addShortcutKeypress(kbAltP); - addShortcutKeypress(kbAltQ); - addShortcutKeypress(kbAltR); - addShortcutKeypress(kbAltS); - addShortcutKeypress(kbAltT); - addShortcutKeypress(kbAltU); - addShortcutKeypress(kbAltV); - addShortcutKeypress(kbAltW); - addShortcutKeypress(kbAltX); - addShortcutKeypress(kbAltY); - addShortcutKeypress(kbAltZ); - } - - /** - * Convert a string array to a whitespace-separated string. - * - * @param array the string array - * @return a single string - */ - private String stringArrayToString(final String [] array) { - StringBuilder sb = new StringBuilder(array[0].length()); - for (int i = 0; i < array.length; i++) { - sb.append(array[i]); - if (i < array.length - 1) { - sb.append(' '); - } - } - return sb.toString(); - } - - /** - * Spawn the shell. - * - * @param command the command line to execute - */ - private void spawnShell(final String [] command) { - - /* - System.err.printf("spawnShell(): '%s'\n", - stringArrayToString(command)); - */ - - vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2); - setBottomValue(0); - - // Assume XTERM - ECMA48.DeviceType deviceType = ECMA48.DeviceType.XTERM; - - try { - ProcessBuilder pb = new ProcessBuilder(command); - Map env = pb.environment(); - env.put("TERM", ECMA48.deviceTypeTerm(deviceType)); - env.put("LANG", ECMA48.deviceTypeLang(deviceType, "en")); - env.put("COLUMNS", "80"); - env.put("LINES", "24"); - pb.redirectErrorStream(true); - shell = pb.start(); - emulator = new ECMA48(deviceType, shell.getInputStream(), - shell.getOutputStream(), this); - } catch (IOException e) { - messageBox(i18n.getString("errorLaunchingShellTitle"), - MessageFormat.format(i18n.getString("errorLaunchingShellText"), - e.getMessage())); - } - - // Setup the scroll bars - onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(), - getHeight())); - - // Claim the keystrokes the emulator will need. - addShortcutKeys(); - - // Add shortcut text - newStatusBar(i18n.getString("statusBarRunning")); - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor spawns a custom command line. @@ -321,38 +196,9 @@ public class TTerminalWindow extends TScrollableWindow } } - /** - * Terminate the child of the 'script' process used on POSIX. This may - * or may not work. - */ - private void terminateShellChildProcess() { - int pid = -1; - if (shell.getClass().getName().equals("java.lang.UNIXProcess")) { - /* get the PID on unix/linux systems */ - try { - Field field = shell.getClass().getDeclaredField("pid"); - field.setAccessible(true); - pid = field.getInt(shell); - } catch (Throwable e) { - // SQUASH, this didn't work. Just bail out quietly. - return; - } - } - if (pid != -1) { - // shell.destroy() works successfully at killing this side of - // 'script'. But we need to make sure the other side (child - // process) is also killed. - String [] cmdKillIt = { - "pkill", "-P", Integer.toString(pid) - }; - try { - Runtime.getRuntime().exec(cmdKillIt); - } catch (Throwable e) { - // SQUASH, this didn't work. Just bail out quietly. - return; - } - } - } + // ------------------------------------------------------------------------ + // TScrollableWindow ------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Draw the display buffer. @@ -455,34 +301,58 @@ public class TTerminalWindow extends TScrollableWindow } /** - * Called by emulator when fresh data has come in. - */ - public void displayChanged() { - getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT)); - } - - /** - * Function to call to obtain the display width. + * Handle window/screen resize events. * - * @return the number of columns in the display + * @param resize resize event */ - public int getDisplayWidth() { - if (ptypipe) { - return getWidth() - 2; - } - return 80; + @Override + public void onResize(final TResizeEvent resize) { + + // Synchronize against the emulator so we don't stomp on its reader + // thread. + synchronized (emulator) { + + if (resize.getType() == TResizeEvent.Type.WIDGET) { + // Resize the scroll bars + reflowData(); + placeScrollbars(); + + // Get out of scrollback + setVerticalValue(0); + + if (ptypipe) { + emulator.setWidth(getWidth() - 2); + emulator.setHeight(getHeight() - 2); + + emulator.writeRemote("\033[8;" + (getHeight() - 2) + ";" + + (getWidth() - 2) + "t"); + } + } + return; + + } // synchronized (emulator) } /** - * Function to call to obtain the display height. - * - * @return the number of rows in the display + * Resize scrollbars for a new width/height. */ - public int getDisplayHeight() { - if (ptypipe) { - return getHeight() - 2; - } - return 24; + @Override + public void reflowData() { + + // Synchronize against the emulator so we don't stomp on its reader + // thread. + synchronized (emulator) { + + // Pull cursor information + readEmulatorState(); + + // Vertical scrollbar + setTopValue(getHeight() - 2 + - (emulator.getScrollbackBuffer().size() + + emulator.getDisplayBuffer().size())); + setVerticalBigChange(getHeight() - 2); + + } // synchronized (emulator) } /** @@ -499,165 +369,12 @@ public class TTerminalWindow extends TScrollableWindow } /** - * Hook for subclasses to be notified of the shell termination. - */ - public void onShellExit() { - getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT)); - } - - /** - * Copy out variables from the emulator that TTerminal has to expose on - * screen. + * Handle keystrokes. + * + * @param keypress keystroke event */ - private void readEmulatorState() { - // Synchronize against the emulator so we don't stomp on its reader - // thread. - synchronized (emulator) { - - setCursorX(emulator.getCursorX() + 1); - setCursorY(emulator.getCursorY() + 1 - + (getHeight() - 2 - emulator.getHeight()) - - getVerticalValue()); - setCursorVisible(emulator.isCursorVisible()); - if (getCursorX() > getWidth() - 2) { - setCursorVisible(false); - } - if ((getCursorY() > getHeight() - 2) || (getCursorY() < 0)) { - setCursorVisible(false); - } - if (emulator.getScreenTitle().length() > 0) { - // Only update the title if the shell is still alive - if (shell != null) { - setTitle(emulator.getScreenTitle()); - } - } - - // Check to see if the shell has died. - if (!emulator.isReading() && (shell != null)) { - try { - int rc = shell.exitValue(); - // The emulator exited on its own, all is fine - setTitle(MessageFormat.format(i18n. - getString("windowTitleCompleted"), getTitle(), rc)); - shell = null; - emulator.close(); - clearShortcutKeypresses(); - statusBar.setText(MessageFormat.format(i18n. - getString("statusBarCompleted"), rc)); - onShellExit(); - } catch (IllegalThreadStateException e) { - // The emulator thread has exited, but the shell Process - // hasn't figured that out yet. Do nothing, we will see - // this in a future tick. - } - } else if (emulator.isReading() && (shell != null)) { - // The shell might be dead, let's check - try { - int rc = shell.exitValue(); - // If we got here, the shell died. - setTitle(MessageFormat.format(i18n. - getString("windowTitleCompleted"), getTitle(), rc)); - shell = null; - emulator.close(); - clearShortcutKeypresses(); - statusBar.setText(MessageFormat.format(i18n. - getString("statusBarCompleted"), rc)); - onShellExit(); - } catch (IllegalThreadStateException e) { - // The shell is still running, do nothing. - } - } - - } // synchronized (emulator) - } - - /** - * Handle window/screen resize events. - * - * @param resize resize event - */ - @Override - public void onResize(final TResizeEvent resize) { - - // Synchronize against the emulator so we don't stomp on its reader - // thread. - synchronized (emulator) { - - if (resize.getType() == TResizeEvent.Type.WIDGET) { - // Resize the scroll bars - reflowData(); - placeScrollbars(); - - // Get out of scrollback - setVerticalValue(0); - - if (ptypipe) { - emulator.setWidth(getWidth() - 2); - emulator.setHeight(getHeight() - 2); - - emulator.writeRemote("\033[8;" + (getHeight() - 2) + ";" + - (getWidth() - 2) + "t"); - } - } - return; - - } // synchronized (emulator) - } - - /** - * Resize scrollbars for a new width/height. - */ - @Override - public void reflowData() { - - // Synchronize against the emulator so we don't stomp on its reader - // thread. - synchronized (emulator) { - - // Pull cursor information - readEmulatorState(); - - // Vertical scrollbar - setTopValue(getHeight() - 2 - - (emulator.getScrollbackBuffer().size() - + emulator.getDisplayBuffer().size())); - setVerticalBigChange(getHeight() - 2); - - } // synchronized (emulator) - } - - /** - * Check if a mouse press/release/motion event coordinate is over the - * emulator. - * - * @param mouse a mouse-based event - * @return whether or not the mouse is on the emulator - */ - private final boolean mouseOnEmulator(final TMouseEvent mouse) { - - synchronized (emulator) { - if (!emulator.isReading()) { - return false; - } - } - - if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1) - && (mouse.getAbsoluteX() < getAbsoluteX() + getWidth() - 1) - && (mouse.getAbsoluteY() >= getAbsoluteY() + 1) - && (mouse.getAbsoluteY() < getAbsoluteY() + getHeight() - 1) - ) { - return true; - } - return false; - } - - /** - * Handle keystrokes. - * - * @param keypress keystroke event - */ - @Override - public void onKeypress(final TKeypressEvent keypress) { + @Override + public void onKeypress(final TKeypressEvent keypress) { // Scrollback up/down if (keypress.equals(kbShiftPgUp) @@ -789,4 +506,303 @@ public class TTerminalWindow extends TScrollableWindow super.onMouseMotion(mouse); } + // ------------------------------------------------------------------------ + // TTerminalWindow -------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Claim the keystrokes the emulator will need. + */ + private void addShortcutKeys() { + addShortcutKeypress(kbCtrlA); + addShortcutKeypress(kbCtrlB); + addShortcutKeypress(kbCtrlC); + addShortcutKeypress(kbCtrlD); + addShortcutKeypress(kbCtrlE); + addShortcutKeypress(kbCtrlF); + addShortcutKeypress(kbCtrlG); + addShortcutKeypress(kbCtrlH); + addShortcutKeypress(kbCtrlU); + addShortcutKeypress(kbCtrlJ); + addShortcutKeypress(kbCtrlK); + addShortcutKeypress(kbCtrlL); + addShortcutKeypress(kbCtrlM); + addShortcutKeypress(kbCtrlN); + addShortcutKeypress(kbCtrlO); + addShortcutKeypress(kbCtrlP); + addShortcutKeypress(kbCtrlQ); + addShortcutKeypress(kbCtrlR); + addShortcutKeypress(kbCtrlS); + addShortcutKeypress(kbCtrlT); + addShortcutKeypress(kbCtrlU); + addShortcutKeypress(kbCtrlV); + addShortcutKeypress(kbCtrlW); + addShortcutKeypress(kbCtrlX); + addShortcutKeypress(kbCtrlY); + addShortcutKeypress(kbCtrlZ); + addShortcutKeypress(kbF1); + addShortcutKeypress(kbF2); + addShortcutKeypress(kbF3); + addShortcutKeypress(kbF4); + addShortcutKeypress(kbF5); + addShortcutKeypress(kbF6); + addShortcutKeypress(kbF7); + addShortcutKeypress(kbF8); + addShortcutKeypress(kbF9); + addShortcutKeypress(kbF10); + addShortcutKeypress(kbF11); + addShortcutKeypress(kbF12); + addShortcutKeypress(kbAltA); + addShortcutKeypress(kbAltB); + addShortcutKeypress(kbAltC); + addShortcutKeypress(kbAltD); + addShortcutKeypress(kbAltE); + addShortcutKeypress(kbAltF); + addShortcutKeypress(kbAltG); + addShortcutKeypress(kbAltH); + addShortcutKeypress(kbAltU); + addShortcutKeypress(kbAltJ); + addShortcutKeypress(kbAltK); + addShortcutKeypress(kbAltL); + addShortcutKeypress(kbAltM); + addShortcutKeypress(kbAltN); + addShortcutKeypress(kbAltO); + addShortcutKeypress(kbAltP); + addShortcutKeypress(kbAltQ); + addShortcutKeypress(kbAltR); + addShortcutKeypress(kbAltS); + addShortcutKeypress(kbAltT); + addShortcutKeypress(kbAltU); + addShortcutKeypress(kbAltV); + addShortcutKeypress(kbAltW); + addShortcutKeypress(kbAltX); + addShortcutKeypress(kbAltY); + addShortcutKeypress(kbAltZ); + } + + /** + * Convert a string array to a whitespace-separated string. + * + * @param array the string array + * @return a single string + */ + private String stringArrayToString(final String [] array) { + StringBuilder sb = new StringBuilder(array[0].length()); + for (int i = 0; i < array.length; i++) { + sb.append(array[i]); + if (i < array.length - 1) { + sb.append(' '); + } + } + return sb.toString(); + } + + /** + * Spawn the shell. + * + * @param command the command line to execute + */ + private void spawnShell(final String [] command) { + + /* + System.err.printf("spawnShell(): '%s'\n", + stringArrayToString(command)); + */ + + vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2); + setBottomValue(0); + + // Assume XTERM + ECMA48.DeviceType deviceType = ECMA48.DeviceType.XTERM; + + try { + ProcessBuilder pb = new ProcessBuilder(command); + Map env = pb.environment(); + env.put("TERM", ECMA48.deviceTypeTerm(deviceType)); + env.put("LANG", ECMA48.deviceTypeLang(deviceType, "en")); + env.put("COLUMNS", "80"); + env.put("LINES", "24"); + pb.redirectErrorStream(true); + shell = pb.start(); + emulator = new ECMA48(deviceType, shell.getInputStream(), + shell.getOutputStream(), this); + } catch (IOException e) { + messageBox(i18n.getString("errorLaunchingShellTitle"), + MessageFormat.format(i18n.getString("errorLaunchingShellText"), + e.getMessage())); + } + + // Setup the scroll bars + onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(), + getHeight())); + + // Claim the keystrokes the emulator will need. + addShortcutKeys(); + + // Add shortcut text + newStatusBar(i18n.getString("statusBarRunning")); + } + + /** + * Terminate the child of the 'script' process used on POSIX. This may + * or may not work. + */ + private void terminateShellChildProcess() { + int pid = -1; + if (shell.getClass().getName().equals("java.lang.UNIXProcess")) { + /* get the PID on unix/linux systems */ + try { + Field field = shell.getClass().getDeclaredField("pid"); + field.setAccessible(true); + pid = field.getInt(shell); + } catch (Throwable e) { + // SQUASH, this didn't work. Just bail out quietly. + return; + } + } + if (pid != -1) { + // shell.destroy() works successfully at killing this side of + // 'script'. But we need to make sure the other side (child + // process) is also killed. + String [] cmdKillIt = { + "pkill", "-P", Integer.toString(pid) + }; + try { + Runtime.getRuntime().exec(cmdKillIt); + } catch (Throwable e) { + // SQUASH, this didn't work. Just bail out quietly. + return; + } + } + } + + /** + * Called by emulator when fresh data has come in. + */ + public void displayChanged() { + getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT)); + } + + /** + * Function to call to obtain the display width. + * + * @return the number of columns in the display + */ + public int getDisplayWidth() { + if (ptypipe) { + return getWidth() - 2; + } + return 80; + } + + /** + * Function to call to obtain the display height. + * + * @return the number of rows in the display + */ + public int getDisplayHeight() { + if (ptypipe) { + return getHeight() - 2; + } + return 24; + } + + /** + * Hook for subclasses to be notified of the shell termination. + */ + public void onShellExit() { + getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT)); + } + + /** + * Copy out variables from the emulator that TTerminal has to expose on + * screen. + */ + private void readEmulatorState() { + // Synchronize against the emulator so we don't stomp on its reader + // thread. + synchronized (emulator) { + + setCursorX(emulator.getCursorX() + 1); + setCursorY(emulator.getCursorY() + 1 + + (getHeight() - 2 - emulator.getHeight()) + - getVerticalValue()); + setCursorVisible(emulator.isCursorVisible()); + if (getCursorX() > getWidth() - 2) { + setCursorVisible(false); + } + if ((getCursorY() > getHeight() - 2) || (getCursorY() < 0)) { + setCursorVisible(false); + } + if (emulator.getScreenTitle().length() > 0) { + // Only update the title if the shell is still alive + if (shell != null) { + setTitle(emulator.getScreenTitle()); + } + } + + // Check to see if the shell has died. + if (!emulator.isReading() && (shell != null)) { + try { + int rc = shell.exitValue(); + // The emulator exited on its own, all is fine + setTitle(MessageFormat.format(i18n. + getString("windowTitleCompleted"), getTitle(), rc)); + shell = null; + emulator.close(); + clearShortcutKeypresses(); + statusBar.setText(MessageFormat.format(i18n. + getString("statusBarCompleted"), rc)); + onShellExit(); + } catch (IllegalThreadStateException e) { + // The emulator thread has exited, but the shell Process + // hasn't figured that out yet. Do nothing, we will see + // this in a future tick. + } + } else if (emulator.isReading() && (shell != null)) { + // The shell might be dead, let's check + try { + int rc = shell.exitValue(); + // If we got here, the shell died. + setTitle(MessageFormat.format(i18n. + getString("windowTitleCompleted"), getTitle(), rc)); + shell = null; + emulator.close(); + clearShortcutKeypresses(); + statusBar.setText(MessageFormat.format(i18n. + getString("statusBarCompleted"), rc)); + onShellExit(); + } catch (IllegalThreadStateException e) { + // The shell is still running, do nothing. + } + } + + } // synchronized (emulator) + } + + /** + * Check if a mouse press/release/motion event coordinate is over the + * emulator. + * + * @param mouse a mouse-based event + * @return whether or not the mouse is on the emulator + */ + private final boolean mouseOnEmulator(final TMouseEvent mouse) { + + synchronized (emulator) { + if (!emulator.isReading()) { + return false; + } + } + + if ((mouse.getAbsoluteX() >= getAbsoluteX() + 1) + && (mouse.getAbsoluteX() < getAbsoluteX() + getWidth() - 1) + && (mouse.getAbsoluteY() >= getAbsoluteY() + 1) + && (mouse.getAbsoluteY() < getAbsoluteY() + getHeight() - 1) + ) { + return true; + } + return false; + } + } diff --git a/src/jexer/TText.java b/src/jexer/TText.java index 0edb290..44176a4 100644 --- a/src/jexer/TText.java +++ b/src/jexer/TText.java @@ -34,7 +34,14 @@ import java.util.List; import jexer.bits.CellAttributes; import jexer.event.TKeypressEvent; import jexer.event.TMouseEvent; -import static jexer.TKeypress.*; +import static jexer.TKeypress.kbDown; +import static jexer.TKeypress.kbEnd; +import static jexer.TKeypress.kbHome; +import static jexer.TKeypress.kbLeft; +import static jexer.TKeypress.kbPgDn; +import static jexer.TKeypress.kbPgUp; +import static jexer.TKeypress.kbRight; +import static jexer.TKeypress.kbUp; /** * TText implements a simple scrollable text area. It reflows automatically on @@ -42,6 +49,10 @@ import static jexer.TKeypress.*; */ public class TText extends TScrollableWidget { + // ------------------------------------------------------------------------ + // Constants -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Available text justifications. */ @@ -67,6 +78,10 @@ public class TText extends TScrollableWidget { FULL, } + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * How to justify the text. */ @@ -97,148 +112,9 @@ public class TText extends TScrollableWidget { */ private int lineSpacing = 1; - /** - * Set the text. - * - * @param text new text to display - */ - public void setText(final String text) { - this.text = text; - reflowData(); - } - - /** - * Get the text. - * - * @return the text - */ - public String getText() { - return text; - } - - /** - * Convenience method used by TWindowLoggerOutput. - * - * @param line new line to add - */ - public void addLine(final String line) { - if (text.length() == 0) { - text = line; - } else { - text += "\n\n"; - text += line; - } - reflowData(); - } - - /** - * Recompute the bounds for the scrollbars. - */ - private void computeBounds() { - maxLineWidth = 0; - for (String line : lines) { - if (line.length() > maxLineWidth) { - maxLineWidth = line.length(); - } - } - - vScroller.setTopValue(0); - vScroller.setBottomValue((lines.size() - getHeight()) + 1); - if (vScroller.getBottomValue() < 0) { - vScroller.setBottomValue(0); - } - if (vScroller.getValue() > vScroller.getBottomValue()) { - vScroller.setValue(vScroller.getBottomValue()); - } - - hScroller.setLeftValue(0); - hScroller.setRightValue((maxLineWidth - getWidth()) + 1); - if (hScroller.getRightValue() < 0) { - hScroller.setRightValue(0); - } - if (hScroller.getValue() > hScroller.getRightValue()) { - hScroller.setValue(hScroller.getRightValue()); - } - } - - /** - * Set justification. - * - * @param justification LEFT, CENTER, RIGHT, or FULL - */ - public void setJustification(final Justification justification) { - this.justification = justification; - reflowData(); - } - - /** - * Left-justify the text. - */ - public void leftJustify() { - justification = Justification.LEFT; - reflowData(); - } - - /** - * Center-justify the text. - */ - public void centerJustify() { - justification = Justification.CENTER; - reflowData(); - } - - /** - * Right-justify the text. - */ - public void rightJustify() { - justification = Justification.RIGHT; - reflowData(); - } - - /** - * Fully-justify the text. - */ - public void fullJustify() { - justification = Justification.FULL; - reflowData(); - } - - /** - * Resize text and scrollbars for a new width/height. - */ - @Override - public void reflowData() { - // Reset the lines - lines.clear(); - - // Break up text into paragraphs - String[] paragraphs = text.split("\n\n"); - for (String p : paragraphs) { - switch (justification) { - case LEFT: - lines.addAll(jexer.bits.StringUtils.left(p, - getWidth() - 1)); - break; - case CENTER: - lines.addAll(jexer.bits.StringUtils.center(p, - getWidth() - 1)); - break; - case RIGHT: - lines.addAll(jexer.bits.StringUtils.right(p, - getWidth() - 1)); - break; - case FULL: - lines.addAll(jexer.bits.StringUtils.full(p, - getWidth() - 1)); - break; - } - - for (int i = 0; i < lineSpacing; i++) { - lines.add(""); - } - } - computeBounds(); - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor. @@ -285,6 +161,10 @@ public class TText extends TScrollableWidget { reflowData(); } + // ------------------------------------------------------------------------ + // TScrollableWidget ------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * Draw the text box. */ @@ -368,4 +248,151 @@ public class TText extends TScrollableWidget { } } + /** + * Resize text and scrollbars for a new width/height. + */ + @Override + public void reflowData() { + // Reset the lines + lines.clear(); + + // Break up text into paragraphs + String[] paragraphs = text.split("\n\n"); + for (String p : paragraphs) { + switch (justification) { + case LEFT: + lines.addAll(jexer.bits.StringUtils.left(p, + getWidth() - 1)); + break; + case CENTER: + lines.addAll(jexer.bits.StringUtils.center(p, + getWidth() - 1)); + break; + case RIGHT: + lines.addAll(jexer.bits.StringUtils.right(p, + getWidth() - 1)); + break; + case FULL: + lines.addAll(jexer.bits.StringUtils.full(p, + getWidth() - 1)); + break; + } + + for (int i = 0; i < lineSpacing; i++) { + lines.add(""); + } + } + computeBounds(); + } + + // ------------------------------------------------------------------------ + // TText ------------------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Set the text. + * + * @param text new text to display + */ + public void setText(final String text) { + this.text = text; + reflowData(); + } + + /** + * Get the text. + * + * @return the text + */ + public String getText() { + return text; + } + + /** + * Convenience method used by TWindowLoggerOutput. + * + * @param line new line to add + */ + public void addLine(final String line) { + if (text.length() == 0) { + text = line; + } else { + text += "\n\n"; + text += line; + } + reflowData(); + } + + /** + * Recompute the bounds for the scrollbars. + */ + private void computeBounds() { + maxLineWidth = 0; + for (String line : lines) { + if (line.length() > maxLineWidth) { + maxLineWidth = line.length(); + } + } + + vScroller.setTopValue(0); + vScroller.setBottomValue((lines.size() - getHeight()) + 1); + if (vScroller.getBottomValue() < 0) { + vScroller.setBottomValue(0); + } + if (vScroller.getValue() > vScroller.getBottomValue()) { + vScroller.setValue(vScroller.getBottomValue()); + } + + hScroller.setLeftValue(0); + hScroller.setRightValue((maxLineWidth - getWidth()) + 1); + if (hScroller.getRightValue() < 0) { + hScroller.setRightValue(0); + } + if (hScroller.getValue() > hScroller.getRightValue()) { + hScroller.setValue(hScroller.getRightValue()); + } + } + + /** + * Set justification. + * + * @param justification LEFT, CENTER, RIGHT, or FULL + */ + public void setJustification(final Justification justification) { + this.justification = justification; + reflowData(); + } + + /** + * Left-justify the text. + */ + public void leftJustify() { + justification = Justification.LEFT; + reflowData(); + } + + /** + * Center-justify the text. + */ + public void centerJustify() { + justification = Justification.CENTER; + reflowData(); + } + + /** + * Right-justify the text. + */ + public void rightJustify() { + justification = Justification.RIGHT; + reflowData(); + } + + /** + * Fully-justify the text. + */ + public void fullJustify() { + justification = Justification.FULL; + reflowData(); + } + } diff --git a/src/jexer/demos/DemoMsgBoxWindow.java b/src/jexer/demos/DemoMsgBoxWindow.java index b6c9404..ee2bca1 100644 --- a/src/jexer/demos/DemoMsgBoxWindow.java +++ b/src/jexer/demos/DemoMsgBoxWindow.java @@ -166,7 +166,8 @@ public class DemoMsgBoxWindow extends TWindow { "This one has both OK and Cancel buttons.\n", "some input text", TInputBox.Type.OKCANCEL); getApplication().messageBox("Your InputBox Answer", - "You entered: " + in.getText()); + "You entered: " + in.getText() + " and pressed " + + in.getResult()); } } ); diff --git a/src/jexer/event/TCommandEvent.java b/src/jexer/event/TCommandEvent.java index 749e3f7..53b9ad2 100644 --- a/src/jexer/event/TCommandEvent.java +++ b/src/jexer/event/TCommandEvent.java @@ -37,19 +37,18 @@ import jexer.TCommand; */ public class TCommandEvent extends TInputEvent { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Command dispatched. */ private TCommand cmd; - /** - * Get TCommand. - * - * @return the TCommand - */ - public TCommand getCmd() { - return cmd; - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public contructor. @@ -60,6 +59,10 @@ public class TCommandEvent extends TInputEvent { this.cmd = cmd; } + // ------------------------------------------------------------------------ + // TInputEvent ------------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * Comparison check. All fields must match to return true. * @@ -108,4 +111,18 @@ public class TCommandEvent extends TInputEvent { public String toString() { return String.format("CommandEvent: %s", cmd.toString()); } + + // ------------------------------------------------------------------------ + // TCommandEvent ---------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Get TCommand. + * + * @return the TCommand + */ + public TCommand getCmd() { + return cmd; + } + } diff --git a/src/jexer/event/TInputEvent.java b/src/jexer/event/TInputEvent.java index 46ecfac..d03ef01 100644 --- a/src/jexer/event/TInputEvent.java +++ b/src/jexer/event/TInputEvent.java @@ -35,11 +35,31 @@ import java.util.Date; */ public abstract class TInputEvent { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Time at which event was generated. */ private Date time; + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Protected contructor. + */ + protected TInputEvent() { + // Save the current time + time = new Date(); + } + + // ------------------------------------------------------------------------ + // TInputEvent ------------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * Get time. * @@ -49,11 +69,4 @@ public abstract class TInputEvent { return time; } - /** - * Protected contructor. - */ - protected TInputEvent() { - // Save the current time - time = new Date(); - } } diff --git a/src/jexer/event/TKeypressEvent.java b/src/jexer/event/TKeypressEvent.java index bdf5e84..f499369 100644 --- a/src/jexer/event/TKeypressEvent.java +++ b/src/jexer/event/TKeypressEvent.java @@ -35,19 +35,18 @@ import jexer.TKeypress; */ public class TKeypressEvent extends TInputEvent { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Keystroke received. */ private TKeypress key; - /** - * Get keystroke. - * - * @return keystroke - */ - public TKeypress getKey() { - return key; - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public contructor. @@ -89,15 +88,9 @@ public class TKeypressEvent extends TInputEvent { alt, ctrl, shift); } - /** - * Create a duplicate instance. - * - * @return duplicate intance - */ - public TKeypressEvent dup() { - TKeypressEvent keypress = new TKeypressEvent(key.dup()); - return keypress; - } + // ------------------------------------------------------------------------ + // TInputEvent ------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Comparison check. All fields must match to return true. @@ -147,4 +140,28 @@ public class TKeypressEvent extends TInputEvent { public String toString() { return String.format("Keypress: %s", key.toString()); } + + // ------------------------------------------------------------------------ + // TKeypressEvent --------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Get keystroke. + * + * @return keystroke + */ + public TKeypress getKey() { + return key; + } + + /** + * Create a duplicate instance. + * + * @return duplicate intance + */ + public TKeypressEvent dup() { + TKeypressEvent keypress = new TKeypressEvent(key.dup()); + return keypress; + } + } diff --git a/src/jexer/event/TMenuEvent.java b/src/jexer/event/TMenuEvent.java index 491a735..5117846 100644 --- a/src/jexer/event/TMenuEvent.java +++ b/src/jexer/event/TMenuEvent.java @@ -35,19 +35,18 @@ package jexer.event; */ public class TMenuEvent extends TInputEvent { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * MenuItem ID. */ private int id; - /** - * Get the MenuItem ID. - * - * @return the ID - */ - public int getId() { - return id; - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public contructor. @@ -58,6 +57,10 @@ public class TMenuEvent extends TInputEvent { this.id = id; } + // ------------------------------------------------------------------------ + // TInputEvent ------------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * Make human-readable description of this TMenuEvent. * @@ -67,4 +70,18 @@ public class TMenuEvent extends TInputEvent { public String toString() { return String.format("MenuEvent: %d", id); } + + // ------------------------------------------------------------------------ + // TMenuEvent ------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Get the MenuItem ID. + * + * @return the ID + */ + public int getId() { + return id; + } + } diff --git a/src/jexer/io/TimeoutInputStream.java b/src/jexer/io/TimeoutInputStream.java index db9eb4a..d654262 100644 --- a/src/jexer/io/TimeoutInputStream.java +++ b/src/jexer/io/TimeoutInputStream.java @@ -37,6 +37,10 @@ import java.io.InputStream; */ public class TimeoutInputStream extends InputStream { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The wrapped stream. */ @@ -54,12 +58,9 @@ public class TimeoutInputStream extends InputStream { */ private volatile boolean cancel = false; - /** - * Request that the current read() operation timeout immediately. - */ - public synchronized void cancelRead() { - cancel = true; - } + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ /** * Public constructor, at the default timeout of 10000 millis (10 @@ -93,6 +94,10 @@ public class TimeoutInputStream extends InputStream { this.timeoutMillis = timeoutMillis; } + // ------------------------------------------------------------------------ + // InputStream ------------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * Reads the next byte of data from the input stream. * @@ -209,7 +214,9 @@ public class TimeoutInputStream extends InputStream { "on?"); } remaining -= rc; - return rc; + if (remaining == 0) { + return b.length; + } } } @@ -283,7 +290,10 @@ public class TimeoutInputStream extends InputStream { "available, but read() returned -1. What is going " + "on?"); } - return rc; + remaining -= rc; + if (remaining == 0) { + return len; + } } } @@ -362,4 +372,15 @@ public class TimeoutInputStream extends InputStream { return stream.skip(n); } + // ------------------------------------------------------------------------ + // TimeoutInputStream ----------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Request that the current read() operation timeout immediately. + */ + public synchronized void cancelRead() { + cancel = true; + } + } diff --git a/src/jexer/teditor/Document.java b/src/jexer/teditor/Document.java index e1a28a0..bd8e91f 100644 --- a/src/jexer/teditor/Document.java +++ b/src/jexer/teditor/Document.java @@ -41,6 +41,10 @@ import jexer.bits.CellAttributes; */ public class Document { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The list of lines. */ @@ -72,6 +76,32 @@ public class Document { */ private Highlighter highlighter = new Highlighter(); + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Construct a new Document from an existing text string. + * + * @param str the text string + * @param defaultColor the color for unhighlighted text + */ + public Document(final String str, final CellAttributes defaultColor) { + this.defaultColor = defaultColor; + + // TODO: set different colors based on file extension + highlighter.setJavaColors(); + + String [] rawLines = str.split("\n"); + for (int i = 0; i < rawLines.length; i++) { + lines.add(new Line(rawLines[i], this.defaultColor, highlighter)); + } + } + + // ------------------------------------------------------------------------ + // Document --------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Get the overwrite flag. * @@ -192,24 +222,6 @@ public class Document { } } - /** - * Construct a new Document from an existing text string. - * - * @param str the text string - * @param defaultColor the color for unhighlighted text - */ - public Document(final String str, final CellAttributes defaultColor) { - this.defaultColor = defaultColor; - - // TODO: set different colors based on file extension - highlighter.setJavaColors(); - - String [] rawLines = str.split("\n"); - for (int i = 0; i < rawLines.length; i++) { - lines.add(new Line(rawLines[i], this.defaultColor, highlighter)); - } - } - /** * Increment the line number by one. If at the last line, do nothing. * diff --git a/src/jexer/teditor/Highlighter.java b/src/jexer/teditor/Highlighter.java index 9576ad1..4a1ae90 100644 --- a/src/jexer/teditor/Highlighter.java +++ b/src/jexer/teditor/Highlighter.java @@ -39,11 +39,19 @@ import jexer.bits.Color; */ public class Highlighter { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The highlighter colors. */ private SortedMap colors; + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Public constructor sets the theme to the default. */ @@ -51,6 +59,10 @@ public class Highlighter { colors = new TreeMap(); } + // ------------------------------------------------------------------------ + // Highlighter ------------------------------------------------------------ + // ------------------------------------------------------------------------ + /** * See if this is a character that should split a word. * @@ -129,5 +141,4 @@ public class Highlighter { } - } diff --git a/src/jexer/teditor/Line.java b/src/jexer/teditor/Line.java index d6016c2..400de9a 100644 --- a/src/jexer/teditor/Line.java +++ b/src/jexer/teditor/Line.java @@ -39,6 +39,10 @@ import jexer.bits.CellAttributes; */ public class Line { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The list of words. */ @@ -65,6 +69,42 @@ public class Line { */ private StringBuilder rawText; + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Construct a new Line from an existing text string, and highlight + * certain strings. + * + * @param str the text string + * @param defaultColor the color for unhighlighted text + * @param highlighter the highlighter to use + */ + public Line(final String str, final CellAttributes defaultColor, + final Highlighter highlighter) { + + this.defaultColor = defaultColor; + this.highlighter = highlighter; + this.rawText = new StringBuilder(str); + + scanLine(); + } + + /** + * Construct a new Line from an existing text string. + * + * @param str the text string + * @param defaultColor the color for unhighlighted text + */ + public Line(final String str, final CellAttributes defaultColor) { + this(str, defaultColor, null); + } + + // ------------------------------------------------------------------------ + // Line ------------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Get a (shallow) copy of the words in this line. * @@ -145,34 +185,6 @@ public class Line { } } - /** - * Construct a new Line from an existing text string, and highlight - * certain strings. - * - * @param str the text string - * @param defaultColor the color for unhighlighted text - * @param highlighter the highlighter to use - */ - public Line(final String str, final CellAttributes defaultColor, - final Highlighter highlighter) { - - this.defaultColor = defaultColor; - this.highlighter = highlighter; - this.rawText = new StringBuilder(str); - - scanLine(); - } - - /** - * Construct a new Line from an existing text string. - * - * @param str the text string - * @param defaultColor the color for unhighlighted text - */ - public Line(final String str, final CellAttributes defaultColor) { - this(str, defaultColor, null); - } - /** * Decrement the cursor by one. If at the first column, do nothing. * diff --git a/src/jexer/teditor/Word.java b/src/jexer/teditor/Word.java index d4532bb..11fa39d 100644 --- a/src/jexer/teditor/Word.java +++ b/src/jexer/teditor/Word.java @@ -40,6 +40,10 @@ import jexer.bits.CellAttributes; */ public class Word { + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * The color to render this word as on screen. */ @@ -61,6 +65,42 @@ public class Word { */ private StringBuilder text = new StringBuilder(3); + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Construct a word with one character. + * + * @param ch the first character of the word + * @param defaultColor the color for unhighlighted text + * @param highlighter the highlighter to use + */ + public Word(final char ch, final CellAttributes defaultColor, + final Highlighter highlighter) { + + this.defaultColor = defaultColor; + this.highlighter = highlighter; + text.append(ch); + } + + /** + * Construct a word with an empty string. + * + * @param defaultColor the color for unhighlighted text + * @param highlighter the highlighter to use + */ + public Word(final CellAttributes defaultColor, + final Highlighter highlighter) { + + this.defaultColor = defaultColor; + this.highlighter = highlighter; + } + + // ------------------------------------------------------------------------ + // Word ------------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** * Get the color used to display this word on screen. * @@ -118,34 +158,6 @@ public class Word { return false; } - /** - * Construct a word with one character. - * - * @param ch the first character of the word - * @param defaultColor the color for unhighlighted text - * @param highlighter the highlighter to use - */ - public Word(final char ch, final CellAttributes defaultColor, - final Highlighter highlighter) { - - this.defaultColor = defaultColor; - this.highlighter = highlighter; - text.append(ch); - } - - /** - * Construct a word with an empty string. - * - * @param defaultColor the color for unhighlighted text - * @param highlighter the highlighter to use - */ - public Word(final CellAttributes defaultColor, - final Highlighter highlighter) { - - this.defaultColor = defaultColor; - this.highlighter = highlighter; - } - /** * Perform highlighting. */ -- 2.27.0