split gui and non-gui portions of console for earlier startup

This commit is contained in:
Ben Fry
2016-12-03 15:46:26 -05:00
parent 7a6b2b221b
commit e0586a39fb
5 changed files with 201 additions and 425 deletions

View File

@@ -139,6 +139,8 @@ public class Base {
}
Platform.init();
// call after Platform.init() because we need the settings folder
Console.startup();
// Set the debug flag based on a file being present in the settings folder
File debugFile = getSettingsFile("debug.txt");
@@ -1474,6 +1476,9 @@ public class Base {
// Save out the current prefs state
Preferences.save();
// Finished with this guy
Console.shutdown();
if (!Platform.isMacOS()) {
// If this was fired from the menu or an AppleEvent (the Finder),
// then Mac OS X will send the terminate signal itself.

View File

@@ -3,7 +3,8 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-10 Ben Fry and Casey Reas
Copyright (c) 2012-16 The Processing Foundation
Copyright (c) 2004-12 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
@@ -21,25 +22,11 @@
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.ui;
package processing.app;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.*;
import javax.swing.border.MatteBorder;
import javax.swing.text.*;
import processing.app.*;
import processing.core.PApplet;
/**
@@ -55,76 +42,87 @@ import processing.core.PApplet;
* It seems that Eclipse's console-grabbing and that of Processing don't
* get along with one another. Use 'ant run' to work on encoding-related issues.
*/
public class EditorConsole extends JScrollPane {
Editor editor;
Timer flushTimer;
JTextPane consoleTextPane;
BufferedStyledDocument consoleDoc;
MutableAttributeSet stdStyle;
MutableAttributeSet errStyle;
int maxLineCount;
PrintStream sketchOut;
PrintStream sketchErr;
public class Console {
// PrintStream sketchOut;
// PrintStream sketchErr;
// 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.
/** The original System.out */
static PrintStream systemOut;
/** The original System.err */
static PrintStream systemErr;
/** Our replacement System.out */
static PrintStream consoleOut;
/** Our replacement System.err */
static PrintStream consoleErr;
/** All stdout also written to a file */
static OutputStream stdoutFile;
/** All stderr also written to a file */
static OutputStream stderrFile;
static EditorConsole currentConsole;
/** stdout listener for the currently active Editor */
static OutputStream editorOut;
/** stderr listener for the currently active Editor */
static OutputStream editorErr;
// For 0185, moved the first init to this static { } block, so that we never
// have a situation that causes systemOut/Err to not be set properly.
static {
static public void startup() {
systemOut = System.out;
systemErr = System.err;
// placing everything inside a try block because this can be a dangerous
// time for the lights to blink out and crash for and obscure reason.
try {
// Create output files that 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.
SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
String randy = PApplet.nf((int) (1000 * Math.random()), 4);
String stamp = formatter.format(new Date()) + "_" + randy;
SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd_HHmmss");
// Moving away from a random string in 0256 (and adding hms) because
// the random digits looked like times anyway, causing confusion.
//String randy = String.format("%04d", (int) (1000 * Math.random()));
//final String stamp = formatter.format(new Date()) + "_" + randy;
final String stamp = formatter.format(new Date());
File consoleDir = Base.getSettingsFile("console");
consoleDir.mkdirs();
if (consoleDir.exists()) {
// clear old debug files
File[] stdFiles = consoleDir.listFiles(new FileFilter() {
final String todayPrefix = stamp.substring(0, 4);
public boolean accept(File file) {
if (!file.isDirectory()) {
String name = file.getName();
if (name.endsWith(".err") || name.endsWith(".out")) {
// don't delete any of today's debug messages
return !name.startsWith(todayPrefix);
}
}
return false;
}
});
// Remove any files that aren't from today
for (File file : stdFiles) {
file.delete();
}
} else {
consoleDir.mkdirs();
}
File outFile = new File(consoleDir, stamp + ".out");
stdoutFile = new FileOutputStream(outFile);
File errFile = new File(consoleDir, stamp + ".err");
stderrFile = new FileOutputStream(errFile);
consoleOut = new PrintStream(new EditorConsoleStream(false, null));
consoleErr = new PrintStream(new EditorConsoleStream(true, null));
// consoleOut = new PrintStream(new EditorConsoleStream(false, null));
// consoleErr = new PrintStream(new EditorConsoleStream(true, null));
consoleOut = new PrintStream(new ConsoleStream(false));
consoleErr = new PrintStream(new ConsoleStream(true));
System.setOut(consoleOut);
System.setErr(consoleErr);
// } catch (Exception e) {
// stdoutFile = null;
// stderrFile = null;
//
// e.printStackTrace();
// Base.showWarning("Console Error",
// "A problem occurred while trying to open the\n" +
// "files used to store the console output.", e);
} catch (Exception e) {
stdoutFile = null;
stderrFile = null;
@@ -135,159 +133,31 @@ public class EditorConsole extends JScrollPane {
System.setOut(systemOut);
System.setErr(systemErr);
e.printStackTrace(systemErr);
e.printStackTrace();
}
}
public EditorConsole(Editor editor) {
this.editor = editor;
maxLineCount = Preferences.getInteger("console.length");
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
consoleTextPane = new JTextPane(consoleDoc);
consoleTextPane.setEditable(false);
updateMode();
// add the jtextpane to this scrollpane
this.setViewportView(consoleTextPane);
sketchOut = new PrintStream(new EditorConsoleStream(false, this));
sketchErr = new PrintStream(new EditorConsoleStream(true, this));
startTimer();
static public void setEditor(OutputStream out, OutputStream err) {
editorOut = out;
editorErr = err;
}
protected void flush() {
// only if new text has been added
if (consoleDoc.hasAppendage) {
// 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());
}
}
// public Console() {
// sketchOut = new PrintStream(new EditorConsoleStream(false, this));
// sketchErr = new PrintStream(new EditorConsoleStream(true, this));
// }
/**
* Start the timer that handles flushing the console text. Has to be started
* and stopped/cleared because the Timer thread will keep a reference to its
* Editor around even after the Editor has been closed, leaking memory.
*/
protected void startTimer() {
if (flushTimer == null) {
// periodically post buffered messages to the console
// should the interval come from the preferences file?
flushTimer = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
flush();
}
});
flushTimer.start();
}
}
// public PrintStream getOut() {
// return sketchOut;
// }
protected void stopTimer() {
if (flushTimer != null) {
flush(); // clear anything that's there
flushTimer.stop();
flushTimer = null;
}
}
public PrintStream getOut() {
return sketchOut;
}
public PrintStream getErr() {
return sketchErr;
}
/**
* Update the font family and sizes based on the Preferences window.
*/
protected void updateAppearance() {
String fontFamily = Preferences.get("editor.font.family");
int fontSize = Preferences.getInteger("console.font.size");
StyleConstants.setFontFamily(stdStyle, fontFamily);
StyleConstants.setFontSize(stdStyle, fontSize);
StyleConstants.setFontFamily(errStyle, fontFamily);
StyleConstants.setFontSize(errStyle, fontSize);
clear(); // otherwise we'll have mixed fonts
}
/**
* Change coloring, fonts, etc in response to a mode change.
*/
protected void updateMode() {
Mode mode = editor.getMode();
// necessary?
MutableAttributeSet standard = new SimpleAttributeSet();
StyleConstants.setAlignment(standard, StyleConstants.ALIGN_LEFT);
consoleDoc.setParagraphAttributes(0, 0, standard, true);
Font font = Preferences.getFont("console.font");
// build styles for different types of console output
Color bgColor = mode.getColor("console.color");
Color fgColorOut = mode.getColor("console.output.color");
Color fgColorErr = mode.getColor("console.error.color");
// Make things line up with the Editor above. If this is ever removed,
// setBorder(null) should be called instead. The defaults are nasty.
setBorder(new MatteBorder(0, Editor.LEFT_GUTTER, 0, 0, bgColor));
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());
if (UIManager.getLookAndFeel().getID().equals("Nimbus")) {
getViewport().setBackground(bgColor);
consoleTextPane.setOpaque(false);
consoleTextPane.setBackground(new Color(0, 0, 0, 0));
} else {
consoleTextPane.setBackground(bgColor);
}
// calculate height of a line of text in pixels
// and size window accordingly
FontMetrics metrics = this.getFontMetrics(font);
int height = metrics.getAscent() + metrics.getDescent();
int lines = Preferences.getInteger("console.lines"); //, 4);
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));
}
static public void setEditor(Editor editor) {
if (currentConsole != null) {
currentConsole.stopTimer(); // allow to be garbage collected
}
currentConsole = editor.console;
currentConsole.startTimer();
}
// public PrintStream getErr() {
// return sketchErr;
// }
/**
@@ -298,66 +168,29 @@ public class EditorConsole extends JScrollPane {
* folder itself is deleted, which can't be guaranteed when using
* the deleteOnExit() method.
*/
public static void handleQuit() {
static public void shutdown() {
// replace original streams to remove references to console's streams
System.setOut(systemOut);
System.setErr(systemErr);
cleanup(consoleOut);
cleanup(consoleErr);
// also have to close the original FileOutputStream
// otherwise it won't be shut down completely
cleanup(stdoutFile);
cleanup(stderrFile);
}
static private void cleanup(OutputStream output) {
try {
// close the PrintStream
if (consoleOut != null) consoleOut.close();
if (consoleErr != null) consoleErr.close();
// also have to close the original FileOutputStream
// otherwise it won't be shut down completely
if (stdoutFile != null) stdoutFile.close();
if (stderrFile != null) stderrFile.close();
if (output != null) {
output.flush();
output.close();
}
} catch (IOException e) {
e.printStackTrace(systemErr);
}
}
synchronized public void message(String what, boolean err) {
if (err) {
systemErr.print(what);
} else {
systemOut.print(what);
}
if (err && (what.contains("invalid context 0x0") || (what.contains("invalid drawable")))) {
// Respectfully declining... This is a quirk of more recent releases of
// Java on Mac OS X, but is widely reported as the source of any other
// bug or problem that a user runs into. It may well be a Processing
// bug, but until we know, we're suppressing the messages.
} else if (err && what.contains("Make pbuffer:")) {
// Remove initalization warning from LWJGL.
} else if (err && what.contains("XInitThreads() called for concurrent")) {
// "Info: XInitThreads() called for concurrent Thread support" message on Linux
} else if (!err && what.contains("Listening for transport dt_socket at address")) {
// Message from the JVM about the socket launch for debug
// Listening for transport dt_socket at address: 8727
} else {
// 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)
consoleDoc.appendString(what, err ? 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?
e.printStackTrace();
}
}
@@ -365,14 +198,12 @@ public class EditorConsole extends JScrollPane {
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
private static class EditorConsoleStream extends OutputStream {
final boolean err; // whether stderr or stdout
final byte single[] = new byte[1];
EditorConsole console;
static class ConsoleStream extends OutputStream {
boolean err; // whether stderr or stdout
byte single[] = new byte[1];
public EditorConsoleStream(boolean err, EditorConsole console) {
public ConsoleStream(boolean err) {
this.err = err;
this.console = console;
}
public void close() { }
@@ -384,20 +215,34 @@ public class EditorConsole extends JScrollPane {
}
public void write(byte b[], int offset, int length) {
if (console != null) {
console.message(new String(b, offset, length), err);
} else if (currentConsole != null) {
currentConsole.message(new String(b, offset, length), err);
// First write to the original stdout/stderr
if (err) {
systemErr.write(b, offset, length);
} else {
// If no console is present, still need to write this to the actual
// System.out or System.err. Otherwise we can't !#$!% debug anything.
if (err) {
systemErr.write(b, offset, length);
} else {
systemOut.write(b, offset, length);
}
systemOut.write(b, offset, length);
}
// Write to the files that are storing this information
writeFile(b, offset, length);
// Write to the console of the current Editor, if any
try {
if (err) {
if (editorErr != null) {
editorErr.write(b, offset, length);
}
} else {
if (editorOut != null) {
editorOut.write(b, offset, length);
}
}
} catch (IOException e) {
// Avoid this function being called in a recursive, infinite loop
e.printStackTrace(systemErr);
}
}
public void writeFile(byte b[], int offset, int length) {
final OutputStream echo = err ? stderrFile : stdoutFile;
if (echo != null) {
try {
@@ -414,91 +259,4 @@ public class EditorConsole extends JScrollPane {
write(single, 0, 1);
}
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
* 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
*/
class BufferedStyledDocument extends DefaultStyledDocument {
List<ElementSpec> elements = new ArrayList<ElementSpec>();
int maxLineLength, maxLineCount;
int currentLineLength = 0;
boolean needLineBreak = false;
boolean hasAppendage = false;
public BufferedStyledDocument(int maxLineLength, int maxLineCount) {
this.maxLineLength = maxLineLength;
this.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) {
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
}
}
}
/** 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
// if too many, shave off a few lines from the beginning
Element element = super.getDefaultRootElement();
int lineCount = element.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
int endOffset = lineElement.getEndOffset();
// remove to the end of the 200th line
super.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;
}
}
}

View File

@@ -182,25 +182,21 @@ public abstract class Editor extends JFrame implements RunnerListener {
// When bringing a window to front, let the Base know
addWindowListener(new WindowAdapter() {
// int importIndex;
public void windowActivated(WindowEvent e) {
base.handleActivated(Editor.this);
fileMenu.insert(Recent.getMenu(), 2);
Toolkit.setMenuMnemsInside(fileMenu);
//sketchMenu.insert(mode.getImportMenu(), 5);
mode.insertImportMenu(sketchMenu);
//sketchMenu.insert(mode.getImportMenu(), importIndex);
Toolkit.setMenuMnemsInside(sketchMenu);
mode.insertToolbarRecentMenu();
}
public void windowDeactivated(WindowEvent e) {
// TODO call handleActivated(null)? or do we run the risk of the
// deactivate call for old window being called after the activate?
fileMenu.remove(Recent.getMenu());
// JMenu importMenu = mode.getImportMenu();
// importIndex = sketchMenu.getComponentZOrder(mode.getImportMenu());
// sketchMenu.remove(mode.getImportMenu());
mode.removeImportMenu(sketchMenu);
mode.removeToolbarRecentMenu();
}

View File

@@ -3,7 +3,8 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-10 Ben Fry and Casey Reas
Copyright (c) 2012-16 The Processing Foundation
Copyright (c) 2004-12 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
@@ -27,19 +28,20 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.*;
import javax.swing.border.MatteBorder;
import javax.swing.text.*;
import processing.app.*;
import processing.core.PApplet;
import processing.app.Console;
import processing.app.Mode;
import processing.app.Preferences;
/**
@@ -71,6 +73,7 @@ public class EditorConsole extends JScrollPane {
PrintStream sketchOut;
PrintStream sketchErr;
/*
// 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.
@@ -83,9 +86,11 @@ public class EditorConsole extends JScrollPane {
static OutputStream stdoutFile;
static OutputStream stderrFile;
*/
static EditorConsole currentConsole;
static EditorConsole current;
/*
// For 0185, moved the first init to this static { } block, so that we never
// have a situation that causes systemOut/Err to not be set properly.
static {
@@ -138,6 +143,7 @@ public class EditorConsole extends JScrollPane {
e.printStackTrace(systemErr);
}
}
*/
public EditorConsole(Editor editor) {
@@ -154,8 +160,10 @@ public class EditorConsole extends JScrollPane {
// add the jtextpane to this scrollpane
this.setViewportView(consoleTextPane);
sketchOut = new PrintStream(new EditorConsoleStream(false, this));
sketchErr = new PrintStream(new EditorConsoleStream(true, this));
// sketchOut = new PrintStream(new EditorConsoleStream(false, this));
// sketchErr = new PrintStream(new EditorConsoleStream(true, this));
sketchOut = new PrintStream(new EditorConsoleStream(false));
sketchErr = new PrintStream(new EditorConsoleStream(true));
startTimer();
}
@@ -282,49 +290,58 @@ public class EditorConsole extends JScrollPane {
static public void setEditor(Editor editor) {
if (currentConsole != null) {
currentConsole.stopTimer(); // allow to be garbage collected
if (current != null) {
current.stopTimer(); // allow to be garbage collected
}
currentConsole = editor.console;
currentConsole.startTimer();
editor.console.setCurrent();
}
/**
* Close the streams so that the temporary files can be deleted.
* <p/>
* File.deleteOnExit() cannot be used because the stdout and stderr
* files are inside a folder, and have to be deleted before the
* folder itself is deleted, which can't be guaranteed when using
* the deleteOnExit() method.
*/
public static void handleQuit() {
// replace original streams to remove references to console's streams
System.setOut(systemOut);
System.setErr(systemErr);
try {
// close the PrintStream
if (consoleOut != null) consoleOut.close();
if (consoleErr != null) consoleErr.close();
// also have to close the original FileOutputStream
// otherwise it won't be shut down completely
if (stdoutFile != null) stdoutFile.close();
if (stderrFile != null) stderrFile.close();
} catch (IOException e) {
e.printStackTrace(systemErr);
}
void setCurrent() {
current = this; //editor.console;
startTimer();
Console.setEditor(sketchOut, sketchErr);
}
// /**
// * Close the streams so that the temporary files can be deleted.
// * <p/>
// * File.deleteOnExit() cannot be used because the stdout and stderr
// * files are inside a folder, and have to be deleted before the
// * folder itself is deleted, which can't be guaranteed when using
// * the deleteOnExit() method.
// */
// public static void handleQuit() {
// // replace original streams to remove references to console's streams
// System.setOut(systemOut);
// System.setErr(systemErr);
//
// try {
// // close the PrintStream
// if (consoleOut != null) consoleOut.close();
// if (consoleErr != null) consoleErr.close();
//
// // also have to close the original FileOutputStream
// // otherwise it won't be shut down completely
// if (stdoutFile != null) stdoutFile.close();
// if (stderrFile != null) stderrFile.close();
//
// } catch (IOException e) {
// e.printStackTrace(systemErr);
// }
// }
synchronized public void message(String what, boolean err) {
// now handled in Console
/*
if (err) {
systemErr.print(what);
Console.systemErr.print(what);
} else {
systemOut.print(what);
Console.systemOut.print(what);
}
*/
if (err && (what.contains("invalid context 0x0") || (what.contains("invalid drawable")))) {
// Respectfully declining... This is a quirk of more recent releases of
@@ -362,12 +379,13 @@ public class EditorConsole extends JScrollPane {
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
private static class EditorConsoleStream extends OutputStream {
final boolean err; // whether stderr or stdout
final byte single[] = new byte[1];
/*
static class EditorConsoleStream extends OutputStream {
boolean err;
EditorConsole console;
public EditorConsoleStream(boolean err, EditorConsole console) {
@@ -375,14 +393,6 @@ public class EditorConsole extends JScrollPane {
this.console = console;
}
public void close() { }
public void flush() { }
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 (console != null) {
console.message(new String(b, offset, length), err);
@@ -397,21 +407,26 @@ public class EditorConsole extends JScrollPane {
systemOut.write(b, offset, length);
}
}
writeEcho(b, offset, length);
}
}
*/
final OutputStream echo = err ? stderrFile : stdoutFile;
if (echo != null) {
try {
echo.write(b, offset, length);
echo.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
class EditorConsoleStream extends OutputStream {
boolean err;
public EditorConsoleStream(boolean err) {
this.err = err;
}
public void write(byte b[], int offset, int length) {
message(new String(b, offset, length), err);
}
// doesn't appear to be called (but must be implemented)
public void write(int b) {
single[0] = (byte) b;
write(single, 0, 1);
write(new byte[] { (byte) b }, 0, 1);
}
}
}

View File

@@ -21,6 +21,8 @@ cleaning
o probably should also check to make sure PApplet running JVM 8
X or compile against 1.8 and force it?
_ no prompt shows with selectInput() on 10.11 and 10.12
_ https://github.com/processing/processing/issues/4758
_ TRIANGLE_STRIP not working correctly with createShape() and default renderer
_ https://github.com/processing/processing/issues/4678