mirror of
https://github.com/arduino/Arduino.git
synced 2025-03-13 10:29:35 +01:00
Refactored and simplified EditorConsole class.
This commit is contained in:
parent
479b974fe1
commit
93562a7800
@ -1,5 +1,3 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
@ -22,15 +20,32 @@
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
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.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.*;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
@ -40,16 +55,15 @@ import java.util.*;
|
||||
* 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;
|
||||
|
||||
MutableAttributeSet stdStyle;
|
||||
MutableAttributeSet errStyle;
|
||||
|
||||
int maxLineCount;
|
||||
SimpleAttributeSet stdStyle;
|
||||
SimpleAttributeSet errStyle;
|
||||
|
||||
static File errFile;
|
||||
static File outFile;
|
||||
@ -70,20 +84,19 @@ public class EditorConsole extends JScrollPane {
|
||||
|
||||
static EditorConsole currentConsole;
|
||||
|
||||
public EditorConsole(Editor _editor) {
|
||||
editor = _editor;
|
||||
|
||||
public EditorConsole(Editor editor) {
|
||||
this.editor = editor;
|
||||
int maxLineCount = Preferences.getInteger("console.length");
|
||||
|
||||
maxLineCount = Preferences.getInteger("console.length");
|
||||
|
||||
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
|
||||
consoleDoc = new BufferedStyledDocument(4000, maxLineCount);
|
||||
consoleTextPane = new JTextPane(consoleDoc);
|
||||
consoleTextPane.setEditable(false);
|
||||
|
||||
// necessary?
|
||||
MutableAttributeSet standard = new SimpleAttributeSet();
|
||||
StyleConstants.setAlignment(standard, StyleConstants.ALIGN_LEFT);
|
||||
consoleDoc.setParagraphAttributes(0, 0, standard, true);
|
||||
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");
|
||||
@ -112,13 +125,13 @@ public class EditorConsole extends JScrollPane {
|
||||
consoleTextPane.setBackground(bgColor);
|
||||
|
||||
// add the jtextpane to this scrollpane
|
||||
this.setViewportView(consoleTextPane);
|
||||
setViewportView(consoleTextPane);
|
||||
|
||||
// calculate height of a line of text in pixels
|
||||
// and size window accordingly
|
||||
FontMetrics metrics = this.getFontMetrics(font);
|
||||
FontMetrics metrics = getFontMetrics(font);
|
||||
int height = metrics.getAscent() + metrics.getDescent();
|
||||
int lines = Preferences.getInteger("console.lines"); //, 4);
|
||||
int lines = Preferences.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));
|
||||
@ -127,10 +140,10 @@ public class EditorConsole extends JScrollPane {
|
||||
systemOut = System.out;
|
||||
systemErr = System.err;
|
||||
|
||||
// Create a temporary folder which will have a randomized name. Has to
|
||||
// be randomized otherwise another instance of Processing (or one of its
|
||||
// sister IDEs) might collide with the file causing permissions problems.
|
||||
// The files and folders are not deleted on exit because they may be
|
||||
// Create a temporary folder which will have a randomized name. Has to
|
||||
// be randomized otherwise another instance of Processing (or one of its
|
||||
// sister IDEs) might collide with the file causing permissions problems.
|
||||
// The files and folders are not deleted on exit because they may be
|
||||
// needed for debugging or bug reporting.
|
||||
tempFolder = Base.createTempFolder("console");
|
||||
tempFolder.deleteOnExit();
|
||||
@ -154,7 +167,7 @@ public class EditorConsole extends JScrollPane {
|
||||
}
|
||||
consoleOut = new PrintStream(new EditorConsoleStream(false));
|
||||
consoleErr = new PrintStream(new EditorConsoleStream(true));
|
||||
|
||||
|
||||
if (Preferences.getBoolean("console")) {
|
||||
try {
|
||||
System.setOut(consoleOut);
|
||||
@ -179,7 +192,7 @@ public class EditorConsole extends JScrollPane {
|
||||
@Override
|
||||
public void run() {
|
||||
// only if new text has been added
|
||||
if (consoleDoc.hasAppendage) {
|
||||
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
|
||||
@ -220,7 +233,7 @@ public class EditorConsole extends JScrollPane {
|
||||
stdoutFile.close();
|
||||
stderrFile.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(systemOut);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
outFile.delete();
|
||||
@ -240,23 +253,18 @@ public class EditorConsole extends JScrollPane {
|
||||
synchronized public void message(String what, boolean err, boolean advance) {
|
||||
if (err) {
|
||||
systemErr.print(what);
|
||||
//systemErr.print("CE" + what);
|
||||
if (advance)
|
||||
systemErr.println();
|
||||
} else {
|
||||
systemOut.print(what);
|
||||
//systemOut.print("CO" + what);
|
||||
}
|
||||
|
||||
if (advance) {
|
||||
appendText("\n", err);
|
||||
if (err) {
|
||||
systemErr.println();
|
||||
} else {
|
||||
if (advance)
|
||||
systemOut.println();
|
||||
}
|
||||
}
|
||||
|
||||
// to console display
|
||||
// to console display
|
||||
appendText(what, err);
|
||||
if (advance)
|
||||
appendText("\n", err);
|
||||
// moved down here since something is punting
|
||||
}
|
||||
|
||||
@ -292,83 +300,47 @@ public class EditorConsole extends JScrollPane {
|
||||
|
||||
|
||||
private static class EditorConsoleStream extends OutputStream {
|
||||
//static EditorConsole current;
|
||||
final boolean err; // whether stderr or stdout
|
||||
final byte single[] = new byte[1];
|
||||
|
||||
public EditorConsoleStream(boolean err) {
|
||||
this.err = err;
|
||||
PrintStream system;
|
||||
OutputStream file;
|
||||
|
||||
public EditorConsoleStream(boolean _err) {
|
||||
err = _err;
|
||||
if (err) {
|
||||
system = systemErr;
|
||||
file = stderrFile;
|
||||
} else {
|
||||
system = systemOut;
|
||||
file = stdoutFile;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() { }
|
||||
|
||||
public void flush() { }
|
||||
|
||||
public void write(byte b[]) { // appears never to be used
|
||||
if (currentConsole != null) {
|
||||
currentConsole.write(b, 0, b.length, err);
|
||||
} else {
|
||||
try {
|
||||
if (err) {
|
||||
systemErr.write(b);
|
||||
} else {
|
||||
systemOut.write(b);
|
||||
}
|
||||
} catch (IOException e) { } // just ignore, where would we write?
|
||||
}
|
||||
public void write(int b) {
|
||||
write(new byte[] { (byte) b });
|
||||
}
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
try {
|
||||
echo.write(b);
|
||||
echo.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
}
|
||||
}
|
||||
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.write(b, offset, length, err);
|
||||
} else {
|
||||
if (err) {
|
||||
systemErr.write(b, offset, length);
|
||||
} else {
|
||||
systemOut.write(b, offset, length);
|
||||
}
|
||||
system.write(b, offset, length);
|
||||
}
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
if (file != null) {
|
||||
try {
|
||||
echo.write(b, offset, length);
|
||||
echo.flush();
|
||||
file.write(b, offset, length);
|
||||
file.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
single[0] = (byte)b;
|
||||
if (currentConsole != null) {
|
||||
currentConsole.write(single, 0, 1, err);
|
||||
} else {
|
||||
// redirect for all the extra handling above
|
||||
write(new byte[] { (byte) b }, 0, 1);
|
||||
}
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
try {
|
||||
echo.write(b);
|
||||
echo.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
file = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,78 +358,73 @@ public class EditorConsole extends JScrollPane {
|
||||
* 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 {
|
||||
ArrayList<ElementSpec> elements = new ArrayList<ElementSpec>();
|
||||
int maxLineLength, maxLineCount;
|
||||
int currentLineLength = 0;
|
||||
boolean needLineBreak = false;
|
||||
boolean hasAppendage = false;
|
||||
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) {
|
||||
this.maxLineLength = maxLineLength;
|
||||
this.maxLineCount = maxLineCount;
|
||||
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 str, AttributeSet a) {
|
||||
// do this so that it's only updated when needed (otherwise console
|
||||
// updates every 250 ms when an app isn't even running.. see bug 180)
|
||||
hasAppendage = true;
|
||||
|
||||
// process each line of the string
|
||||
while (str.length() > 0) {
|
||||
// newlines within an element have (almost) no effect, so we need to
|
||||
// replace them with proper paragraph breaks (start and end tags)
|
||||
if (needLineBreak || currentLineLength > maxLineLength) {
|
||||
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' || 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;
|
||||
}
|
||||
|
||||
if (str.indexOf('\n') == -1) {
|
||||
elements.add(new ElementSpec(a, ElementSpec.ContentType,
|
||||
str.toCharArray(), 0, str.length()));
|
||||
currentLineLength += str.length();
|
||||
needLineBreak = false;
|
||||
str = str.substring(str.length()); // eat the string
|
||||
} else {
|
||||
elements.add(new ElementSpec(a, ElementSpec.ContentType,
|
||||
str.toCharArray(), 0, str.indexOf('\n') + 1));
|
||||
needLineBreak = true;
|
||||
str = str.substring(str.indexOf('\n') + 1); // eat the line
|
||||
start = stop;
|
||||
}
|
||||
}
|
||||
elements.add(new ElementSpec(a, ElementSpec.ContentType, chars, start,
|
||||
stop - start));
|
||||
}
|
||||
|
||||
/** insert the buffered strings */
|
||||
public synchronized void insertAll() {
|
||||
ElementSpec[] elementArray = new ElementSpec[elements.size()];
|
||||
elements.toArray(elementArray);
|
||||
|
||||
try {
|
||||
// check how many lines have been used so far
|
||||
// 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 element = super.getDefaultRootElement();
|
||||
int lineCount = element.getElementCount();
|
||||
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
|
||||
//systemOut.println("overage is " + overage);
|
||||
Element lineElement = element.getElement(overage);
|
||||
if (lineElement == null) return; // do nuthin
|
||||
Element lineElement = root.getElement(overage);
|
||||
if (lineElement == null)
|
||||
return; // do nuthin
|
||||
|
||||
int endOffset = lineElement.getEndOffset();
|
||||
// remove to the end of the 200th line
|
||||
super.remove(0, endOffset);
|
||||
int endOffset = lineElement.getEndOffset();
|
||||
remove(0, endOffset);
|
||||
}
|
||||
super.insert(super.getLength(), elementArray);
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
// ignore the error otherwise this will cause an infinite loop
|
||||
// maybe not a good idea in the long run?
|
||||
}
|
||||
elements.clear();
|
||||
hasAppendage = false;
|
||||
changed = false;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user