mirror of
https://github.com/processing/processing4.git
synced 2026-01-30 03:41:15 +01:00
split gui and non-gui portions of console for earlier startup
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user