3232import java .awt .event .ActionListener ;
3333import java .io .OutputStream ;
3434import java .io .PrintStream ;
35- import java .util .ArrayList ;
36- import java .util .List ;
35+ import java .util .concurrent .LinkedBlockingQueue ;
3736
3837import javax .swing .*;
3938import javax .swing .border .MatteBorder ;
4645
4746/**
4847 * Message console that sits below the editing area.
49- * <p />
50- * Be careful when debugging this class, because if it's throwing exceptions,
51- * don't take over System.err, and debug while watching just System.out
52- * or just call println() or whatever directly to systemOut or systemErr.
53- * <p />
54- * Also note that encodings will not work properly when run from Eclipse. This
55- * means that if you use non-ASCII characters in a println() or some such,
56- * the characters won't print properly in the Processing and/or Eclipse console.
57- * It seems that Eclipse's console-grabbing and that of Processing don't
58- * get along with one another. Use 'ant run' to work on encoding-related issues.
5948 */
6049public class EditorConsole extends JScrollPane {
6150 Editor editor ;
@@ -69,6 +58,7 @@ public class EditorConsole extends JScrollPane {
6958 MutableAttributeSet errStyle ;
7059
7160 int maxLineCount ;
61+ int maxCharCount ;
7262
7363 PrintStream sketchOut ;
7464 PrintStream sketchErr ;
@@ -79,9 +69,10 @@ public class EditorConsole extends JScrollPane {
7969 public EditorConsole (Editor editor ) {
8070 this .editor = editor ;
8171
82- maxLineCount = Preferences .getInteger ("console.length" );
72+ maxLineCount = Preferences .getInteger ("console.lines" );
73+ maxCharCount = Preferences .getInteger ("console.chars" );
8374
84- consoleDoc = new BufferedStyledDocument (10000 , maxLineCount );
75+ consoleDoc = new BufferedStyledDocument (10000 , maxLineCount , maxCharCount );
8576 consoleTextPane = new JTextPane (consoleDoc );
8677 consoleTextPane .setEditable (false );
8778
@@ -98,7 +89,7 @@ public EditorConsole(Editor editor) {
9889
9990 protected void flush () {
10091 // only if new text has been added
101- if (consoleDoc .hasAppendage ) {
92+ if (consoleDoc .hasAppendage () ) {
10293 // insert the text that's been added in the meantime
10394 consoleDoc .insertAll ();
10495 // always move to the end of the text as it's added
@@ -150,8 +141,7 @@ public PrintStream getErr() {
150141 */
151142 protected void updateAppearance () {
152143 String fontFamily = Preferences .get ("editor.font.family" );
153- int fontSize =
154- Toolkit .zoom (Preferences .getInteger ("console.font.size" ));
144+ int fontSize = Toolkit .zoom (Preferences .getInteger ("console.font.size" ));
155145 StyleConstants .setFontFamily (stdStyle , fontFamily );
156146 StyleConstants .setFontSize (stdStyle , fontSize );
157147 StyleConstants .setFontFamily (errStyle , fontFamily );
@@ -232,7 +222,7 @@ void setCurrent() {
232222 }
233223
234224
235- synchronized public void message (String what , boolean err ) {
225+ public void message (String what , boolean err ) {
236226 if (err && (what .contains ("invalid context 0x0" ) || (what .contains ("invalid drawable" )))) {
237227 // Respectfully declining... This is a quirk of more recent releases of
238228 // Java on Mac OS X, but is widely reported as the source of any other
@@ -302,22 +292,32 @@ public void write(int b) {
302292 * swing event thread, so they need to be synchronized
303293 */
304294class BufferedStyledDocument extends DefaultStyledDocument {
305- List <ElementSpec > elements = new ArrayList <>();
306- int maxLineLength , maxLineCount ;
295+ //List<ElementSpec> elements = new ArrayList<>();
296+ LinkedBlockingQueue <ElementSpec > elements ;
297+ // AtomicInteger queuedLineCount = new AtomicInteger();
298+ int maxLineLength , maxLineCount , maxCharCount ;
307299 int currentLineLength = 0 ;
308300 boolean needLineBreak = false ;
309- boolean hasAppendage = false ;
301+ // boolean hasAppendage = false;
302+ final Object insertLock = new Object ();
310303
311- public BufferedStyledDocument (int maxLineLength , int maxLineCount ) {
304+ public BufferedStyledDocument (int maxLineLength , int maxLineCount ,
305+ int maxCharCount ) {
312306 this .maxLineLength = maxLineLength ;
313307 this .maxLineCount = maxLineCount ;
308+ this .maxCharCount = maxCharCount ;
309+ elements = new LinkedBlockingQueue <>();
310+ }
311+
312+ // monitor this so that it's only updated when needed (otherwise console
313+ // updates every 250 ms when an app isn't even running.. see bug 180)
314+ public boolean hasAppendage () {
315+ return elements .size () > 0 ;
314316 }
315317
316318 /** buffer a string for insertion at the end of the DefaultStyledDocument */
317- public synchronized void appendString (String str , AttributeSet a ) {
318- // do this so that it's only updated when needed (otherwise console
319- // updates every 250 ms when an app isn't even running.. see bug 180)
320- hasAppendage = true ;
319+ public void appendString (String str , AttributeSet a ) {
320+ // hasAppendage = true;
321321
322322 // process each line of the string
323323 while (str .length () > 0 ) {
@@ -326,6 +326,7 @@ public synchronized void appendString(String str, AttributeSet a) {
326326 if (needLineBreak || currentLineLength > maxLineLength ) {
327327 elements .add (new ElementSpec (a , ElementSpec .EndTagType ));
328328 elements .add (new ElementSpec (a , ElementSpec .StartTagType ));
329+ // queuedLineCount.incrementAndGet();
329330 currentLineLength = 0 ;
330331 }
331332
@@ -341,15 +342,42 @@ public synchronized void appendString(String str, AttributeSet a) {
341342 needLineBreak = true ;
342343 str = str .substring (str .indexOf ('\n' ) + 1 ); // eat the line
343344 }
345+ /*
346+ while (queuedLineCount.get() > maxLineCount) {
347+ Console.systemOut("too many: " + queuedLineCount);
348+ ElementSpec elem = elements.remove();
349+ if (elem.getType() == ElementSpec.EndTagType) {
350+ queuedLineCount.decrementAndGet();
351+ }
352+ }
353+ */
354+ }
355+ if (elements .size () > 1000 ) {
356+ insertAll ();
344357 }
345358 }
346359
347360 /** insert the buffered strings */
348- public synchronized void insertAll () {
349- ElementSpec [] elementArray = new ElementSpec [elements .size ()];
350- elements .toArray (elementArray );
361+ public void insertAll () {
362+ /*
363+ // each line is ~3 elements
364+ int tooMany = elements.size() - maxLineCount*3;
365+ if (tooMany > 0) {
366+ try {
367+ remove(0, getLength()); // clear the document first
368+ } catch (BadLocationException ble) {
369+ ble.printStackTrace();
370+ }
371+ Console.systemOut("skipping " + elements.size());
372+ for (int i = 0; i < tooMany; i++) {
373+ elements.remove();
374+ }
375+ }
376+ */
377+ ElementSpec [] elementArray = elements .toArray (new ElementSpec [0 ]);
351378
352379 try {
380+ /*
353381 // check how many lines have been used so far
354382 // if too many, shave off a few lines from the beginning
355383 Element element = super.getDefaultRootElement();
@@ -366,13 +394,42 @@ public synchronized void insertAll() {
366394 // remove to the end of the 200th line
367395 super.remove(0, endOffset);
368396 }
369- super .insert (super .getLength (), elementArray );
397+ */
398+ synchronized (insertLock ) {
399+ checkLength ();
400+ insert (getLength (), elementArray );
401+ checkLength ();
402+ }
370403
371404 } catch (BadLocationException e ) {
372405 // ignore the error otherwise this will cause an infinite loop
373406 // maybe not a good idea in the long run?
374407 }
375408 elements .clear ();
376- hasAppendage = false ;
409+ // hasAppendage = false;
410+ }
411+
412+ private void checkLength () throws BadLocationException {
413+ // set a limit on the number of characters in the console
414+ int docLength = getLength ();
415+ if (docLength > maxCharCount ) {
416+ remove (0 , docLength - maxCharCount );
417+ }
418+ // check how many lines have been used so far
419+ // if too many, shave off a few lines from the beginning
420+ Element element = super .getDefaultRootElement ();
421+ int lineCount = element .getElementCount ();
422+ int overage = lineCount - maxLineCount ;
423+ if (overage > 0 ) {
424+ // if 1200 lines, and 1000 lines is max,
425+ // find the position of the end of the 200th line
426+ //systemOut.println("overage is " + overage);
427+ Element lineElement = element .getElement (overage );
428+ if (lineElement != null ) {
429+ int endOffset = lineElement .getEndOffset ();
430+ // remove to the end of the 200th line
431+ super .remove (0 , endOffset );
432+ }
433+ }
377434 }
378435}
0 commit comments