From 872ed42e5988bcd7cafdcda024ab2f7c8dc6bad9 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Mon, 22 Jun 2015 18:13:26 +0200 Subject: [PATCH] New console: replaces previous EditorConsoleStream with one that's faster and doesn't discard end chars. See #2798 --- .../arduino/LimitLinesDocumentListener.java | 136 ++++++++++ app/src/cc/arduino/MessageConsole.java | 204 +++++++++++++++ app/src/processing/app/Base.java | 3 - app/src/processing/app/Editor.java | 2 +- app/src/processing/app/EditorConsole.java | 232 ++++-------------- .../processing/app/EditorConsoleStream.java | 65 ----- app/src/processing/app/EditorStatus.java | 2 +- ...ngEscapeOnCloseConfirmationDialogTest.java | 2 +- .../ReduceIndentWith1CharOnLastLineTest.java | 2 +- 9 files changed, 387 insertions(+), 261 deletions(-) create mode 100644 app/src/cc/arduino/LimitLinesDocumentListener.java create mode 100644 app/src/cc/arduino/MessageConsole.java delete mode 100644 app/src/processing/app/EditorConsoleStream.java diff --git a/app/src/cc/arduino/LimitLinesDocumentListener.java b/app/src/cc/arduino/LimitLinesDocumentListener.java new file mode 100644 index 00000000000..9ccd99d2674 --- /dev/null +++ b/app/src/cc/arduino/LimitLinesDocumentListener.java @@ -0,0 +1,136 @@ +/** + * This file courtesy of Rob Camick + *

+ * https://tips4java.wordpress.com/2008/10/15/limit-lines-in-document/ + *

+ * About page at https://tips4java.wordpress.com/about/ says something + * like MIT + */ + +package cc.arduino; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; + +/* + * A class to control the maximum number of lines to be stored in a Document + * + * Excess lines can be removed from the start or end of the Document + * depending on your requirement. + * + * a) if you append text to the Document, then you would want to remove lines + * from the start. + * b) if you insert text at the beginning of the Document, then you would + * want to remove lines from the end. + */ +public class LimitLinesDocumentListener implements DocumentListener { + private int maximumLines; + private final boolean isRemoveFromStart; + + /* + * Specify the number of lines to be stored in the Document. + * Extra lines will be removed from the start of the Document. + */ + public LimitLinesDocumentListener(int maximumLines) { + this(maximumLines, true); + } + + /* + * Specify the number of lines to be stored in the Document. + * Extra lines will be removed from the start or end of the Document, + * depending on the boolean value specified. + */ + public LimitLinesDocumentListener(int maximumLines, boolean isRemoveFromStart) { + setLimitLines(maximumLines); + this.isRemoveFromStart = isRemoveFromStart; + } + + /* + * Return the maximum number of lines to be stored in the Document + */ + public int getLimitLines() { + return maximumLines; + } + + /* + * Set the maximum number of lines to be stored in the Document + */ + public void setLimitLines(int maximumLines) { + if (maximumLines < 1) { + String message = "Maximum lines must be greater than 0"; + throw new IllegalArgumentException(message); + } + + this.maximumLines = maximumLines; + } + + // Handle insertion of new text into the Document + + public void insertUpdate(final DocumentEvent e) { + // Changes to the Document can not be done within the listener + // so we need to add the processing to the end of the EDT + + SwingUtilities.invokeLater(() -> removeLines(e)); + } + + public void removeUpdate(DocumentEvent e) { + } + + public void changedUpdate(DocumentEvent e) { + } + + /* + * Remove lines from the Document when necessary + */ + private void removeLines(DocumentEvent e) { + // The root Element of the Document will tell us the total number + // of line in the Document. + + Document document = e.getDocument(); + Element root = document.getDefaultRootElement(); + + while (root.getElementCount() > maximumLines) { + if (isRemoveFromStart) { + removeFromStart(document, root); + } else { + removeFromEnd(document, root); + } + } + } + + /* + * Remove lines from the start of the Document + */ + private void removeFromStart(Document document, Element root) { + Element line = root.getElement(0); + int end = line.getEndOffset(); + + try { + document.remove(0, end); + } catch (BadLocationException ble) { + System.out.println(ble); + } + } + + /* + * Remove lines from the end of the Document + */ + private void removeFromEnd(Document document, Element root) { + // We use start minus 1 to make sure we remove the newline + // character of the previous line + + Element line = root.getElement(root.getElementCount() - 1); + int start = line.getStartOffset(); + int end = line.getEndOffset(); + + try { + document.remove(start - 1, end - start); + } catch (BadLocationException ble) { + System.out.println(ble); + } + } +} diff --git a/app/src/cc/arduino/MessageConsole.java b/app/src/cc/arduino/MessageConsole.java new file mode 100644 index 00000000000..9981bb67574 --- /dev/null +++ b/app/src/cc/arduino/MessageConsole.java @@ -0,0 +1,204 @@ +/** + * This file courtesy of Rob Camick + *

