X-Git-Url: http://git.nikiroo.be/?p=nikiroo-utils.git;a=blobdiff_plain;f=src%2Fjexer%2FTEditorWidget.java;h=361ed83b9be4bc8355c53f9ad4318746e78363b8;hp=6fed1fc818f05356f02e34b88dc7f9bd429e20e9;hb=e8a11f986bfe2556e450d7b8ad6ef0059b369bbc;hpb=12b55d76e3473407bf37fca3667860240cb8f3be diff --git a/src/jexer/TEditorWidget.java b/src/jexer/TEditorWidget.java index 6fed1fc..361ed83 100644 --- a/src/jexer/TEditorWidget.java +++ b/src/jexer/TEditorWidget.java @@ -31,6 +31,7 @@ package jexer; import jexer.bits.CellAttributes; import jexer.event.TKeypressEvent; import jexer.event.TMouseEvent; +import jexer.event.TResizeEvent; import jexer.teditor.Document; import jexer.teditor.Line; import jexer.teditor.Word; @@ -47,6 +48,21 @@ public final class TEditorWidget extends TWidget { */ private Document document; + /** + * The default color for the TEditor class. + */ + private CellAttributes defaultColor = null; + + /** + * The topmost line number in the visible area. 0-based. + */ + private int topLine = 0; + + /** + * The leftmost column number in the visible area. 0-based. + */ + private int leftColumn = 0; + /** * Public constructor. * @@ -64,7 +80,9 @@ public final class TEditorWidget extends TWidget { super(parent, x, y, width, height); setCursorVisible(true); - document = new Document(text); + + defaultColor = getTheme().getColor("teditor"); + document = new Document(text, defaultColor); } /** @@ -72,23 +90,21 @@ public final class TEditorWidget extends TWidget { */ @Override public void draw() { - // Setup my color - CellAttributes color = getTheme().getColor("teditor"); - - int lineNumber = document.getLineNumber(); for (int i = 0; i < getHeight(); i++) { // Background line - getScreen().hLineXY(0, i, getWidth(), ' ', color); + getScreen().hLineXY(0, i, getWidth(), ' ', defaultColor); // Now draw document's line - if (lineNumber + i < document.getLineCount()) { - Line line = document.getLine(lineNumber + i); + if (topLine + i < document.getLineCount()) { + Line line = document.getLine(topLine + i); int x = 0; for (Word word: line.getWords()) { - getScreen().putStringXY(x, i, word.getText(), + // For now, we are cheating: draw outside the left region + // if needed and let screen do the clipping. + getScreen().putStringXY(x - leftColumn, i, word.getText(), word.getColor()); x += word.getDisplayLength(); - if (x > getWidth()) { + if (x - leftColumn > getWidth()) { break; } } @@ -105,20 +121,93 @@ public final class TEditorWidget extends TWidget { @Override public void onMouseDown(final TMouseEvent mouse) { if (mouse.isMouseWheelUp()) { - document.up(); + if (getCursorY() == getHeight() - 1) { + if (document.up()) { + if (topLine > 0) { + topLine--; + } + alignCursor(); + } + } else { + if (topLine > 0) { + topLine--; + setCursorY(getCursorY() + 1); + } + } return; } if (mouse.isMouseWheelDown()) { - document.down(); + if (getCursorY() == 0) { + if (document.down()) { + if (topLine < document.getLineNumber()) { + topLine++; + } + alignCursor(); + } + } else { + if (topLine < document.getLineCount() - getHeight()) { + topLine++; + setCursorY(getCursorY() - 1); + } + } return; } - // TODO: click sets row and column + if (mouse.isMouse1()) { + // Set the row and column + int newLine = topLine + mouse.getY(); + int newX = leftColumn + mouse.getX(); + if (newLine > document.getLineCount()) { + // Go to the end + document.setLineNumber(document.getLineCount() - 1); + document.end(); + if (document.getLineCount() > getHeight()) { + setCursorY(getHeight() - 1); + } else { + setCursorY(document.getLineCount() - 1); + } + alignCursor(); + return; + } + + document.setLineNumber(newLine); + setCursorY(mouse.getY()); + if (newX > document.getCurrentLine().getDisplayLength()) { + document.end(); + alignCursor(); + } else { + setCursorX(mouse.getX()); + } + return; + } // Pass to children super.onMouseDown(mouse); } + /** + * 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. * @@ -127,33 +216,104 @@ public final class TEditorWidget extends TWidget { @Override public void onKeypress(final TKeypressEvent keypress) { if (keypress.equals(kbLeft)) { - document.left(); + if (document.left()) { + alignCursor(); + } } else if (keypress.equals(kbRight)) { - document.right(); + if (document.right()) { + alignCursor(); + } } else if (keypress.equals(kbUp)) { - document.up(); + if (document.up()) { + if (getCursorY() > 0) { + setCursorY(getCursorY() - 1); + } else { + if (topLine > 0) { + topLine--; + } + } + alignCursor(); + } } else if (keypress.equals(kbDown)) { - document.down(); + if (document.down()) { + if (getCursorY() < getHeight() - 1) { + setCursorY(getCursorY() + 1); + } else { + if (topLine < document.getLineCount() - getHeight()) { + topLine++; + } + } + alignCursor(); + } } else if (keypress.equals(kbPgUp)) { - document.up(getHeight() - 1); + for (int i = 0; i < getHeight() - 1; i++) { + if (document.up()) { + if (getCursorY() > 0) { + setCursorY(getCursorY() - 1); + } else { + if (topLine > 0) { + topLine--; + } + } + alignCursor(); + } else { + break; + } + } } else if (keypress.equals(kbPgDn)) { - document.down(getHeight() - 1); + for (int i = 0; i < getHeight() - 1; i++) { + if (document.down()) { + if (getCursorY() < getHeight() - 1) { + setCursorY(getCursorY() + 1); + } else { + if (topLine < document.getLineCount() - getHeight()) { + topLine++; + } + } + alignCursor(); + } else { + break; + } + } } else if (keypress.equals(kbHome)) { - document.home(); + if (document.home()) { + leftColumn = 0; + if (leftColumn < 0) { + leftColumn = 0; + } + setCursorX(0); + } } else if (keypress.equals(kbEnd)) { - document.end(); + if (document.end()) { + alignCursor(); + } } else if (keypress.equals(kbCtrlHome)) { document.setLineNumber(0); document.home(); + topLine = 0; + leftColumn = 0; + setCursorX(0); + setCursorY(0); } else if (keypress.equals(kbCtrlEnd)) { document.setLineNumber(document.getLineCount() - 1); document.end(); + topLine = document.getLineCount() - getHeight(); + if (topLine < 0) { + topLine = 0; + } + if (document.getLineCount() > getHeight()) { + setCursorY(getHeight() - 1); + } else { + setCursorY(document.getLineCount() - 1); + } + alignCursor(); } else if (keypress.equals(kbIns)) { document.setOverwrite(!document.getOverwrite()); } else if (keypress.equals(kbDel)) { document.del(); } else if (keypress.equals(kbBackspace)) { document.backspace(); + alignCursor(); } else if (!keypress.getKey().isFnKey() && !keypress.getKey().isAlt() && !keypress.getKey().isCtrl() @@ -166,4 +326,32 @@ public final class TEditorWidget extends TWidget { } } + /** + * Method that subclasses can override to handle window/screen resize + * events. + * + * @param resize resize event + */ + @Override + public void onResize(final TResizeEvent resize) { + // Change my width/height, and pull the cursor in as needed. + if (resize.getType() == TResizeEvent.Type.WIDGET) { + setWidth(resize.getWidth()); + setHeight(resize.getHeight()); + // See if the cursor is now outside the window, and if so move + // things. + if (getCursorX() >= getWidth()) { + leftColumn += getCursorX() - (getWidth() - 1); + setCursorX(getWidth() - 1); + } + if (getCursorY() >= getHeight()) { + topLine += getCursorY() - (getHeight() - 1); + setCursorY(getHeight() - 1); + } + } else { + // Let superclass handle it + super.onResize(resize); + } + } + }