1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-15 12:29:26 +01:00

Refactored and simplified EditorConsole class.

This commit is contained in:
Cristian Maglie 2014-01-26 22:05:57 +01:00
parent 479b974fe1
commit 93562a7800

View File

@ -1,5 +1,3 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* /*
Part of the Processing project - http://processing.org Part of the Processing project - http://processing.org
@ -22,15 +20,32 @@
*/ */
package processing.app; package processing.app;
import static processing.app.I18n._; import static processing.app.I18n._;
import java.awt.*; import java.awt.Color;
import java.awt.event.*; import java.awt.Dimension;
import java.io.*; import java.awt.Font;
import javax.swing.*; import java.awt.FontMetrics;
import javax.swing.text.*; 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 * don't take over System.err, and debug while watching just System.out
* or just write println() or whatever directly to systemOut or systemErr. * 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; Editor editor;
JTextPane consoleTextPane; JTextPane consoleTextPane;
BufferedStyledDocument consoleDoc; BufferedStyledDocument consoleDoc;
MutableAttributeSet stdStyle; SimpleAttributeSet stdStyle;
MutableAttributeSet errStyle; SimpleAttributeSet errStyle;
int maxLineCount;
static File errFile; static File errFile;
static File outFile; static File outFile;
@ -70,20 +84,19 @@ public class EditorConsole extends JScrollPane {
static EditorConsole currentConsole; static EditorConsole currentConsole;
public EditorConsole(Editor _editor) {
editor = _editor;
public EditorConsole(Editor editor) { int maxLineCount = Preferences.getInteger("console.length");
this.editor = editor;
maxLineCount = Preferences.getInteger("console.length"); consoleDoc = new BufferedStyledDocument(4000, maxLineCount);
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
consoleTextPane = new JTextPane(consoleDoc); consoleTextPane = new JTextPane(consoleDoc);
consoleTextPane.setEditable(false); consoleTextPane.setEditable(false);
// necessary? // necessary?
MutableAttributeSet standard = new SimpleAttributeSet(); SimpleAttributeSet leftAlignAttr = new SimpleAttributeSet();
StyleConstants.setAlignment(standard, StyleConstants.ALIGN_LEFT); StyleConstants.setAlignment(leftAlignAttr, StyleConstants.ALIGN_LEFT);
consoleDoc.setParagraphAttributes(0, 0, standard, true); consoleDoc.setParagraphAttributes(0, 0, leftAlignAttr, true);
// build styles for different types of console output // build styles for different types of console output
Color bgColor = Theme.getColor("console.color"); Color bgColor = Theme.getColor("console.color");
@ -112,13 +125,13 @@ public class EditorConsole extends JScrollPane {
consoleTextPane.setBackground(bgColor); consoleTextPane.setBackground(bgColor);
// add the jtextpane to this scrollpane // add the jtextpane to this scrollpane
this.setViewportView(consoleTextPane); setViewportView(consoleTextPane);
// 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 = this.getFontMetrics(font); FontMetrics metrics = getFontMetrics(font);
int height = metrics.getAscent() + metrics.getDescent(); 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 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 * 4) + sizeFudge));
@ -179,7 +192,7 @@ public class EditorConsole extends JScrollPane {
@Override @Override
public void run() { public void run() {
// only if new text has been added // only if new text has been added
if (consoleDoc.hasAppendage) { if (consoleDoc.isChanged()) {
// insert the text that's been added in the meantime // insert the text that's been added in the meantime
consoleDoc.insertAll(); consoleDoc.insertAll();
// always move to the end of the text as it's added // always move to the end of the text as it's added
@ -220,7 +233,7 @@ public class EditorConsole extends JScrollPane {
stdoutFile.close(); stdoutFile.close();
stderrFile.close(); stderrFile.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(systemOut); e.printStackTrace();
} }
outFile.delete(); outFile.delete();
@ -240,23 +253,18 @@ public class EditorConsole extends JScrollPane {
synchronized public void message(String what, boolean err, boolean advance) { synchronized public void message(String what, boolean err, boolean advance) {
if (err) { if (err) {
systemErr.print(what); systemErr.print(what);
//systemErr.print("CE" + what); if (advance)
} else {
systemOut.print(what);
//systemOut.print("CO" + what);
}
if (advance) {
appendText("\n", err);
if (err) {
systemErr.println(); systemErr.println();
} else { } else {
systemOut.print(what);
if (advance)
systemOut.println(); systemOut.println();
} }
}
// to console display // to console display
appendText(what, err); appendText(what, err);
if (advance)
appendText("\n", err);
// moved down here since something is punting // moved down here since something is punting
} }
@ -292,83 +300,47 @@ public class EditorConsole extends JScrollPane {
private static class EditorConsoleStream extends OutputStream { private static class EditorConsoleStream extends OutputStream {
//static EditorConsole current;
final boolean err; // whether stderr or stdout final boolean err; // whether stderr or stdout
final byte single[] = new byte[1]; PrintStream system;
OutputStream file;
public EditorConsoleStream(boolean err) { public EditorConsoleStream(boolean _err) {
this.err = err; err = _err;
if (err) {
system = systemErr;
file = stderrFile;
} else {
system = systemOut;
file = stdoutFile;
}
} }
public void close() { } public void close() { }
public void flush() { } public void flush() { }
public void write(byte b[]) { // appears never to be used public void write(int b) {
if (currentConsole != null) { write(new byte[] { (byte) b });
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?
} }
OutputStream echo = err ? stderrFile : stdoutFile; public void write(byte b[]) { // appears never to be used
if (echo != null) { write(b, 0, b.length);
try {
echo.write(b);
echo.flush();
} catch (IOException e) {
e.printStackTrace();
echo = null;
}
}
} }
public void write(byte b[], int offset, int length) { public void write(byte b[], int offset, int length) {
if (currentConsole != null) { if (currentConsole != null) {
currentConsole.write(b, offset, length, err); currentConsole.write(b, offset, length, err);
} else { } else {
if (err) { system.write(b, offset, length);
systemErr.write(b, offset, length);
} else {
systemOut.write(b, offset, length);
}
} }
OutputStream echo = err ? stderrFile : stdoutFile; if (file != null) {
if (echo != null) {
try { try {
echo.write(b, offset, length); file.write(b, offset, length);
echo.flush(); file.flush();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
echo = null; file = 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;
} }
} }
} }
@ -386,78 +358,73 @@ public class EditorConsole extends JScrollPane {
* appendString() is called from multiple threads, and insertAll from the * appendString() is called from multiple threads, and insertAll from the
* swing event thread, so they need to be synchronized * swing event thread, so they need to be synchronized
*/ */
@SuppressWarnings("serial")
class BufferedStyledDocument extends DefaultStyledDocument { class BufferedStyledDocument extends DefaultStyledDocument {
ArrayList<ElementSpec> elements = new ArrayList<ElementSpec>(); private List<ElementSpec> elements = new ArrayList<ElementSpec>();
int maxLineLength, maxLineCount; private int maxLineLength, maxLineCount;
int currentLineLength = 0; private int currentLineLength = 0;
boolean needLineBreak = false; private boolean changed = false;
boolean hasAppendage = false;
public BufferedStyledDocument(int maxLineLength, int maxLineCount) { public BufferedStyledDocument(int _maxLineLength, int _maxLineCount) {
this.maxLineLength = maxLineLength; maxLineLength = _maxLineLength;
this.maxLineCount = maxLineCount; maxLineCount = _maxLineCount;
} }
/** buffer a string for insertion at the end of the DefaultStyledDocument */ /** buffer a string for insertion at the end of the DefaultStyledDocument */
public synchronized void appendString(String str, AttributeSet a) { public synchronized void appendString(String text, AttributeSet a) {
// do this so that it's only updated when needed (otherwise console changed = true;
// updates every 250 ms when an app isn't even running.. see bug 180) char[] chars = text.toCharArray();
hasAppendage = true; int start = 0;
int stop = 0;
// process each line of the string while (stop < chars.length) {
while (str.length() > 0) { char c = chars[stop];
// newlines within an element have (almost) no effect, so we need to stop++;
// replace them with proper paragraph breaks (start and end tags) currentLineLength++;
if (needLineBreak || currentLineLength > maxLineLength) { 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.EndTagType));
elements.add(new ElementSpec(a, ElementSpec.StartTagType)); elements.add(new ElementSpec(a, ElementSpec.StartTagType));
currentLineLength = 0; currentLineLength = 0;
} start = stop;
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
} }
} }
elements.add(new ElementSpec(a, ElementSpec.ContentType, chars, start,
stop - start));
} }
/** insert the buffered strings */ /** insert the buffered strings */
public synchronized void insertAll() { public synchronized void insertAll() {
ElementSpec[] elementArray = new ElementSpec[elements.size()];
elements.toArray(elementArray);
try { 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 // if too many, shave off a few lines from the beginning
Element element = super.getDefaultRootElement(); Element root = getDefaultRootElement();
int lineCount = element.getElementCount(); int lineCount = root.getElementCount();
int overage = lineCount - maxLineCount; int overage = lineCount - maxLineCount;
if (overage > 0) { if (overage > 0) {
// if 1200 lines, and 1000 lines is max, // if 1200 lines, and 1000 lines is max,
// find the position of the end of the 200th line // find the position of the end of the 200th line
//systemOut.println("overage is " + overage); Element lineElement = root.getElement(overage);
Element lineElement = element.getElement(overage); if (lineElement == null)
if (lineElement == null) return; // do nuthin return; // do nuthin
int endOffset = lineElement.getEndOffset();
// remove to the end of the 200th line // 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) { } 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?
} }
elements.clear(); elements.clear();
hasAppendage = false; changed = false;
}
public boolean isChanged() {
return changed;
} }
} }