Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: edu/emory/mathcs/util/swing/JConsole.java


1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is the Emory Utilities.
15   *
16   * The Initial Developer of the Original Code is
17   * The Distributed Computing Laboratory, Emory University.
18   * Portions created by the Initial Developer are Copyright (C) 2002
19   * the Initial Developer. All Rights Reserved.
20   *
21   * Alternatively, the contents of this file may be used under the terms of
22   * either the GNU General Public License Version 2 or later (the "GPL"), or
23   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
24   * in which case the provisions of the GPL or the LGPL are applicable instead
25   * of those above. If you wish to allow use of your version of this file only
26   * under the terms of either the GPL or the LGPL, and not to allow others to
27   * use your version of this file under the terms of the MPL, indicate your
28   * decision by deleting the provisions above and replace them with the notice
29   * and other provisions required by the GPL or the LGPL. If you do not delete
30   * the provisions above, a recipient may use your version of this file under
31   * the terms of any one of the MPL, the GPL or the LGPL.
32   *
33   * ***** END LICENSE BLOCK ***** */
34  
35  package  edu.emory.mathcs.util.swing;
36  
37  import java.awt.Component;
38  import java.awt.Font;
39  import java.awt.Color;
40  import java.awt.Insets;
41  import java.awt.event.*;
42  import java.beans.PropertyChangeEvent;
43  import java.beans.PropertyChangeListener;
44  import java.io.*;
45  import java.util.Vector;
46  import java.awt.Cursor;
47  import javax.swing.text.*;
48  import javax.swing.*;
49  import javax.swing.JFrame;
50  
51  // Things that are not in the core packages
52  
53  //import bsh.util.NameCompletion;
54  
55  /**
56      A JFC/Swing based console for the BeanShell desktop.
57      This is a descendant of the old AWTConsole.
58  
59      Improvements by: Mark Donszelmann <Mark.Donszelmann@cern.ch>
60          including Cut & Paste
61  
62      Improvements by: Daniel Leuck
63          including Color and Image support, key press bug workaround
64  */
65  public class JConsole extends JScrollPane
66      implements /*GUIConsoleInterface,*/ Runnable, KeyListener,
67      MouseListener, ActionListener, PropertyChangeListener
68  {
69      private final static String  CUT = "Cut";
70      private final static String  COPY = "Copy";
71      private final static String  PASTE =  "Paste";
72  
73      private  OutputStream outPipe;
74      private  InputStream inPipe;
75      private  InputStream in;
76      private  PrintStream out;
77      private  InputStream errPipe;
78      private  InputStream err;
79  
80      public InputStream getInputStream() { return in; }
81      public Reader getIn() { return new InputStreamReader(in); }
82      public PrintStream getOut() { return out;  }
83      public PrintStream getErr() { return out;  }
84  
85      private int  cmdStart = 0;
86      private  Vector history = new Vector();
87      private  String startedLine;
88      private  int histLine = 0;
89  
90      private boolean stopListening=false;
91  
92      private JPopupMenu menu;
93      private JTextPane text;
94      private DefaultStyledDocument doc;
95  
96      //NameCompletion nameCompletion;
97      final int SHOW_AMBIG_MAX = 10;
98  
99      // hack to prevent key repeat for some reason?
100     private boolean gotUp = true;
101 
102     private JConsole() {
103         this(null, null, null);
104     }
105 
106     public JConsole( InputStream cin, OutputStream cout, InputStream err)
107     {
108         super();
109 
110         // Special TextPane which catches for cut and paste, both L&F keys and
111         // programmatic  behaviour
112         text = new JTextPane( doc=new DefaultStyledDocument() )
113             {
114                 public void  cut() {
115                     if (text.getCaretPosition() < cmdStart)  {
116                         super.copy();
117                     } else {
118                         super.cut();
119                     }
120                 }
121 
122                 public void  paste()  {
123                     forceCaretMoveToEnd();
124                     super.paste();
125                 }
126             };
127 
128         Font font = new  Font("Monospaced",Font.PLAIN,12);
129         text.setText("");
130         text.setFont( font );
131         text.setMargin(  new Insets(7,5,7,5) );
132         text.addKeyListener(this);
133         setViewportView(text);
134 
135         // create popup  menu
136         menu = new JPopupMenu("JConsole  Menu");
137         menu.add(new JMenuItem(CUT)).addActionListener(this);
138         menu.add(new JMenuItem(COPY)).addActionListener(this);
139         menu.add(new JMenuItem(PASTE)).addActionListener(this);
140 
141         text.addMouseListener(this);
142 
143         // make  sure popup menu  follows  Look & Feel
144         UIManager.addPropertyChangeListener(this);
145 
146         outPipe  = cout;
147         if ( outPipe ==  null ) {
148             outPipe  = new PipedOutputStream();
149             try {
150                 in = new PipedInputStream((PipedOutputStream)outPipe);
151             } catch  ( IOException e  ) {
152                 print("Console internal  error (1)...", Color.red);
153             }
154         }
155 
156         inPipe = cin;
157         if ( inPipe == null ) {
158             PipedOutputStream pout = new PipedOutputStream();
159             out = new PrintStream( pout );
160             try {
161                 inPipe = new BlockingPipedInputStream(pout);
162             } catch ( IOException e ) { print("Console internal error: "+e); }
163         }
164         // Start the inpipe watcher
165         new Thread( this ).start();
166 
167         errPipe= err;
168         if ( errPipe != null )
169             new Thread(new ErrPipeWatcher()).start();
170 
171         requestFocus();
172     }
173 
174     public void keyPressed(  KeyEvent e ) {
175         type( e );
176         gotUp=false;
177     }
178 
179     public void keyTyped(KeyEvent e) {
180         type( e );
181     }
182 
183     public void  keyReleased(KeyEvent e)  {
184         gotUp=true;
185         type( e  );
186     }
187 
188     private synchronized void type( KeyEvent e ) {
189         switch ( e.getKeyCode()  ) {
190 
191             case ( KeyEvent.VK_ENTER ):
192                 if (e.getID() == KeyEvent.KEY_PRESSED) {
193                     if (gotUp) {
194                         enter();
195                         resetCommandStart();
196                         text.setCaretPosition(cmdStart);
197                     }
198                 }
199                 e.consume();
200                 text.repaint();
201                 break;
202 
203             case ( KeyEvent.VK_UP ):
204                 if (e.getID() == KeyEvent.KEY_PRESSED) {
205                     historyUp();
206                 }
207                 e.consume();
208                 break;
209 
210             case ( KeyEvent.VK_DOWN  ):
211                 if (e.getID() == KeyEvent.KEY_PRESSED) {
212                     historyDown();
213                 }
214                 e.consume();
215                 break;
216 
217             case ( KeyEvent.VK_LEFT  ):
218             case ( KeyEvent.VK_BACK_SPACE ):
219             case ( KeyEvent.VK_DELETE ):
220                 if (text.getCaretPosition() <= cmdStart) {
221 // Why isn't this working? JDK1.3 ignores this consume...
222                     e.consume();
223                 }
224                 break;
225 
226             case ( KeyEvent.VK_RIGHT ):
227                 forceCaretMoveToStart();
228                 break;
229 
230             case ( KeyEvent.VK_HOME ):
231                 text.setCaretPosition(cmdStart);
232                 e.consume();
233                 break;
234 
235             case ( KeyEvent.VK_U ):  // clear line
236                 if ( (e.getModifiers() & InputEvent.CTRL_MASK) > 0 ) {
237                     replaceRange( "", cmdStart, text.getText().length());
238                     histLine = 0;
239                     e.consume();
240                 }
241                 break;
242 
243             case ( KeyEvent.VK_ALT ):
244             case ( KeyEvent.VK_CAPS_LOCK ):
245             case ( KeyEvent.VK_CONTROL ):
246             case ( KeyEvent.VK_META ):
247             case ( KeyEvent.VK_SHIFT ):
248             case ( KeyEvent.VK_PRINTSCREEN ):
249             case ( KeyEvent.VK_SCROLL_LOCK ):
250             case ( KeyEvent.VK_PAUSE ):
251             case ( KeyEvent.VK_INSERT ):
252             case ( KeyEvent.VK_F1):
253             case ( KeyEvent.VK_F2):
254             case ( KeyEvent.VK_F3):
255             case ( KeyEvent.VK_F4):
256             case ( KeyEvent.VK_F5):
257             case ( KeyEvent.VK_F6):
258             case ( KeyEvent.VK_F7):
259             case ( KeyEvent.VK_F8):
260             case ( KeyEvent.VK_F9):
261             case ( KeyEvent.VK_F10):
262             case ( KeyEvent.VK_F11):
263             case ( KeyEvent.VK_F12):
264             case ( KeyEvent.VK_ESCAPE ):
265 
266             // only  modifier pressed
267             break;
268 
269             // Control-C
270             case ( KeyEvent.VK_C ):
271                 if (text.getSelectedText() == null) {
272                     if (( (e.getModifiers() & InputEvent.CTRL_MASK) > 0  )
273                     && (e.getID() == KeyEvent.KEY_PRESSED))  {
274                         append("^C");
275                     }
276                     e.consume();
277                 }
278                 break;
279 
280             case ( KeyEvent.VK_TAB ):
281 //                if (e.getID() == KeyEvent.KEY_RELEASED) {
282 //                    String part = text.getText().substring( cmdStart );
283 //                    doCommandCompletion( part );
284 //                }
285                 e.consume();
286                 break;
287 
288             default:
289                 if (
290                     (e.getModifiers() &
291                     (InputEvent.CTRL_MASK
292                     | InputEvent.ALT_MASK | InputEvent.META_MASK)) == 0 )
293                 {
294                     // plain character
295                     forceCaretMoveToEnd();
296                 }
297                 break;
298         }
299     }
300 
301 //    void doCommandCompletion( String part ) {
302 //        if ( nameCompletion == null )
303 //            return;
304 //
305 //        int i=part.length()-1;
306 //
307 //        // Character.isJavaIdentifierPart()  How convenient for us!!
308 //        while (
309 //            i >= 0 &&
310 //                ( Character.isJavaIdentifierPart(part.charAt(i))
311 //                || part.charAt(i) == '.' )
312 //        )
313 //            i--;
314 //
315 //        part = part.substring(i+1);
316 //
317 //        if ( part.length() < 2 )  // reasonable completion length
318 //            return;
319 //
320 //        //System.out.println("completing part: "+part);
321 //
322 //        // no completion
323 //        String [] complete = nameCompletion.completeName(part);
324 //        if ( complete.length == 0 ) {
325 //            java.awt.Toolkit.getDefaultToolkit().beep();
326 //            return;
327 //        }
328 //
329 //        // Found one completion (possibly what we already have)
330 //        if ( complete.length == 1 && !complete.equals(part) ) {
331 //            String append = complete[0].substring(part.length());
332 //            append( append );
333 //            return;
334 //        }
335 //
336 //        // Found ambiguous, show (some of) them
337 //
338 //        String line = text.getText();
339 //        String command = line.substring( cmdStart );
340 //        // Find prompt
341 //        for(i=cmdStart; line.charAt(i) != '\n' && i > 0; i--);
342 //        String prompt = line.substring( i+1, cmdStart );
343 //
344 //        // Show ambiguous
345 //        StringBuffer sb = new StringBuffer("\n");
346 //        for( i=0; i<complete.length && i<SHOW_AMBIG_MAX; i++)
347 //            sb.append( complete[i] +"\n" );
348 //        if ( i == SHOW_AMBIG_MAX )
349 //            sb.append("...\n");
350 //
351 //        print( sb, Color.gray );
352 //        print( prompt ); // print resets command start
353 //        append( command ); // append does not reset command start
354 //    }
355 
356     private void resetCommandStart() {
357         cmdStart = text.getDocument().getLength();
358     }
359 
360     private  void append(String string) {
361         int slen = text.getText().length();
362         text.select(slen, slen);
363         text.replaceSelection(string);
364     }
365 
366     String replaceRange(Object s, int start, int  end) {
367         String st = s.toString();
368         text.select(start, end);
369         text.replaceSelection(st);
370         //text.repaint();
371         return st;
372     }
373 
374     private  void forceCaretMoveToEnd() {
375         if (text.getCaretPosition() < cmdStart)  {
376             // move caret first!
377             text.setCaretPosition(text.getText().length());
378         }
379         text.repaint();
380     }
381 
382     private  void forceCaretMoveToStart() {
383         if (text.getCaretPosition() < cmdStart)  {
384             // move caret first!
385         }
386         text.repaint();
387     }
388 
389 
390     private  void enter() {
391         String s = getCmd();
392 
393         if ( s.length()  == 0 )  // special hack  for empty return!
394             s = ";\n";
395         else {
396             history.addElement( s );
397             s = s +"\n";
398         }
399 
400         append("\n");
401         histLine = 0;
402         acceptLine( s );
403         text.repaint();
404     }
405 
406     private String getCmd() {
407         String s = "";
408         try {
409             s =  text.getText(cmdStart, text.getText().length() - cmdStart);
410         } catch  (BadLocationException e) {
411             // should not happen
412             System.out.println("Internal JConsole Error: "+e);
413         }
414         return s;
415     }
416 
417     private  void historyUp() {
418         if ( history.size() == 0 )
419             return;
420         if ( histLine == 0 )  // save current line
421             startedLine = getCmd();
422         if ( histLine <  history.size() ) {
423             histLine++;
424             showHistoryLine();
425         }
426     }
427     private  void historyDown() {
428         if ( histLine == 0 )
429             return;
430 
431         histLine--;
432         showHistoryLine();
433     }
434 
435     private  void showHistoryLine() {
436         String showline;
437         if ( histLine == 0 )
438             showline = startedLine;
439         else
440             showline = (String)history.elementAt( history.size() - histLine  );
441 
442         replaceRange( showline,  cmdStart, text.getText().length() );
443         text.setCaretPosition(text.getText().length());
444         text.repaint();
445     }
446 
447     private  void acceptLine( String  line ) {
448         if (outPipe == null )
449             print("Console internal  error: cannot output ...", Color.red);
450         else
451             try {
452                 outPipe.write( line.getBytes() );
453                 outPipe.flush();
454             } catch  ( IOException e  ) {
455                 outPipe  = null;
456                 throw new RuntimeException("Console pipe broken...");
457             }
458         //text.repaint();
459     }
460 
461     public void println(String string) {
462         print( string + "\n" );
463         text.repaint();
464     }
465 
466     public synchronized void print(String string) {
467         append( (string==null) ? "null" : string );
468         resetCommandStart();
469         text.setCaretPosition(cmdStart);
470     }
471 
472     /**
473       * Prints "\\n" (i.e. newline)
474       */
475 
476     public void println() {
477         print("\n");
478         text.repaint();
479     }
480 
481     public void error( String s ) {
482         print( s, Color.red );
483     }
484 
485     public void println(Object object) {
486         // ugly but  fast
487         print(new StringBuffer(
488             String.valueOf(object)).append("\n"));
489         text.repaint();
490     }
491 
492     public void println(Icon icon) {
493         print(icon);
494         println();
495         text.repaint();
496     }
497 
498     /**
499       * Prints all primitive integer values
500       * (i.e. byte,  short, int, and  long)
501     public void println(long l) {
502         println(String.valueOf(l));
503     }
504       */
505 
506     /**
507       * Prints the primitive type "double"
508     public void println(double d) {
509         println(String.valueOf(d));
510     }
511       */
512 
513     /**
514       * Prints the primitive type "float"
515       * (needed because of float->double
516       * coercion weirdness)
517     public void println(float f) {
518         println(String.valueOf(f));
519     }
520       */
521 
522     /*
523     public void println(boolean b) {
524         println((b ? "true" : "false"));
525     }
526 
527     public void println(char c) {
528         println(String.valueOf(c));
529     }
530     */
531 
532     public synchronized void print(Object object) {
533         append(String.valueOf(object));
534         resetCommandStart();
535         text.setCaretPosition(cmdStart);
536     }
537 
538     public synchronized void print(Icon icon) {
539         if (icon==null)
540             return;
541 
542         text.insertIcon(icon);
543         resetCommandStart();
544         text.setCaretPosition(cmdStart);
545     }
546 
547     /**
548       * Prints all primitive integer values
549       * (i.e. byte,  short, int, and  long)
550     public void print(long l) {
551         print(String.valueOf(l));
552     }
553       */
554 
555     /**
556       * Prints the primitive type "double"
557     public void print(double d) {
558     print(String.valueOf(d));
559     }
560       */
561 
562     /**
563       * Prints the primitive type "float"
564       * (needed because of float->double
565       * coercion weirdness)
566     public void print(float  f) {
567         print(String.valueOf(f));
568     }
569       */
570 
571     /*
572     public void print(boolean b) {
573         print(b  ? "true" : "false");
574     }
575 
576     public void print(char c) {
577         print(String.valueOf(c));
578     }
579     */
580 
581     public void print(Object s, Font font) {
582         print(s, font, null);
583     }
584 
585     public void print(Object s, Color color) {
586         print(s, null, color);
587     }
588     public void print(String s, Color color) {
589         print(s, null, color);
590     }
591 
592     public synchronized void print(Object s, Font font, Color color) {
593         AttributeSet old = getStyle();
594 
595         setStyle(font, color);
596         print(s);
597         setStyle(old, true);
598     }
599 
600     public synchronized void print(
601         Object s,
602         String fontFamilyName,
603         int  size,
604         Color color
605         ) {
606         AttributeSet old = getStyle();
607 
608         setStyle(fontFamilyName, size, color);
609         print(s);
610         setStyle(old, true);
611     }
612 
613     public synchronized void print(
614         Object s,
615         String fontFamilyName,
616         int  size,
617         Color color,
618         boolean bold,
619         boolean italic,
620         boolean underline
621         )
622     {
623 
624         AttributeSet old = getStyle();
625 
626         setStyle(fontFamilyName, size, color, bold,  italic,  underline);
627         print(s);
628         setStyle(old, true);
629     }
630 
631     public AttributeSet  setStyle(Font font) {
632         return setStyle(font, null);
633     }
634 
635     public AttributeSet  setStyle(Color color) {
636         return setStyle(null, color);
637     }
638 
639     public AttributeSet  setStyle( Font font, Color color)
640     {
641         if (font!=null)
642             return setStyle( font.getFamily(), font.getSize(), color,
643                 font.isBold(), font.isItalic(),
644                 StyleConstants.isUnderline(getStyle()) );
645         else
646             return setStyle(null,-1,color);
647     }
648 
649     public synchronized  AttributeSet setStyle (
650         String fontFamilyName, int  size, Color color)
651     {
652         MutableAttributeSet attr = new SimpleAttributeSet();
653         if (color!=null)
654             StyleConstants.setForeground(attr, color);
655         if (fontFamilyName!=null)
656             StyleConstants.setFontFamily(attr, fontFamilyName);
657         if (size!=-1)
658             StyleConstants.setFontSize(attr, size);
659 
660         setStyle(attr);
661 
662         return getStyle();
663     }
664 
665     public synchronized  AttributeSet setStyle(
666         String fontFamilyName,
667         int  size,
668         Color color,
669         boolean bold,
670         boolean italic,
671         boolean underline
672         )
673     {
674         MutableAttributeSet attr = new SimpleAttributeSet();
675         if (color!=null)
676             StyleConstants.setForeground(attr, color);
677         if (fontFamilyName!=null)
678             StyleConstants.setFontFamily(attr, fontFamilyName);
679         if (size!=-1)
680             StyleConstants.setFontSize(attr, size);
681         StyleConstants.setBold(attr, bold);
682         StyleConstants.setItalic(attr, italic);
683         StyleConstants.setUnderline(attr, underline);
684 
685         setStyle(attr);
686 
687         return getStyle();
688     }
689 
690     public void  setStyle(AttributeSet attributes) {
691         setStyle(attributes, false);
692     }
693 
694     public void  setStyle(AttributeSet attributes, boolean overWrite) {
695         text.setCharacterAttributes(attributes,  overWrite);
696     }
697 
698     public AttributeSet  getStyle() {
699         return text.getCharacterAttributes();
700     }
701 
702     public void setFont( Font font ) {
703         super.setFont( font );
704 
705         if ( text != null )
706             text.setFont( font );
707     }
708 
709     private  void inPipeWatcher() throws IOException  {
710         byte []  ba = new byte [256]; //  arbitrary blocking factor
711         int read; String s;
712         while (  (read =  inPipe.read(ba)) != -1  && !stopListening) {
713             print( s=new String(ba, 0, read) );
714             //text.repaint();
715         }
716 
717         println("Console: Input  closed...");
718     }
719 
720     class ErrPipeWatcher implements Runnable {
721         public void run() {
722             try {
723                 byte []  ba = new byte [256]; //  arbitrary blocking factor
724                 int read;
725                 while (  (read =  errPipe.read(ba)) != -1 && !stopListening) {
726                     print( new String(ba, 0, read), Color.red );
727                     //text.repaint();
728                 }
729 
730                 println("Console: Error input closed...");
731             }
732             catch (IOException e) {
733                 print("Console: I/O Error: "+e+"\n", Color.red);
734             }
735         }
736     }
737 
738     public void run() {
739         try {
740             inPipeWatcher();
741         } catch  ( IOException e  ) {
742             print("Console: I/O Error: "+e+"\n", Color.red);
743         }
744     }
745 
746     public String toString() {
747         return "BeanShell console";
748     }
749 
750     // MouseListener Interface
751     public void  mouseClicked(MouseEvent  event) {
752     }
753 
754     public void mousePressed(MouseEvent event) {
755         if (event.isPopupTrigger()) {
756             menu.show(
757                 (Component)event.getSource(), event.getX(), event.getY());
758         }
759     }
760 
761     public void  mouseReleased(MouseEvent event)  {
762         if (event.isPopupTrigger()) {
763             menu.show((Component)event.getSource(), event.getX(),
764             event.getY());
765         }
766         text.repaint();
767     }
768 
769     public void  mouseEntered(MouseEvent  event) { }
770 
771     public void  mouseExited(MouseEvent event) { }
772 
773     // property  change
774     public void  propertyChange(PropertyChangeEvent event) {
775         if (event.getPropertyName().equals("lookAndFeel")) {
776             SwingUtilities.updateComponentTreeUI(menu);
777         }
778     }
779 
780     // handle cut, copy  and paste
781     public void  actionPerformed(ActionEvent event) {
782         String cmd = event.getActionCommand();
783         if (cmd.equals(CUT)) {
784             text.cut();
785         } else if (cmd.equals(COPY)) {
786             text.copy();
787         } else if (cmd.equals(PASTE)) {
788             text.paste();
789         }
790     }
791 
792     /**
793         The overridden read method in this class will not throw "Broken pipe"
794         IOExceptions;  It will simply wait for new writers and data.
795         This is used by the JConsole internal read thread to allow writers
796         in different (and in particular ephemeral) threads to write to the pipe.
797 
798         It also checks a little more frequently than the original read().
799 
800         Warning: read() will not even error on a read to an explicitly closed
801         pipe (override closed to for that).
802     */
803     public static class BlockingPipedInputStream extends PipedInputStream
804     {
805         boolean closed;
806         public BlockingPipedInputStream( PipedOutputStream pout )
807             throws IOException
808         {
809             super(pout);
810         }
811         public synchronized int read() throws IOException {
812             if ( closed )
813                 throw new IOException("stream closed");
814 
815             while (super.in < 0) {  // While no data */
816                 notifyAll();  // Notify any writers to wake up
817                 try {
818                     wait(750);
819                 } catch ( InterruptedException e ) {
820                     throw new InterruptedIOException();
821                 }
822             }
823             // This is what the superclass does.
824             int ret = buffer[super.out++] & 0xFF;
825             if (super.out >= buffer.length)
826                 super.out = 0;
827             if (super.in == super.out)
828                 super.in = -1;  /* now empty */
829             return ret;
830         }
831         public void close() throws IOException {
832             closed = true;
833             super.close();
834         }
835     }
836 
837 //    public void setNameCompletion( NameCompletion nc ) {
838 //        this.nameCompletion = nc;
839 //    }
840 
841     public void setWaitFeedback( boolean on ) {
842         if ( on )
843             setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR) );
844         else
845             setCursor( Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR) );
846     }
847 
848 //    public static void main(String [] argsv) {
849 //        JFrame jfr=new JFrame();
850 //        jfr.getContentPane().add(new  JConsole(System.in,System.out, null));
851 //        jfr.pack();
852 //        jfr.setVisible(true);
853 //    }
854 
855     public void show(String title) {
856         show(null, title);
857     }
858 
859     public void show(Component parent, String title) {
860         console.setTitle(title);
861         console.setSize(400, 300);
862         console.getContentPane().add(this);
863         if (parent != null) {
864             console.setLocationRelativeTo(parent);
865         }
866         console.addWindowListener(new java.awt.event.WindowAdapter () {
867                 public void windowClosing(java.awt.event.WindowEvent e) {
868                     stopListening=true;
869                 }
870             }
871         );
872         console.setVisible(true);
873     }
874 
875     private final JFrame console = new JFrame();
876 
877     public void hide() {
878       console.setVisible(false);
879     }
880 }
881 
882