+ * https://tips4java.wordpress.com/2008/11/08/message-console/ + *

+ * About page at https://tips4java.wordpress.com/about/ says something + * like MIT + */ + +package cc.arduino; + +import javax.swing.*; +import javax.swing.event.DocumentListener; +import javax.swing.text.*; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +/* + * Create a simple console to display text messages. + * + * Messages can be directed here from different sources. Each source can + * have its messages displayed in a different color. + * + * You can limit the number of lines to hold in the Document. + */ +public class MessageConsole { + + private final JTextComponent textComponent; + private final JScrollPane scrollPane; + private final Document document; + private DocumentListener limitLinesListener; + + /* + * Use the text component specified as a simply console to display + * text messages. + */ + public MessageConsole(JTextComponent textComponent, JScrollPane scrollPane) { + this.textComponent = textComponent; + this.scrollPane = scrollPane; + this.document = textComponent.getDocument(); + this.textComponent.setEditable(false); + DefaultCaret caret = (DefaultCaret) this.textComponent.getCaret(); + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + } + + /* + * Redirect the output from the standard output to the console + * using the default text color and null PrintStream + */ + public void redirectOut() { + redirectOut(null, null); + } + + /* + * Redirect the output from the standard output to the console + * using the specified color and PrintStream. When a PrintStream + * is specified the message will be added to the Document before + * it is also written to the PrintStream. + */ + public void redirectOut(SimpleAttributeSet style, PrintStream printStream) { + ConsoleOutputStream cos = new ConsoleOutputStream(style, printStream); + System.setOut(new PrintStream(cos, true)); + } + + /* + * Redirect the output from the standard error to the console + * using the default text color and null PrintStream + */ + public void redirectErr() { + redirectErr(null, null); + } + + /* + * Redirect the output from the standard error to the console + * using the specified color and PrintStream. When a PrintStream + * is specified the message will be added to the Document before + * it is also written to the PrintStream. + */ + public void redirectErr(SimpleAttributeSet style, PrintStream printStream) { + ConsoleOutputStream cos = new ConsoleOutputStream(style, printStream); + System.setErr(new PrintStream(cos, true)); + } + + /* + * To prevent memory from being used up you can control the number of + * lines to display in the console + * + * This number can be dynamically changed, but the console will only + * be updated the next time the Document is updated. + */ + public void setMessageLines(int lines) { + if (limitLinesListener != null) { + document.removeDocumentListener(limitLinesListener); + } + + limitLinesListener = new LimitLinesDocumentListener(lines, true); + document.addDocumentListener(limitLinesListener); + } + + /* + * Class to intercept output from a PrintStream and add it to a Document. + * The output can optionally be redirected to a different PrintStream. + * The text displayed in the Document can be color coded to indicate + * the output source. + */ + class ConsoleOutputStream extends ByteArrayOutputStream { + + private SimpleAttributeSet attributes; + private final PrintStream printStream; + private final StringBuffer buffer = new StringBuffer(1000); + private boolean isFirstLine; + + /* + * Specify the option text color and PrintStream + */ + public ConsoleOutputStream(SimpleAttributeSet attributes, PrintStream printStream) { + this.attributes = attributes; + this.printStream = printStream; + this.isFirstLine = true; + } + + /* + * Override this method to intercept the output text. Each line of text + * output will actually involve invoking this method twice: + * + * a) for the actual text message + * b) for the newLine string + * + * The message will be treated differently depending on whether the line + * will be appended or inserted into the Document + */ + public void flush() { + String message = toString(); + + if (message.length() == 0) { + return; + } + + handleAppend(message); + + reset(); + } + + /* + * We don't want to have blank lines in the Document. The first line + * added will simply be the message. For additional lines it will be: + * + * newLine + message + */ + private void handleAppend(String message) { + // This check is needed in case the text in the Document has been + // cleared. The buffer may contain the EOL string from the previous + // message. + + if (document.getLength() == 0) { + buffer.setLength(0); + } + + buffer.append(message); + clearBuffer(); + } + + /* + * The message and the newLine have been added to the buffer in the + * appropriate order so we can now update the Document and send the + * text to the optional PrintStream. + */ + private void clearBuffer() { + // In case both the standard out and standard err are being redirected + // we need to insert a newline character for the first line only + + synchronized (document) { + if (isFirstLine && document.getLength() != 0) { + buffer.insert(0, "\n"); + } + + isFirstLine = false; + String line = buffer.toString(); + + int offset = document.getLength(); + SwingUtilities.invokeLater(() -> { + try { + document.insertString(offset, line, attributes); + } catch (BadLocationException ble) { + //ignore + } + }); + + Timer timer = new Timer(200, (e) -> { + scrollPane.getHorizontalScrollBar().setValue(0); + scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum()); + }); + timer.setRepeats(false); + timer.start(); + + if (printStream != null) { + printStream.print(line); + } + + buffer.setLength(0); + } + } + } +} diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index ba95406e3a7..557c43fd6d8 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -639,9 +639,6 @@ protected void handleActivated(Editor whichEditor) { // noop } } - - // set the current window to be the console that's getting output - EditorConsoleStream.setCurrent(activeEditor.console); } diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 1eb3b6a8f95..879d47b41b9 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -263,7 +263,7 @@ public void windowDeactivated(WindowEvent e) { status = new EditorStatus(this); consolePanel.add(status, BorderLayout.NORTH); - console = new EditorConsole(this); + console = new EditorConsole(); console.setName("console"); // windows puts an ugly border on this guy console.setBorder(null); diff --git a/app/src/processing/app/EditorConsole.java b/app/src/processing/app/EditorConsole.java index a2116f8b436..7e7e1cf4ca5 100644 --- a/app/src/processing/app/EditorConsole.java +++ b/app/src/processing/app/EditorConsole.java @@ -21,236 +21,90 @@ package processing.app; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; +import cc.arduino.MessageConsole; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.text.AttributeSet; +import javax.swing.*; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; -import javax.swing.text.Element; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; - -import processing.app.helpers.OSUtils; +import java.awt.*; /** * Message console that sits below the editing area. - *

