diff --git a/processing/app/PdeEditor.java b/processing/app/PdeEditor.java index d8ed932ea..a04556743 100644 --- a/processing/app/PdeEditor.java +++ b/processing/app/PdeEditor.java @@ -27,7 +27,8 @@ public class PdeEditor extends Panel /*implements PdeEnvironment*/ { PdeEditorButtons buttons; PdeEditorHeader header; PdeEditorStatus status; - PdeEditorOutput output; + //PdeEditorOutput output; + PdeEditorConsole console; //Label status; TextArea textarea; @@ -137,20 +138,24 @@ public class PdeEditor extends Panel /*implements PdeEnvironment*/ { status = new PdeEditorStatus(this); statusPanel.add("North", status); - PdeEditorLabel stdoutLabel = new PdeEditorLabel(2); - Color stdoutBgColor = + //int lineCount = PdeApplet.getInteger("editor.console.lines", 4); + console = new PdeEditorConsole(this); //, lineCount); + + /* + Color consoleBgColor = PdeApplet.getColor("editor.console.bgcolor", new Color(26, 26, 26)); - Color stdoutFgColor = + Color consoleFgColor = PdeApplet.getColor("editor.console.fgcolor", new Color(153, 153, 153)); - stdoutLabel.setBackground(stdoutBgColor); - stdoutLabel.setForeground(stdoutFgColor); - Font stdoutFont = + //console.setBackground(consoleBgColor); + //console.setForeground(consoleFgColor); + Font consoleFont = PdeApplet.getFont("editor.console.font", new Font("monospaced", Font.PLAIN, 11)); - stdoutLabel.setFont(stdoutFont); - //stdoutLabel.setText("Test the print"); - //stdoutLabel.setInsets(new Insets(4, 4, 4, 4)); - statusPanel.add("South", stdoutLabel); + console.setFont(consoleFont); + */ + //console.setText("Test the print"); + //console.setInsets(new Insets(4, 4, 4, 4)); + statusPanel.add("South", console); rightPanel.add("South", statusPanel); diff --git a/processing/app/PdeEditorConsole.java b/processing/app/PdeEditorConsole.java new file mode 100644 index 000000000..07eb309a8 --- /dev/null +++ b/processing/app/PdeEditorConsole.java @@ -0,0 +1,282 @@ +import java.awt.*; +import java.io.*; + + +// might be nice to have option to save this to a file + +// debugging this class is tricky.. if it's throwing +// exceptions, don't take over System.err, and debug +// while watching just System.out +// or just write directly to systemOut or systemErr + +public class PdeEditorConsole extends Component { + PdeEditor editor; + + static final byte CR = (byte)'\r'; + static final byte LF = (byte)'\n'; + + int lineCount; + int maxLineCount; + String lines[]; + boolean isError[]; + int firstLine; + + byte cline[] = new byte[1024]; + byte clength; + boolean cerror; + + Color bgColor; + Color fgColorErr; + Color fgColorOut; + + Font font; + FontMetrics metrics; + int ascent; + int leading; + + Image offscreen; + int sizeW, sizeH; + int imageW, imageH; + + static final int HINSET = 6; + static final int VINSET = 6; + + static PrintStream systemOut; + static PrintStream systemErr; + + PrintStream consoleOut; + PrintStream consoleErr; + + + public PdeEditorConsole(PdeEditor editor) { + this.editor = editor; + + lineCount = PdeApplet.getInteger("editor.console.lines", 6); + + if (systemOut == null) { + systemOut = System.out; + systemErr = System.err; + + consoleOut = new PrintStream(new PdeEditorConsoleStream(this, false)); + consoleErr = new PrintStream(new PdeEditorConsoleStream(this, true)); + + System.setOut(consoleOut); + System.setErr(consoleErr); + } + + maxLineCount = 1000; + lines = new String[maxLineCount]; + isError = new boolean[maxLineCount]; + for (int i = 0; i < maxLineCount; i++) { + lines[i] = ""; + isError[i] = false; + } + firstLine = 0; + } + + + public void update() { + Graphics g = this.getGraphics(); + if (g != null) paint(g); + } + + public void update(Graphics g) { + paint(g); + } + + public void paint(Graphics screen) { + //systemOut.println("paint()"); + if (bgColor == null) { + bgColor = PdeApplet.getColor("editor.console.bgcolor", + new Color(26, 26, 26)); + fgColorOut = PdeApplet.getColor("editor.console.fgcolor.output", + new Color(153, 153, 153)); + fgColorErr = PdeApplet.getColor("editor.console.fgcolor.error", + new Color(153, 0, 0)); + screen.setFont(font); + metrics = screen.getFontMetrics(); + ascent = metrics.getAscent(); + leading = ascent + metrics.getDescent(); + //System.out.println(ascent + " " + leading); + } + + Dimension size = getSize(); + if ((size.width != sizeW) || (size.height != sizeH)) { + // component has been resized + + if ((size.width > imageW) || (size.height > imageH)) { + // nix the image and recreate, it's too small + offscreen = null; + + } else { + // who cares, just resize + sizeW = size.width; + sizeH = size.height; + //setButtonBounds(); + } + } + //systemErr.println("size h, w = " + sizeW + " " + sizeH); + + if (offscreen == null) { + sizeW = size.width; + sizeH = size.height; + //setButtonBounds(); + imageW = sizeW; + imageH = sizeH; + offscreen = createImage(imageW, imageH); + } + + if (offscreen == null) return; + Graphics g = offscreen.getGraphics(); + /* + if (font == null) { + font = PdeApplet.getFont("editor.console.font", + new Font("Monospaced", Font.PLAIN, 11)); + //font = new Font("SansSerif", Font.PLAIN, 10); + g.setFont(font); + metrics = g.getFontMetrics(); + ascent = metrics.getAscent(); + } + */ + g.setFont(font); + + g.setColor(bgColor); + g.fillRect(0, 0, imageW, imageH); + + for (int i = 0; i < lineCount; i++) { + int ii = (firstLine + i) % maxLineCount; + g.setColor(isError[ii] ? fgColorErr : fgColorOut); + //System.out.println(leading); + g.drawString(lines[ii], HINSET, VINSET + ascent + i*ascent); + } + + screen.drawImage(offscreen, 0, 0, null); + } + + public void write(byte b[], int offset, int length, boolean err) { + if ((clength > 0) && (err != cerror)) { + // advance the line because switching between err/out streams + message(new String(cline, 0, clength), cerror, true); + clength = 0; + } + int last = offset+length - 1; + // starting a new line, so set its output type to out or err + if (clength == 0) cerror = err; + for (int i = offset; i <= last; i++) { + if (b[i] == CR) { // mac CR or win CRLF + if ((i != last) && (b[i+1] == LF)) { + // if windows CRLF, skip the LF too + i++; + } + message(new String(cline, 0, clength), cerror, true); + clength = 0; + + } else if (b[i] == LF) { // unix LF only + message(new String(cline, 0, clength), cerror, true); + clength = 0; + + } else { + if (cline.length == clength) { + byte temp[] = new byte[clength * 2]; + System.arraycopy(cline, 0, temp, 0, clength); + cline = temp; + } + cline[clength++] = b[i]; + } + } + if (clength != 0) { + message(new String(cline, 0, clength), cerror, false); + } + } + + public void message(String what, boolean err, boolean advance) { + int currentLine = (firstLine + lineCount) % maxLineCount; + lines[currentLine] = what; + isError[currentLine] = err; + + if (advance) { + firstLine = (firstLine + 1) % maxLineCount; + //systemOut.println((err ? "ERR: " : "OUT: ") + what); + systemOut.println(what); + } + update(); + } + + public Dimension getPreferredSize() { + //systemOut.println("pref'd sizde"); + if (font == null) { + font = PdeApplet.getFont("editor.console.font", + new Font("Monospaced", Font.PLAIN, 11)); + //font = new Font("SansSerif", Font.PLAIN, 10); + //g.setFont(font); + //metrics = g.getFontMetrics(); + metrics = Toolkit.getDefaultToolkit().getFontMetrics(font); + ascent = metrics.getAscent(); + } + + //if (ascent == 0) { + // no useful font information yet + //System.out.println("PdeEditorConsole: setting size w/o metrics"); + //return new Dimension(300, 84); + //} else { + //System.out.println("PdeEditorConsole: got metrics, setting size" + + // new Dimension(300 + HINSET*2, + // leading*lineCount + VINSET*2)); + return new Dimension(300 + HINSET*2, + ascent*lineCount + VINSET*2); + //} + } +} + + +class PdeEditorConsoleStream extends OutputStream { + PdeEditorConsole parent; + boolean err; // whether stderr or stdout + byte single[] = new byte[1]; + + public PdeEditorConsoleStream(PdeEditorConsole parent, boolean err) { + this.parent = parent; + this.err = err; + } + + public void close() { } + + public void flush() { } + + public void write(byte b[]) { // appears never to be used + parent.write(b, 0, b.length, err); + } + + public void write(byte b[], int offset, int length) { + parent.write(b, offset, length, err); + /* + //System.out.println("leech2:"); + if (length >= 1) { + int lastchar = b[offset + length - 1]; + if (lastchar == '\r') { + length--; + } else if (lastchar == '\n') { + if (length >= 2) { + int secondtolastchar = b[offset + length - 2]; + if (secondtolastchar == '\r') { + length -= 2; + } else { + length--; + } + } else { + length--; + } + } + //if ((lastchar = '\r') || (lastchar == '\n')) length--; + } + //if (b[offset + length - 1] == '\r' + parent.message("2: " + length + " " + new String(b, offset, length), err); + */ + } + + public void write(int b) { + single[0] = (byte)b; + parent.write(single, 0, 1, err); + //parent.message(String.valueOf((char)b), err); + } +} diff --git a/processing/app/PdeEditorHeader.java b/processing/app/PdeEditorHeader.java index d4f8b4be6..f9e8357ce 100644 --- a/processing/app/PdeEditorHeader.java +++ b/processing/app/PdeEditorHeader.java @@ -53,9 +53,9 @@ public class PdeEditorHeader extends Panel /* implements ActionListener*/ { if (primaryColor == null) { backgroundColor = PdeApplet.getColor("editor.header.bgcolor", new Color(51, 51, 51)); - primaryColor = PdeApplet.getColor("editor.header.fgcolor1", + primaryColor = PdeApplet.getColor("editor.header.fgcolor.primary", new Color(255, 255, 255)); - secondaryColor = PdeApplet.getColor("editor.header.fgcolor2", + secondaryColor = PdeApplet.getColor("editor.header.fgcolor.secondary", new Color(153, 153, 153)); } } diff --git a/processing/app/PdeEditorLabel.java b/processing/app/PdeEditorLabel.java deleted file mode 100644 index 8834423f6..000000000 --- a/processing/app/PdeEditorLabel.java +++ /dev/null @@ -1,19 +0,0 @@ -import java.awt.*; - - -public class PdeEditorLabel extends Label { - int rows; - - public PdeEditorLabel(int rows) { - super(""); //pde editor label"); - setRows(rows); - } - - public void setRows(int rows) { - this.rows = rows; - } - - public Dimension getPreferredSize() { - return new Dimension(200, rows * PdeEditorButtons.BUTTON_HEIGHT); - } -} diff --git a/processing/app/PdeEditorOutput.java b/processing/app/PdeEditorOutput.java deleted file mode 100644 index 88364f367..000000000 --- a/processing/app/PdeEditorOutput.java +++ /dev/null @@ -1,11 +0,0 @@ -import java.awt.*; -import java.io.*; - - -public class PdeEditorOutput extends Component { - PdeEditor editor; - - public PdeEditorOutput(PdeEditor editor) { - this.editor = editor; - } -} diff --git a/processing/app/PdeEditorStatus.java b/processing/app/PdeEditorStatus.java index 78d7d7c07..13087c9c1 100644 --- a/processing/app/PdeEditorStatus.java +++ b/processing/app/PdeEditorStatus.java @@ -25,7 +25,7 @@ public class PdeEditorStatus extends Panel implements ActionListener { Font font; FontMetrics metrics; - int fontAscent; + int ascent; Image offscreen; int sizeW, sizeH; @@ -101,7 +101,8 @@ public class PdeEditorStatus extends Panel implements ActionListener { public void update() { - paint(this.getGraphics()); + Graphics g = this.getGraphics(); + if (g != null) paint(g); } public void update(Graphics g) { @@ -109,8 +110,7 @@ public class PdeEditorStatus extends Panel implements ActionListener { } public void paint(Graphics screen) { - if (screen == null) return; - + //if (screen == null) return; if (yesButton == null) { yesButton = new Button(PROMPT_YES); noButton = new Button(PROMPT_NO); @@ -158,14 +158,14 @@ public class PdeEditorStatus extends Panel implements ActionListener { //font = new Font("SansSerif", Font.PLAIN, 10); g.setFont(font); metrics = g.getFontMetrics(); - fontAscent = metrics.getAscent(); + ascent = metrics.getAscent(); } g.setColor(bgColor[mode]); g.fillRect(0, 0, imageW, imageH); g.setColor(fgColor[mode]); - g.drawString(message, PdeEditor.INSET_SIZE, (sizeH + fontAscent) / 2); + g.drawString(message, PdeEditor.INSET_SIZE, (sizeH + ascent) / 2); screen.drawImage(offscreen, 0, 0, null); } diff --git a/processing/app/buttons.gif b/processing/app/buttons.gif index 131d4a8e6..f13a8df08 100644 Binary files a/processing/app/buttons.gif and b/processing/app/buttons.gif differ