57d563b5f9fab8f067b31e08d05545fc976f4207
[jalview.git] / src / jalview / gui / Console.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4.1)
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.io.*;
22 import java.awt.*;
23 import java.awt.event.*;
24 import javax.swing.*;
25
26 import org.apache.log4j.SimpleLayout;
27
28 /**
29  * Simple Jalview Java Console. Version 1 - allows viewing of console output after desktop is created.
30  * Acquired with thanks from RJHM's site http://www.comweb.nl/java/Console/Console.html
31  *  A simple Java Console for your application (Swing version)
32  * Requires Java 1.1.5 or higher
33  * Disclaimer the use of this source is at your own risk. 
34  * Permision to use and distribute into your own applications
35  * RJHM van den Bergh , rvdb@comweb.nl
36  */
37
38 public class Console extends WindowAdapter implements WindowListener,
39         ActionListener, Runnable
40 {
41   private JFrame frame;
42
43   private JTextArea textArea;
44
45   private Thread reader;
46
47   private Thread reader2;
48
49   private boolean quit;
50
51   private final PipedInputStream pin = new PipedInputStream();
52
53   private final PipedInputStream pin2 = new PipedInputStream();
54
55
56   Thread errorThrower; // just for testing (Throws an Exception at this Console
57   // are we attached to some parent Desktop
58   Desktop parent = null;
59   public Console()
60   {
61     // create all components and add them
62     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
63     frame = initFrame("Java Console", screenSize.width / 2,
64             screenSize.height / 2, -1, -1);
65     initConsole(true);
66   }
67
68   private void initConsole(boolean visible)
69   {
70     // CutAndPasteTransfer cpt = new CutAndPasteTransfer();
71     //textArea = cpt.getTextArea();
72     textArea = new JTextArea();
73     textArea.setEditable(false);
74     JButton button = new JButton("clear");
75
76     // frame = cpt;
77     frame.getContentPane().setLayout(new BorderLayout());
78     frame.getContentPane().add(new JScrollPane(textArea),
79             BorderLayout.CENTER);
80     frame.getContentPane().add(button, BorderLayout.SOUTH);
81     frame.setVisible(visible);
82
83     frame.addWindowListener(this);
84     button.addActionListener(this);
85
86     try
87     {
88       PipedOutputStream pout = new PipedOutputStream(this.pin);
89       System.setOut(new PrintStream(pout, true));
90     } catch (java.io.IOException io)
91     {
92       textArea.append("Couldn't redirect STDOUT to this console\n"
93               + io.getMessage());
94     } catch (SecurityException se)
95     {
96       textArea.append("Couldn't redirect STDOUT to this console\n"
97               + se.getMessage());
98     }
99
100     try
101     {
102       PipedOutputStream pout2 = new PipedOutputStream(this.pin2);
103       System.setErr(new PrintStream(pout2, true));
104     } catch (java.io.IOException io)
105     {
106       textArea.append("Couldn't redirect STDERR to this console\n"
107               + io.getMessage());
108     } catch (SecurityException se)
109     {
110       textArea.append("Couldn't redirect STDERR to this console\n"
111               + se.getMessage());
112     }
113
114     quit = false; // signals the Threads that they should exit
115
116     // Starting two seperate threads to read from the PipedInputStreams
117     //
118     reader = new Thread(this);
119     reader.setDaemon(true);
120     reader.start();
121     //
122     reader2 = new Thread(this);
123     reader2.setDaemon(true);
124     reader2.start();
125   }
126   public void test() {
127     // testing part
128     // you may omit this part for your application
129     // 
130     
131     System.out.println("Hello World 2");
132     System.out.println("All fonts available to Graphic2D:\n");
133     GraphicsEnvironment ge = GraphicsEnvironment
134             .getLocalGraphicsEnvironment();
135     String[] fontNames = ge.getAvailableFontFamilyNames();
136     for (int n = 0; n < fontNames.length; n++)
137       System.out.println(fontNames[n]);
138     // Testing part: simple an error thrown anywhere in this JVM will be printed
139     // on the Console
140     // We do it with a seperate Thread becasue we don't wan't to break a Thread
141     // used by the Console.
142     System.out.println("\nLets throw an error on this console");
143     errorThrower = new Thread(this);
144     errorThrower.setDaemon(true);
145     errorThrower.start();
146   }
147
148   private JFrame initFrame(String string, int i, int j, int x, int y)
149   {
150     JFrame frame = new JFrame(string);
151     frame.setName(string);
152     if (x==-1)
153       x = (int) (i / 2);
154     if (y==-1)
155       y = (int) (j / 2);
156     frame.setBounds(x, y, i, j);
157     return frame;
158   }
159
160   /**
161    * attach a console to the desktop - the desktop will open it if requested.
162    * 
163    * @param desktop
164    */
165   public Console(Desktop desktop)
166   {
167     parent = desktop;
168     // window name - get x,y,width, height possibly scaled
169     Rectangle bounds = desktop.getLastKnownDimensions("JAVA_CONSOLE_");
170     if (bounds==null)
171     {
172     frame = initFrame("Jalview Java Console", desktop.getWidth() / 2,
173             desktop.getHeight() / 4,desktop.getX(),desktop.getY());
174     } else {
175       frame = initFrame("Jalview Java Console", bounds.width, bounds.height, bounds.x, bounds.y);
176     }
177     // desktop.add(frame);
178     initConsole(false);
179     JalviewAppender jappender = new JalviewAppender();
180     jappender.setLayout(new SimpleLayout());
181     jappender.setTextArea(textArea);
182     org.apache.log4j.Logger.getRootLogger().addAppender(jappender);
183   }
184
185   public synchronized void stopConsole()
186   {
187     quit = true;
188     this.notifyAll(); // stop all threads
189     try
190     {
191       reader.join(10);
192       pin.close();
193     } catch (Exception e)
194     {
195     }
196     try
197     {
198       reader2.join(10);
199       pin2.close();
200     } catch (Exception e)
201     {
202     }
203 //    System.exit(0);
204   }
205
206   public synchronized void windowClosed(WindowEvent evt)
207   {
208     frame.setVisible(false);
209     if (parent == null)
210     {
211
212       stopConsole();
213     } else {
214       parent.showConsole(false);
215     }
216   }
217
218   public synchronized void windowClosing(WindowEvent evt)
219   {
220     frame.setVisible(false); // default behaviour of JFrame
221 //    frame.dispose();
222   }
223
224   public synchronized void actionPerformed(ActionEvent evt)
225   {
226     textArea.setText("");
227   }
228
229   public synchronized void run()
230   {
231     try
232     {
233       while (Thread.currentThread() == reader)
234       {
235         try
236         {
237           this.wait(100);
238         } catch (InterruptedException ie)
239         {
240         }
241         if (pin.available() != 0)
242         {
243           String input = this.readLine(pin);
244           textArea.append(input);
245         }
246         if (quit)
247           return;
248       }
249
250       while (Thread.currentThread() == reader2)
251       {
252         try
253         {
254           this.wait(100);
255         } catch (InterruptedException ie)
256         {
257         }
258         if (pin2.available() != 0)
259         {
260           String input = this.readLine(pin2);
261           textArea.append(input);
262         }
263         if (quit)
264           return;
265       }
266     } catch (Exception e)
267     {
268       textArea.append("\nConsole reports an Internal error.");
269       textArea.append("The error is: " + e);
270     }
271
272     // just for testing (Throw a Nullpointer after 1 second)
273     if (Thread.currentThread() == errorThrower)
274     {
275       try
276       {
277         this.wait(1000);
278       } catch (InterruptedException ie)
279       {
280       }
281       throw new NullPointerException(
282               "Application test: throwing an NullPointerException It should arrive at the console");
283     }
284
285   }
286
287   public synchronized String readLine(PipedInputStream in)
288           throws IOException
289   {
290     String input = "";
291     do
292     {
293       int available = in.available();
294       if (available == 0)
295         break;
296       byte b[] = new byte[available];
297       in.read(b);
298       input = input + new String(b, 0, b.length);
299     } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
300     return input;
301   }
302
303   public static void main(String[] arg)
304   {
305     new Console().test(); // create console with not reference
306     
307   }
308
309   public void setVisible(boolean selected)
310   {
311     frame.setVisible(selected);
312     if (selected == true)
313     {
314       frame.toFront();
315     }    
316   }
317
318   public Rectangle getBounds()
319   {
320     if (frame!=null)
321     {
322       return frame.getBounds();
323     }
324     return null;
325   }
326 }