+ *

* Debugging this class is tricky... If it's throwing exceptions, * don't take over System.err, and debug while watching just System.out * or just write println() or whatever directly to systemOut or systemErr. */ @SuppressWarnings("serial") public class EditorConsole extends JScrollPane { - Editor editor; - - JTextPane consoleTextPane; - BufferedStyledDocument consoleDoc; - - SimpleAttributeSet stdStyle; - SimpleAttributeSet errStyle; + private final DefaultStyledDocument document; + private final JTextPane consoleTextPane; // Single static instance shared because there's only one real System.out. // Within the input handlers, the currentConsole variable will be used to // echo things to the correct location. - - public EditorConsole(Editor _editor) { - editor = _editor; - int maxLineCount = PreferencesData.getInteger("console.length"); + public EditorConsole() { + document = new DefaultStyledDocument(); - consoleDoc = new BufferedStyledDocument(4000, maxLineCount); - consoleTextPane = new JTextPane(consoleDoc); - consoleTextPane.setEditable(false); + consoleTextPane = new JTextPane(document); + Color backgroundColour = Theme.getColor("console.color"); + consoleTextPane.setBackground(backgroundColour); - // necessary? - SimpleAttributeSet leftAlignAttr = new SimpleAttributeSet(); - StyleConstants.setAlignment(leftAlignAttr, StyleConstants.ALIGN_LEFT); - consoleDoc.setParagraphAttributes(0, 0, leftAlignAttr, true); - - // build styles for different types of console output - Color bgColor = Theme.getColor("console.color"); - Color fgColorOut = Theme.getColor("console.output.color"); - Color fgColorErr = Theme.getColor("console.error.color"); Font consoleFont = Theme.getFont("console.font"); Font editorFont = PreferencesData.getFont("editor.font"); - Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize()); - - stdStyle = new SimpleAttributeSet(); - StyleConstants.setForeground(stdStyle, fgColorOut); - StyleConstants.setBackground(stdStyle, bgColor); - StyleConstants.setFontSize(stdStyle, font.getSize()); - StyleConstants.setFontFamily(stdStyle, font.getFamily()); - StyleConstants.setBold(stdStyle, font.isBold()); - StyleConstants.setItalic(stdStyle, font.isItalic()); - - errStyle = new SimpleAttributeSet(); - StyleConstants.setForeground(errStyle, fgColorErr); - StyleConstants.setBackground(errStyle, bgColor); - StyleConstants.setFontSize(errStyle, font.getSize()); - StyleConstants.setFontFamily(errStyle, font.getFamily()); - StyleConstants.setBold(errStyle, font.isBold()); - StyleConstants.setItalic(errStyle, font.isItalic()); - - consoleTextPane.setBackground(bgColor); - - // add the jtextpane to this scrollpane - setViewportView(consoleTextPane); + Font actualFont = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize()); + + SimpleAttributeSet stdOutStyle = new SimpleAttributeSet(); + StyleConstants.setForeground(stdOutStyle, Theme.getColor("console.output.color")); + StyleConstants.setBackground(stdOutStyle, backgroundColour); + StyleConstants.setFontSize(stdOutStyle, actualFont.getSize()); + StyleConstants.setFontFamily(stdOutStyle, actualFont.getFamily()); + StyleConstants.setBold(stdOutStyle, actualFont.isBold()); + StyleConstants.setItalic(stdOutStyle, actualFont.isItalic()); + + SimpleAttributeSet stdErrStyle = new SimpleAttributeSet(); + StyleConstants.setForeground(stdErrStyle, Theme.getColor("console.error.color")); + StyleConstants.setBackground(stdErrStyle, backgroundColour); + StyleConstants.setFontSize(stdErrStyle, actualFont.getSize()); + StyleConstants.setFontFamily(stdErrStyle, actualFont.getFamily()); + StyleConstants.setBold(stdErrStyle, actualFont.isBold()); + StyleConstants.setItalic(stdErrStyle, actualFont.isItalic()); + + MessageConsole messageConsole = new MessageConsole(consoleTextPane, this); + messageConsole.redirectErr(stdErrStyle, System.err); + messageConsole.redirectOut(stdOutStyle, System.out); + messageConsole.setMessageLines(PreferencesData.getInteger("console.length") * 2); + + JPanel noWrapPanel = new JPanel(new BorderLayout()); + noWrapPanel.add(consoleTextPane); + + setViewportView(noWrapPanel); + getVerticalScrollBar().setUnitIncrement(7); // calculate height of a line of text in pixels // and size window accordingly - FontMetrics metrics = getFontMetrics(font); + FontMetrics metrics = getFontMetrics(actualFont); int height = metrics.getAscent() + metrics.getDescent(); int lines = PreferencesData.getInteger("console.lines"); int sizeFudge = 6; //10; // unclear why this is necessary, but it is setPreferredSize(new Dimension(1024, (height * lines) + sizeFudge)); setMinimumSize(new Dimension(1024, (height * 4) + sizeFudge)); - - EditorConsoleStream.init(); - - // to fix ugliness.. normally macosx java 1.3 puts an - // ugly white border around this object, so turn it off. - if (OSUtils.isMacOS()) { - setBorder(null); - } - - // periodically post buffered messages to the console - // should the interval come from the preferences file? - new Timer(250, new ActionListener() { - public void actionPerformed(ActionEvent evt) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // only if new text has been added - if (consoleDoc.isChanged()) { - // insert the text that's been added in the meantime - consoleDoc.insertAll(); - // always move to the end of the text as it's added - consoleTextPane.setCaretPosition(consoleDoc.getLength()); - } - } - }); - } - }).start(); - } - - - /** - * Append a piece of text to the console. - *

- * Swing components are NOT thread-safe, and since the MessageSiphon - * instantiates new threads, and in those callbacks, they often print - * output to stdout and stderr, which are wrapped by EditorConsoleStream - * and eventually leads to EditorConsole.appendText(), which directly - * updates the Swing text components, causing deadlock. - *

- * Updates are buffered to the console and displayed at regular - * intervals on Swing's event-dispatching thread. (patch by David Mellis) - */ - synchronized void appendText(String txt, boolean e) { - consoleDoc.appendString(txt, e ? errStyle : stdStyle); } - public void clear() { try { - consoleDoc.remove(0, consoleDoc.getLength()); - } catch (BadLocationException e) { - // ignore the error otherwise this will cause an infinite loop - // maybe not a good idea in the long run? - } - } -} - - -// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - -/** - * Buffer updates to the console and output them in batches. For info, see: - * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer and - * http://javatechniques.com/public/java/docs/gui/jtextpane-speed-part2.html - * appendString() is called from multiple threads, and insertAll from the - * swing event thread, so they need to be synchronized - */ -@SuppressWarnings("serial") -class BufferedStyledDocument extends DefaultStyledDocument { - private List elements = new ArrayList(); - private int maxLineLength, maxLineCount; - private int currentLineLength = 0; - private boolean changed = false; - - public BufferedStyledDocument(int _maxLineLength, int _maxLineCount) { - maxLineLength = _maxLineLength; - maxLineCount = _maxLineCount; - } - - /** buffer a string for insertion at the end of the DefaultStyledDocument */ - public synchronized void appendString(String text, AttributeSet a) { - changed = true; - char[] chars = text.toCharArray(); - int start = 0; - int stop = 0; - while (stop < chars.length) { - char c = chars[stop]; - stop++; - currentLineLength++; - if (c == '\n' || c == '\r' || currentLineLength > maxLineLength) { - elements.add(new ElementSpec(a, ElementSpec.ContentType, chars, start, - stop - start)); - elements.add(new ElementSpec(a, ElementSpec.EndTagType)); - elements.add(new ElementSpec(a, ElementSpec.StartTagType)); - currentLineLength = 0; - start = stop; - } - } - elements.add(new ElementSpec(a, ElementSpec.ContentType, chars, start, - stop - start)); - } - - /** insert the buffered strings */ - public synchronized void insertAll() { - try { - // Insert new elements at the bottom - ElementSpec[] elementArray = elements.toArray(new ElementSpec[0]); - insert(getLength(), elementArray); - - // check how many lines have been used - // if too many, shave off a few lines from the beginning - Element root = getDefaultRootElement(); - int lineCount = root.getElementCount(); - int overage = lineCount - maxLineCount; - if (overage > 0) { - // if 1200 lines, and 1000 lines is max, - // find the position of the end of the 200th line - Element lineElement = root.getElement(overage); - if (lineElement == null) - return; // do nuthin - - // remove to the end of the 200th line - int endOffset = lineElement.getEndOffset(); - remove(0, endOffset); - } + document.remove(0, document.getLength()); } catch (BadLocationException e) { // ignore the error otherwise this will cause an infinite loop // maybe not a good idea in the long run? } - elements.clear(); - changed = false; } - public boolean isChanged() { - return changed; + public String getText() { + return consoleTextPane.getText().trim(); } } diff --git a/app/src/processing/app/EditorConsoleStream.java b/app/src/processing/app/EditorConsoleStream.java deleted file mode 100644 index 57d06cc910d..00000000000 --- a/app/src/processing/app/EditorConsoleStream.java +++ /dev/null @@ -1,65 +0,0 @@ -package processing.app; - -import java.io.OutputStream; -import java.io.PrintStream; - -class EditorConsoleStream extends OutputStream { - - private static EditorConsole currentConsole; - private static PrintStream systemErr; - private static PrintStream systemOut; - - public static void init() { - if (systemOut == null) { - systemOut = System.out; - systemErr = System.err; - - if (PreferencesData.getBoolean("console")) { - PrintStream consoleOut = new PrintStream(new EditorConsoleStream(false)); - PrintStream consoleErr = new PrintStream(new EditorConsoleStream(true)); - - System.setOut(consoleOut); - System.setErr(consoleErr); - } - } - } - - private final boolean isStdErr; // whether stderr or stdout - private final PrintStream system; - - private EditorConsoleStream(boolean isStdErr) { - this.isStdErr = isStdErr; - if (this.isStdErr) { - system = systemErr; - } else { - system = systemOut; - } - } - - public void close() { - } - - public void flush() { - } - - public void write(int b) { - write(new byte[]{(byte) b}); - } - - public void write(byte b[]) { // appears never to be used - write(b, 0, b.length); - } - - public void write(byte b[], int offset, int length) { - if (currentConsole != null) { - currentConsole.appendText(new String(b, offset, length), isStdErr); - } - - system.write(b, offset, length); - } - - public static void setCurrent(EditorConsole console) { - currentConsole = console; - } - -} diff --git a/app/src/processing/app/EditorStatus.java b/app/src/processing/app/EditorStatus.java index ce84c8c820c..6114575435d 100644 --- a/app/src/processing/app/EditorStatus.java +++ b/app/src/processing/app/EditorStatus.java @@ -466,7 +466,7 @@ public void actionPerformed(ActionEvent e) { String message = ""; message += _("Arduino: ") + BaseNoGui.VERSION_NAME_LONG + " (" + System.getProperty("os.name") + "), "; message += _("Board: ") + "\"" + BaseNoGui.getBoardPreferences().get("name") + "\"\n\n"; - message += editor.console.consoleTextPane.getText().trim(); + message += editor.console.getText(); if ((PreferencesData.getBoolean("build.verbose")) == false) { message += "\n\n"; message += " " + _("This report would have more information with") + "\n"; diff --git a/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java b/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java index b5655965950..83897b1963c 100644 --- a/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java +++ b/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java @@ -54,6 +54,6 @@ public void shouldJustCloseTheDialog() throws Exception { EditorConsole console = (EditorConsole) window.scrollPane("console").component(); - assertEquals("", console.consoleDoc.getText(0, console.consoleDoc.getLength())); + assertEquals("", console.getText()); } } diff --git a/app/test/processing/app/ReduceIndentWith1CharOnLastLineTest.java b/app/test/processing/app/ReduceIndentWith1CharOnLastLineTest.java index f5cd01f89bb..81c46754311 100644 --- a/app/test/processing/app/ReduceIndentWith1CharOnLastLineTest.java +++ b/app/test/processing/app/ReduceIndentWith1CharOnLastLineTest.java @@ -52,6 +52,6 @@ public void shouldJustCloseTheDialog() throws Exception { EditorConsole console = (EditorConsole) window.scrollPane("console").component(); - assertEquals("", console.consoleDoc.getText(0, console.consoleDoc.getLength())); + assertEquals("", console.getText()); } }