Skip to content

New console #3400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions app/src/cc/arduino/LimitLinesDocumentListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* This file courtesy of Rob Camick
* <p>
* https://tips4java.wordpress.com/2008/10/15/limit-lines-in-document/
* <p>
* 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);
}
}
}
204 changes: 204 additions & 0 deletions app/src/cc/arduino/MessageConsole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/**
* 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 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);
}
}
}
}
3 changes: 0 additions & 3 deletions app/src/processing/app/Base.java
Original file line number Diff line number Diff line change
@@ -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);
}


2 changes: 1 addition & 1 deletion app/src/processing/app/Editor.java
Original file line number Diff line number Diff line change
@@ -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);
Loading