mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-18 07:52:14 +01:00
New console: replaces previous EditorConsoleStream with one that's faster and doesn't discard end chars.
See #2798
This commit is contained in:
parent
16c852ada5
commit
e15ba64ee2
131
app/src/cc/arduino/ConsoleOutputStream.java
Normal file
131
app/src/cc/arduino/ConsoleOutputStream.java
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Original version of this file courtesy of Rob Camick
|
||||||
|
* <p>
|
||||||
|
* https://tips4java.wordpress.com/2008/11/08/message-console/
|
||||||
|
* <p>
|
||||||
|
* About page at https://tips4java.wordpress.com/about/ says something
|
||||||
|
* like MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino;
|
||||||
|
|
||||||
|
import processing.app.EditorConsole;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.SimpleAttributeSet;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public class ConsoleOutputStream extends ByteArrayOutputStream {
|
||||||
|
|
||||||
|
private final SimpleAttributeSet attributes;
|
||||||
|
private final PrintStream printStream;
|
||||||
|
private final StringBuilder buffer;
|
||||||
|
private final Timer timer;
|
||||||
|
private JScrollPane scrollPane;
|
||||||
|
private Document document;
|
||||||
|
|
||||||
|
public ConsoleOutputStream(SimpleAttributeSet attributes, PrintStream printStream) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
this.printStream = printStream;
|
||||||
|
this.buffer = new StringBuilder();
|
||||||
|
|
||||||
|
this.timer = new Timer(100, (e) -> {
|
||||||
|
if (scrollPane != null) {
|
||||||
|
synchronized (scrollPane) {
|
||||||
|
scrollPane.getHorizontalScrollBar().setValue(0);
|
||||||
|
scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
timer.setRepeats(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setCurrentEditorConsole(EditorConsole console) {
|
||||||
|
this.scrollPane = console;
|
||||||
|
this.document = console.getDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void flush() {
|
||||||
|
String message = toString();
|
||||||
|
|
||||||
|
if (message.length() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAppend(message);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAppend(String message) {
|
||||||
|
resetBufferIfDocumentEmpty();
|
||||||
|
|
||||||
|
buffer.append(message);
|
||||||
|
|
||||||
|
clearBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetBufferIfDocumentEmpty() {
|
||||||
|
if (document != null && document.getLength() == 0) {
|
||||||
|
buffer.setLength(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearBuffer() {
|
||||||
|
String line = buffer.toString();
|
||||||
|
buffer.setLength(0);
|
||||||
|
|
||||||
|
printStream.print(line);
|
||||||
|
|
||||||
|
if (document != null) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
int offset = document.getLength();
|
||||||
|
document.insertString(offset, line, attributes);
|
||||||
|
} catch (BadLocationException ble) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!timer.isRunning()) {
|
||||||
|
timer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -641,7 +641,7 @@ public class Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the current window to be the console that's getting output
|
// set the current window to be the console that's getting output
|
||||||
EditorConsoleStream.setCurrent(activeEditor.console);
|
EditorConsole.setCurrentEditorConsole(activeEditor.console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
status = new EditorStatus(this);
|
status = new EditorStatus(this);
|
||||||
consolePanel.add(status, BorderLayout.NORTH);
|
consolePanel.add(status, BorderLayout.NORTH);
|
||||||
|
|
||||||
console = new EditorConsole(this);
|
console = new EditorConsole();
|
||||||
console.setName("console");
|
console.setName("console");
|
||||||
// windows puts an ugly border on this guy
|
// windows puts an ugly border on this guy
|
||||||
console.setBorder(null);
|
console.setBorder(null);
|
||||||
|
@ -21,236 +21,106 @@
|
|||||||
|
|
||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
import java.awt.Color;
|
import cc.arduino.ConsoleOutputStream;
|
||||||
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 javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JTextPane;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.Timer;
|
|
||||||
import javax.swing.text.AttributeSet;
|
|
||||||
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 javax.swing.*;
|
||||||
|
import javax.swing.text.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message console that sits below the editing area.
|
* Message console that sits below the editing area.
|
||||||
* <P>
|
|
||||||
* 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 {
|
public class EditorConsole extends JScrollPane {
|
||||||
Editor editor;
|
|
||||||
|
|
||||||
JTextPane consoleTextPane;
|
private static ConsoleOutputStream out;
|
||||||
BufferedStyledDocument consoleDoc;
|
private static ConsoleOutputStream err;
|
||||||
|
|
||||||
SimpleAttributeSet stdStyle;
|
public static synchronized void init(SimpleAttributeSet outStyle, PrintStream outStream, SimpleAttributeSet errStyle, PrintStream errStream) {
|
||||||
SimpleAttributeSet errStyle;
|
if (out != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Single static instance shared because there's only one real System.out.
|
out = new ConsoleOutputStream(outStyle, outStream);
|
||||||
// Within the input handlers, the currentConsole variable will be used to
|
System.setOut(new PrintStream(out, true));
|
||||||
// echo things to the correct location.
|
|
||||||
|
|
||||||
public EditorConsole(Editor _editor) {
|
err = new ConsoleOutputStream(errStyle, errStream);
|
||||||
editor = _editor;
|
System.setErr(new PrintStream(err, true));
|
||||||
|
}
|
||||||
|
|
||||||
int maxLineCount = PreferencesData.getInteger("console.length");
|
public static void setCurrentEditorConsole(EditorConsole console) {
|
||||||
|
out.setCurrentEditorConsole(console);
|
||||||
|
err.setCurrentEditorConsole(console);
|
||||||
|
}
|
||||||
|
|
||||||
consoleDoc = new BufferedStyledDocument(4000, maxLineCount);
|
private final DefaultStyledDocument document;
|
||||||
consoleTextPane = new JTextPane(consoleDoc);
|
private final JTextPane consoleTextPane;
|
||||||
|
|
||||||
|
public EditorConsole() {
|
||||||
|
document = new DefaultStyledDocument();
|
||||||
|
|
||||||
|
consoleTextPane = new JTextPane(document);
|
||||||
consoleTextPane.setEditable(false);
|
consoleTextPane.setEditable(false);
|
||||||
|
DefaultCaret caret = (DefaultCaret) consoleTextPane.getCaret();
|
||||||
|
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
|
||||||
|
|
||||||
// necessary?
|
Color backgroundColour = Theme.getColor("console.color");
|
||||||
SimpleAttributeSet leftAlignAttr = new SimpleAttributeSet();
|
consoleTextPane.setBackground(backgroundColour);
|
||||||
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 consoleFont = Theme.getFont("console.font");
|
||||||
Font editorFont = PreferencesData.getFont("editor.font");
|
Font editorFont = PreferencesData.getFont("editor.font");
|
||||||
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
|
Font actualFont = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
|
||||||
|
|
||||||
stdStyle = new SimpleAttributeSet();
|
SimpleAttributeSet stdOutStyle = new SimpleAttributeSet();
|
||||||
StyleConstants.setForeground(stdStyle, fgColorOut);
|
StyleConstants.setForeground(stdOutStyle, Theme.getColor("console.output.color"));
|
||||||
StyleConstants.setBackground(stdStyle, bgColor);
|
StyleConstants.setBackground(stdOutStyle, backgroundColour);
|
||||||
StyleConstants.setFontSize(stdStyle, font.getSize());
|
StyleConstants.setFontSize(stdOutStyle, actualFont.getSize());
|
||||||
StyleConstants.setFontFamily(stdStyle, font.getFamily());
|
StyleConstants.setFontFamily(stdOutStyle, actualFont.getFamily());
|
||||||
StyleConstants.setBold(stdStyle, font.isBold());
|
StyleConstants.setBold(stdOutStyle, actualFont.isBold());
|
||||||
StyleConstants.setItalic(stdStyle, font.isItalic());
|
StyleConstants.setItalic(stdOutStyle, actualFont.isItalic());
|
||||||
|
|
||||||
errStyle = new SimpleAttributeSet();
|
consoleTextPane.setParagraphAttributes(stdOutStyle, true);
|
||||||
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);
|
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());
|
||||||
|
|
||||||
// add the jtextpane to this scrollpane
|
JPanel noWrapPanel = new JPanel(new BorderLayout());
|
||||||
setViewportView(consoleTextPane);
|
noWrapPanel.add(consoleTextPane);
|
||||||
|
|
||||||
|
setViewportView(noWrapPanel);
|
||||||
|
getVerticalScrollBar().setUnitIncrement(7);
|
||||||
|
|
||||||
// calculate height of a line of text in pixels
|
// calculate height of a line of text in pixels
|
||||||
// and size window accordingly
|
// and size window accordingly
|
||||||
FontMetrics metrics = getFontMetrics(font);
|
FontMetrics metrics = getFontMetrics(actualFont);
|
||||||
int height = metrics.getAscent() + metrics.getDescent();
|
int height = metrics.getAscent() + metrics.getDescent();
|
||||||
int lines = PreferencesData.getInteger("console.lines");
|
int lines = PreferencesData.getInteger("console.lines");
|
||||||
int sizeFudge = 6; //10; // unclear why this is necessary, but it is
|
int sizeFudge = 6; //10; // unclear why this is necessary, but it is
|
||||||
setPreferredSize(new Dimension(1024, (height * lines) + sizeFudge));
|
setPreferredSize(new Dimension(1024, (height * lines) + sizeFudge));
|
||||||
setMinimumSize(new Dimension(1024, (height * 4) + sizeFudge));
|
setMinimumSize(new Dimension(1024, (height * 5) + sizeFudge));
|
||||||
|
|
||||||
EditorConsoleStream.init();
|
EditorConsole.init(stdOutStyle, System.out, stdErrStyle, System.err);
|
||||||
|
|
||||||
// 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.
|
|
||||||
* <P>
|
|
||||||
* 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.
|
|
||||||
* <P>
|
|
||||||
* 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() {
|
public void clear() {
|
||||||
try {
|
try {
|
||||||
consoleDoc.remove(0, consoleDoc.getLength());
|
document.remove(0, document.getLength());
|
||||||
} catch (BadLocationException e) {
|
} catch (BadLocationException e) {
|
||||||
// ignore the error otherwise this will cause an infinite loop
|
// ignore the error otherwise this will cause an infinite loop
|
||||||
// maybe not a good idea in the long run?
|
// maybe not a good idea in the long run?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
return consoleTextPane.getText().trim();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<ElementSpec> elements = new ArrayList<ElementSpec>();
|
|
||||||
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 Document getDocument() {
|
||||||
public synchronized void appendString(String text, AttributeSet a) {
|
return document;
|
||||||
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);
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -466,7 +466,7 @@ public class EditorStatus extends JPanel /*implements ActionListener*/ {
|
|||||||
String message = "";
|
String message = "";
|
||||||
message += _("Arduino: ") + BaseNoGui.VERSION_NAME_LONG + " (" + System.getProperty("os.name") + "), ";
|
message += _("Arduino: ") + BaseNoGui.VERSION_NAME_LONG + " (" + System.getProperty("os.name") + "), ";
|
||||||
message += _("Board: ") + "\"" + BaseNoGui.getBoardPreferences().get("name") + "\"\n\n";
|
message += _("Board: ") + "\"" + BaseNoGui.getBoardPreferences().get("name") + "\"\n\n";
|
||||||
message += editor.console.consoleTextPane.getText().trim();
|
message += editor.console.getText();
|
||||||
if ((PreferencesData.getBoolean("build.verbose")) == false) {
|
if ((PreferencesData.getBoolean("build.verbose")) == false) {
|
||||||
message += "\n\n";
|
message += "\n\n";
|
||||||
message += " " + _("This report would have more information with") + "\n";
|
message += " " + _("This report would have more information with") + "\n";
|
||||||
|
@ -54,6 +54,6 @@ public class HittingEscapeOnCloseConfirmationDialogTest extends AbstractGUITest
|
|||||||
|
|
||||||
EditorConsole console = (EditorConsole) window.scrollPane("console").component();
|
EditorConsole console = (EditorConsole) window.scrollPane("console").component();
|
||||||
|
|
||||||
assertEquals("", console.consoleDoc.getText(0, console.consoleDoc.getLength()));
|
assertEquals("", console.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,6 @@ public class ReduceIndentWith1CharOnLastLineTest extends AbstractGUITest {
|
|||||||
|
|
||||||
EditorConsole console = (EditorConsole) window.scrollPane("console").component();
|
EditorConsole console = (EditorConsole) window.scrollPane("console").component();
|
||||||
|
|
||||||
assertEquals("", console.consoleDoc.getText(0, console.consoleDoc.getLength()));
|
assertEquals("", console.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user