From 17c8e30466e7a52708ed95465151dd254617a7e4 Mon Sep 17 00:00:00 2001 From: jprocter Date: Tue, 13 Oct 2009 15:22:19 +0000 Subject: [PATCH] prototype Java log window and sticky configuration --- src/jalview/gui/Console.java | 326 ++++++++++++++++++++++++++++++++++ src/jalview/gui/JalviewAppender.java | 39 ++++ src/jalview/jbgui/GDesktop.java | 17 ++ 3 files changed, 382 insertions(+) create mode 100644 src/jalview/gui/Console.java create mode 100644 src/jalview/gui/JalviewAppender.java diff --git a/src/jalview/gui/Console.java b/src/jalview/gui/Console.java new file mode 100644 index 0000000..57d563b --- /dev/null +++ b/src/jalview/gui/Console.java @@ -0,0 +1,326 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4.1) + * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +package jalview.gui; + +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import org.apache.log4j.SimpleLayout; + +/** + * Simple Jalview Java Console. Version 1 - allows viewing of console output after desktop is created. + * Acquired with thanks from RJHM's site http://www.comweb.nl/java/Console/Console.html + * A simple Java Console for your application (Swing version) + * Requires Java 1.1.5 or higher + * Disclaimer the use of this source is at your own risk. + * Permision to use and distribute into your own applications + * RJHM van den Bergh , rvdb@comweb.nl + */ + +public class Console extends WindowAdapter implements WindowListener, + ActionListener, Runnable +{ + private JFrame frame; + + private JTextArea textArea; + + private Thread reader; + + private Thread reader2; + + private boolean quit; + + private final PipedInputStream pin = new PipedInputStream(); + + private final PipedInputStream pin2 = new PipedInputStream(); + + + Thread errorThrower; // just for testing (Throws an Exception at this Console + // are we attached to some parent Desktop + Desktop parent = null; + public Console() + { + // create all components and add them + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + frame = initFrame("Java Console", screenSize.width / 2, + screenSize.height / 2, -1, -1); + initConsole(true); + } + + private void initConsole(boolean visible) + { + // CutAndPasteTransfer cpt = new CutAndPasteTransfer(); + //textArea = cpt.getTextArea(); + textArea = new JTextArea(); + textArea.setEditable(false); + JButton button = new JButton("clear"); + + // frame = cpt; + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(new JScrollPane(textArea), + BorderLayout.CENTER); + frame.getContentPane().add(button, BorderLayout.SOUTH); + frame.setVisible(visible); + + frame.addWindowListener(this); + button.addActionListener(this); + + try + { + PipedOutputStream pout = new PipedOutputStream(this.pin); + System.setOut(new PrintStream(pout, true)); + } catch (java.io.IOException io) + { + textArea.append("Couldn't redirect STDOUT to this console\n" + + io.getMessage()); + } catch (SecurityException se) + { + textArea.append("Couldn't redirect STDOUT to this console\n" + + se.getMessage()); + } + + try + { + PipedOutputStream pout2 = new PipedOutputStream(this.pin2); + System.setErr(new PrintStream(pout2, true)); + } catch (java.io.IOException io) + { + textArea.append("Couldn't redirect STDERR to this console\n" + + io.getMessage()); + } catch (SecurityException se) + { + textArea.append("Couldn't redirect STDERR to this console\n" + + se.getMessage()); + } + + quit = false; // signals the Threads that they should exit + + // Starting two seperate threads to read from the PipedInputStreams + // + reader = new Thread(this); + reader.setDaemon(true); + reader.start(); + // + reader2 = new Thread(this); + reader2.setDaemon(true); + reader2.start(); + } + public void test() { + // testing part + // you may omit this part for your application + // + + System.out.println("Hello World 2"); + System.out.println("All fonts available to Graphic2D:\n"); + GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + String[] fontNames = ge.getAvailableFontFamilyNames(); + for (int n = 0; n < fontNames.length; n++) + System.out.println(fontNames[n]); + // Testing part: simple an error thrown anywhere in this JVM will be printed + // on the Console + // We do it with a seperate Thread becasue we don't wan't to break a Thread + // used by the Console. + System.out.println("\nLets throw an error on this console"); + errorThrower = new Thread(this); + errorThrower.setDaemon(true); + errorThrower.start(); + } + + private JFrame initFrame(String string, int i, int j, int x, int y) + { + JFrame frame = new JFrame(string); + frame.setName(string); + if (x==-1) + x = (int) (i / 2); + if (y==-1) + y = (int) (j / 2); + frame.setBounds(x, y, i, j); + return frame; + } + + /** + * attach a console to the desktop - the desktop will open it if requested. + * + * @param desktop + */ + public Console(Desktop desktop) + { + parent = desktop; + // window name - get x,y,width, height possibly scaled + Rectangle bounds = desktop.getLastKnownDimensions("JAVA_CONSOLE_"); + if (bounds==null) + { + frame = initFrame("Jalview Java Console", desktop.getWidth() / 2, + desktop.getHeight() / 4,desktop.getX(),desktop.getY()); + } else { + frame = initFrame("Jalview Java Console", bounds.width, bounds.height, bounds.x, bounds.y); + } + // desktop.add(frame); + initConsole(false); + JalviewAppender jappender = new JalviewAppender(); + jappender.setLayout(new SimpleLayout()); + jappender.setTextArea(textArea); + org.apache.log4j.Logger.getRootLogger().addAppender(jappender); + } + + public synchronized void stopConsole() + { + quit = true; + this.notifyAll(); // stop all threads + try + { + reader.join(10); + pin.close(); + } catch (Exception e) + { + } + try + { + reader2.join(10); + pin2.close(); + } catch (Exception e) + { + } +// System.exit(0); + } + + public synchronized void windowClosed(WindowEvent evt) + { + frame.setVisible(false); + if (parent == null) + { + + stopConsole(); + } else { + parent.showConsole(false); + } + } + + public synchronized void windowClosing(WindowEvent evt) + { + frame.setVisible(false); // default behaviour of JFrame +// frame.dispose(); + } + + public synchronized void actionPerformed(ActionEvent evt) + { + textArea.setText(""); + } + + public synchronized void run() + { + try + { + while (Thread.currentThread() == reader) + { + try + { + this.wait(100); + } catch (InterruptedException ie) + { + } + if (pin.available() != 0) + { + String input = this.readLine(pin); + textArea.append(input); + } + if (quit) + return; + } + + while (Thread.currentThread() == reader2) + { + try + { + this.wait(100); + } catch (InterruptedException ie) + { + } + if (pin2.available() != 0) + { + String input = this.readLine(pin2); + textArea.append(input); + } + if (quit) + return; + } + } catch (Exception e) + { + textArea.append("\nConsole reports an Internal error."); + textArea.append("The error is: " + e); + } + + // just for testing (Throw a Nullpointer after 1 second) + if (Thread.currentThread() == errorThrower) + { + try + { + this.wait(1000); + } catch (InterruptedException ie) + { + } + throw new NullPointerException( + "Application test: throwing an NullPointerException It should arrive at the console"); + } + + } + + public synchronized String readLine(PipedInputStream in) + throws IOException + { + String input = ""; + do + { + int available = in.available(); + if (available == 0) + break; + byte b[] = new byte[available]; + in.read(b); + input = input + new String(b, 0, b.length); + } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit); + return input; + } + + public static void main(String[] arg) + { + new Console().test(); // create console with not reference + + } + + public void setVisible(boolean selected) + { + frame.setVisible(selected); + if (selected == true) + { + frame.toFront(); + } + } + + public Rectangle getBounds() + { + if (frame!=null) + { + return frame.getBounds(); + } + return null; + } +} diff --git a/src/jalview/gui/JalviewAppender.java b/src/jalview/gui/JalviewAppender.java new file mode 100644 index 0000000..8d3f990 --- /dev/null +++ b/src/jalview/gui/JalviewAppender.java @@ -0,0 +1,39 @@ +package jalview.gui; + +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import org.apache.log4j.WriterAppender; +import org.apache.log4j.spi.LoggingEvent; + +/** + * From http://textareaappender.zcage.com/ + * the means to capture the logs, too. + * Simple example of creating a Log4j appender that will + * write to a JTextArea. + */ +public class JalviewAppender extends WriterAppender { + + static private JTextArea jTextArea = null; + + /** Set the target JTextArea for the logging information to appear. */ + static public void setTextArea(JTextArea jTextArea) { + JalviewAppender.jTextArea = jTextArea; + } + /** + * Format and then append the loggingEvent to the stored + * JTextArea. + */ + public void append(LoggingEvent loggingEvent) { + final String message = this.layout.format(loggingEvent); + + // Append formatted message to textarea using the Swing Thread. + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (jTextArea!=null) { + jTextArea.append(message); + } + } + }); + } +} \ No newline at end of file diff --git a/src/jalview/jbgui/GDesktop.java b/src/jalview/jbgui/GDesktop.java index 5ff13af..773267d 100755 --- a/src/jalview/jbgui/GDesktop.java +++ b/src/jalview/jbgui/GDesktop.java @@ -87,6 +87,8 @@ public class GDesktop extends JFrame JMenuItem garbageCollect = new JMenuItem(); + protected JCheckBoxMenuItem showConsole = new JCheckBoxMenuItem(); + /** * Creates a new GDesktop object. */ @@ -297,6 +299,14 @@ public class GDesktop extends JFrame showMemusage_actionPerformed(e); } }); + showConsole.setText("Show Java Console"); + showConsole.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + showConsole_actionPerformed(e); + } + }); desktopMenubar.add(FileMenu); desktopMenubar.add(toolsMenu); VamsasMenu.setVisible(false); @@ -320,6 +330,7 @@ public class GDesktop extends JFrame VamsasMenu.add(vamsasStop); toolsMenu.add(preferences); toolsMenu.add(showMemusage); + toolsMenu.add(showConsole); toolsMenu.add(garbageCollect); inputMenu.add(inputLocalFileMenuItem); inputMenu.add(inputURLMenuItem); @@ -331,6 +342,12 @@ public class GDesktop extends JFrame // inputMenu.add(vamsasLoad); } + protected void showConsole_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + protected void showMemusage_actionPerformed(ActionEvent e) { // TODO Auto-generated method stub -- 1.7.10.2