BUG: TTreeView.reflow() doesn't keep the vertical dot within the
scrollbar.
-0.0.5
-
-- TEditor
- - Document
- - Filename
- - Pick appropriate Highlighter: plain, Java, XML, ...
- - TEditorWidget:
- - Cut and Paste
- - TTextArea extends TScrollableWidget
-
0.0.6
- TEditor
- True tokenization and syntax highlighting: Java, C, Clojure, XML
- Tab character support
+ - Cut and Paste
- Finish up multiscreen support:
- cmAbort to cmScreenDisconnected
Jexer Work Log
==============
+August 14, 2017
+
+TEditor is basically done. Mouse movement, keyboard movement,
+backspace / delete / enter / etc. are all in. Things are starting to
+look pretty good.
+
+I'm going to prep for a final cut and release tag tomorrow or the next
+evening. I need to take a break and get some meatspace life dealt
+with.
+
August 12, 2017
TEditor is stubbed in about 50% complete now. I have a Highlighter
and if so grab it. Perhaps I can put together some good Turbo Vision
resources too. At the very least direct people to the Borland-derived
C++ releases and Free Vision.
-
}
}
}
-
}
/**
// Set the row and column
int newLine = topLine + mouse.getY();
int newX = leftColumn + mouse.getX();
- if (newLine > document.getLineCount()) {
+ if (newLine > document.getLineCount() - 1) {
// Go to the end
document.setLineNumber(document.getLineCount() - 1);
document.end();
- if (document.getLineCount() > getHeight()) {
- setCursorY(getHeight() - 1);
+ if (newLine > document.getLineCount() - 1) {
+ setCursorY(document.getLineCount() - 1 - topLine);
} else {
- setCursorY(document.getLineCount() - 1);
+ setCursorY(mouse.getY());
}
alignCursor();
return;
document.end();
alignCursor();
} else {
+ document.setCursor(newX);
setCursorX(mouse.getX());
}
return;
*/
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.
} else {
document.setLineNumber(topLine + (getHeight() - 1));
}
+ if (cursor < document.getCurrentLine().getDisplayLength()) {
+ document.setCursor(cursor);
+ }
}
/*
/*
System.err.println("document cursor " + document.getCursor() +
" leftColumn " + leftColumn);
- */
+ */
+
setCursorX(document.getCursor() - leftColumn);
}
@Override
public void onKeypress(final TKeypressEvent keypress) {
if (keypress.equals(kbLeft)) {
- if (document.left()) {
- alignCursor();
- }
+ document.left();
+ alignTopLine(false);
} else if (keypress.equals(kbRight)) {
- if (document.right()) {
- alignCursor();
- }
+ document.right();
+ alignTopLine(true);
} else if (keypress.equals(kbUp)) {
document.up();
alignTopLine(false);
} else if (keypress.equals(kbIns)) {
document.setOverwrite(!document.getOverwrite());
} else if (keypress.equals(kbDel)) {
- // TODO: join lines
document.del();
alignCursor();
} else if (keypress.equals(kbBackspace)) {
document.backspace();
+ alignTopLine(false);
+ } else if (keypress.equals(kbTab)) {
+ // TODO: tab character. For now just add spaces until we hit
+ // modulo 8.
+ for (int i = document.getCursor(); (i + 1) % 8 != 0; i++) {
+ document.addChar(' ');
+ }
alignCursor();
} else if (keypress.equals(kbEnter)) {
- // TODO: split lines
+ document.enter();
+ alignTopLine(true);
} else if (!keypress.getKey().isFnKey()
&& !keypress.getKey().isAlt()
&& !keypress.getKey().isCtrl()
setupAfterEditor();
}
+ /**
+ * Public constructor opens a file.
+ *
+ * @param parent the main application
+ * @param file the file to open
+ * @throws IOException if a java.io operation throws
+ */
+ public TEditorWindow(final TApplication parent,
+ final File file) throws IOException {
+
+ super(parent, file.getName(), 0, 0, parent.getScreen().getWidth(),
+ parent.getScreen().getHeight() - 2, RESIZABLE);
+
+ filename = file.getName();
+ String contents = readFileData(file);
+ editField = addEditor(contents, 0, 0, getWidth() - 2, getHeight() - 2);
+ setupAfterEditor();
+ }
+
/**
* Public constructor.
*
this(parent, "New Text Document");
}
+ /**
+ * 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));
+ }
+
/**
* Draw the window.
*/
*/
@Override
public void onMouseDown(final TMouseEvent mouse) {
+ // Use TWidget's code to pass the event to the children.
+ super.onMouseDown(mouse);
+
if (mouseOnEditor(mouse)) {
- editField.onMouseDown(mouse);
+ // The editor might have changed, update the scollbars.
setBottomValue(editField.getMaximumRowNumber());
setVerticalValue(editField.getEditingRowNumber());
setRightValue(editField.getMaximumColumnNumber());
setHorizontalValue(editField.getEditingColumnNumber());
} else {
- // Let the scrollbars get the event
- super.onMouseDown(mouse);
-
if (mouse.isMouseWheelUp() || mouse.isMouseWheelDown()) {
+ // Vertical scrollbar actions
editField.setEditingRowNumber(getVerticalValue());
}
// TODO: horizontal scrolling
if (command.equals(cmOpen)) {
try {
String filename = fileOpenBox(".");
- if (filename != null) {
- try {
- File file = new File(filename);
- StringBuilder fileContents = new StringBuilder();
- Scanner scanner = new Scanner(file);
- String EOL = System.getProperty("line.separator");
-
- try {
- while (scanner.hasNextLine()) {
- fileContents.append(scanner.nextLine() + EOL);
- }
- new TEditorWindow(getApplication(), filename,
- fileContents.toString());
- } finally {
- scanner.close();
- }
- } catch (IOException e) {
- // TODO: make this a message box
- e.printStackTrace();
- }
- }
+ if (filename != null) {
+ try {
+ String contents = readFileData(filename);
+ new TEditorWindow(getApplication(), filename, contents);
+ } catch (IOException e) {
+ messageBox("Error", "Error reading file: " +
+ e.getMessage());
+ }
+ }
} catch (IOException e) {
- // TODO: make this a message box
- e.printStackTrace();
+ messageBox("Error", "Error opening file dialog: " +
+ e.getMessage());
}
return;
}
try {
editField.saveToFilename(filename);
} catch (IOException e) {
- // TODO: make this a message box
- e.printStackTrace();
+ messageBox("Error", "Error saving file: " + e.getMessage());
}
}
return;
getScreen().hLineXY(x, y, n, ch, attr);
}
-
}
package jexer.demos;
import java.io.*;
-import java.util.*;
import jexer.*;
import jexer.event.*;
String filename = fileOpenBox(".");
if (filename != null) {
try {
- File file = new File(filename);
- StringBuilder fileContents = new StringBuilder();
- Scanner scanner = new Scanner(file);
- String EOL = System.getProperty("line.separator");
-
- try {
- while (scanner.hasNextLine()) {
- fileContents.append(scanner.nextLine() + EOL);
- }
- new DemoTextWindow(this, filename,
- fileContents.toString());
- } finally {
- scanner.close();
- }
+ new TEditorWindow(this, new File(filename));
} catch (IOException e) {
e.printStackTrace();
}
*/
package jexer.demos;
+import java.io.*;
+
import jexer.*;
+import jexer.event.*;
import static jexer.TCommand.*;
import static jexer.TKeypress.*;
statusBar.addShortcutKeypress(kbF3, cmOpen, "Open");
statusBar.addShortcutKeypress(kbF10, cmExit, "Exit");
}
+
+ /**
+ * Method that subclasses can override to handle posted command events.
+ *
+ * @param command command event
+ */
+ @Override
+ public void onCommand(final TCommandEvent command) {
+ if (command.equals(cmOpen)) {
+ try {
+ String filename = fileOpenBox(".");
+ if (filename != null) {
+ try {
+ new TEditorWindow(getApplication(), new File(filename));
+ } catch (IOException e) {
+ messageBox("Error", "Error reading file: " +
+ e.getMessage());
+ }
+ }
+ } catch (IOException e) {
+ messageBox("Error", "Error opening file dialog: " +
+ e.getMessage());
+ }
+ return;
+ }
+
+ // Didn't handle it, let children get it instead
+ super.onCommand(command);
+ }
+
}
* @return true if the cursor position changed
*/
public boolean left() {
- return lines.get(lineNumber).left();
+ if (!lines.get(lineNumber).left()) {
+ // We are on the leftmost column, wrap
+ if (up()) {
+ end();
+ } else {
+ return false;
+ }
+ }
+ return true;
}
/**
* @return true if the cursor position changed
*/
public boolean right() {
- return lines.get(lineNumber).right();
+ if (!lines.get(lineNumber).right()) {
+ // We are on the rightmost column, wrap
+ if (down()) {
+ home();
+ } else {
+ return false;
+ }
+ }
+ return true;
}
/**
*/
public void del() {
dirty = true;
- lines.get(lineNumber).del();
+ int cursor = lines.get(lineNumber).getCursor();
+ if (cursor < lines.get(lineNumber).getDisplayLength() - 1) {
+ lines.get(lineNumber).del();
+ } else if (lineNumber < lines.size() - 2) {
+ // Join two lines
+ StringBuilder newLine = new StringBuilder(lines.
+ get(lineNumber).getRawString());
+ newLine.append(lines.get(lineNumber + 1).getRawString());
+ lines.set(lineNumber, new Line(newLine.toString(),
+ defaultColor, highlighter));
+ lines.get(lineNumber).setCursor(cursor);
+ lines.remove(lineNumber + 1);
+ }
}
/**
*/
public void backspace() {
dirty = true;
- lines.get(lineNumber).backspace();
+ int cursor = lines.get(lineNumber).getCursor();
+ if (cursor > 0) {
+ lines.get(lineNumber).backspace();
+ } else if (lineNumber > 0) {
+ // Join two lines
+ lineNumber--;
+ String firstLine = lines.get(lineNumber).getRawString();
+ if (firstLine.length() > 0) {
+ // Backspacing combining two lines
+ StringBuilder newLine = new StringBuilder(firstLine);
+ newLine.append(lines.get(lineNumber + 1).getRawString());
+ lines.set(lineNumber, new Line(newLine.toString(),
+ defaultColor, highlighter));
+ lines.get(lineNumber).setCursor(firstLine.length());
+ lines.remove(lineNumber + 1);
+ } else {
+ // Backspacing an empty line
+ lines.remove(lineNumber);
+ lines.get(lineNumber).setCursor(0);
+ }
+ }
+ }
+
+ /**
+ * Split the current line into two, like pressing the enter key.
+ */
+ public void enter() {
+ dirty = true;
+ int cursor = lines.get(lineNumber).getCursor();
+ String original = lines.get(lineNumber).getRawString();
+ String firstLine = original.substring(0, cursor);
+ String secondLine = original.substring(cursor);
+ lines.add(lineNumber + 1, new Line(secondLine, defaultColor,
+ highlighter));
+ lines.set(lineNumber, new Line(firstLine, defaultColor, highlighter));
+ lineNumber++;
+ lines.get(lineNumber).home();
}
/**