1   /*
2    *  LogArea.java
3    *
4    *  Copyright (c) 1998-2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Cristian URSU, 26/03/2001
12   *
13   *  $Id: LogArea.java,v 1.21 2001/11/15 14:21:14 valyt Exp $
14   *
15   */
16  
17  package gate.gui;
18  
19  import javax.swing.*;
20  import javax.swing.text.*;
21  
22  import java.awt.*;
23  import java.awt.event.*;
24  import java.io.*;
25  
26  import gate.util.*;
27  import gate.swing.*;
28  
29  /**
30    * This class is used to log all messages from GATE. When an object of this
31    * class is created, it redirects the output of {@link gate.util.Out} &
32    * {@link gate.util.Err}.
33    * The output from Err is written with <font color="red">red</font> and the
34    * one from Out is written in <b>black</b>.
35    */
36  public class LogArea extends XJTextPane {
37  
38    /** Field needed in inner classes*/
39    protected LogArea thisLogArea = null;
40  
41    /** The popup menu with various actions*/
42    protected JPopupMenu popup = null;
43  
44    /** The original printstream on System.out */
45    protected PrintStream originalOut;
46  
47    /** The original printstream on System.err */
48    protected PrintStream originalErr;
49    /** This fields defines the Select all behaviour*/
50    protected SelectAllAction selectAllAction = null;
51  
52    /** This fields defines the copy  behaviour*/
53    protected CopyAction copyAction = null;
54  
55    /** This fields defines the clear all  behaviour*/
56    protected ClearAllAction clearAllAction = null;
57  
58    /** Constructs a LogArea object and captures the output from Err and Out. The
59      * output from System.out & System.err is not captured.
60      */
61    public LogArea(){
62      thisLogArea = this;
63      this.setEditable(false);
64  
65      LogAreaOutputStream err = new LogAreaOutputStream(true);
66      LogAreaOutputStream out = new LogAreaOutputStream(false);
67  
68      // Redirecting Err
69      Err.setPrintWriter(new PrintWriter(err,true));
70      // Redirecting Out
71      Out.setPrintWriter(new PrintWriter(out,true));
72  
73      // Redirecting System.out
74      originalOut = System.out;
75      System.setOut(new PrintStream(out,true));
76      // Redirecting System.err
77      originalErr = System.err;
78      System.setErr(new PrintStream(err,true));
79      popup = new JPopupMenu();
80      selectAllAction = new SelectAllAction();
81      copyAction = new CopyAction();
82      clearAllAction = new ClearAllAction();
83  
84      popup.add(selectAllAction);
85      popup.add(copyAction);
86      popup.addSeparator();
87      popup.add(clearAllAction);
88      initListeners();
89    }// LogArea
90  
91    /** Init all listeners for this object*/
92    public void initListeners(){
93      super.initListeners();
94      this.addMouseListener(new MouseAdapter(){
95        public void mouseClicked(MouseEvent e){
96          if(SwingUtilities.isRightMouseButton(e)){
97            popup.show(thisLogArea, e.getPoint().x, e.getPoint().y);
98          }//End if
99        }// end mouseClicked()
100     });// End addMouseListener();
101   }
102 
103   /** Returns the original printstream on System.err */
104   public PrintStream getOriginalErr() {
105     return originalErr;
106   }
107 
108   /** Returns the original printstream on System.out */
109   public PrintStream getOriginalOut() {
110     return originalOut;
111   }// initListeners();
112 
113   /** Inner class that defines the behaviour of SelectAll action.*/
114   protected class SelectAllAction extends AbstractAction{
115     public SelectAllAction(){
116       super("Select all");
117     }// SelectAll
118     public void actionPerformed(ActionEvent e){
119       thisLogArea.selectAll();
120     }// actionPerformed();
121   }// End class SelectAllAction
122 
123   /** Inner class that defines the behaviour of copy action.*/
124   protected class CopyAction extends AbstractAction{
125     public CopyAction(){
126       super("Copy");
127     }// CopyAction
128     public void actionPerformed(ActionEvent e){
129       thisLogArea.copy();
130     }// actionPerformed();
131   }// End class CopyAction
132 
133   /**
134    * A runnable that adds a bit of text to the area; needed so we can write
135    * from the Swing thread.
136    */
137   protected class SwingWriter implements Runnable{
138     SwingWriter(String text, Style style){
139       this.text = text;
140       this.style = style;
141     }
142 
143     public void run(){
144       try{
145         if(getDocument().getLength() > 0){
146           Rectangle place = modelToView(getDocument().getLength() - 1);
147           if(place != null) scrollRectToVisible(place);
148         }
149         getDocument().insertString(getDocument().getLength(), text, style);
150       } catch(BadLocationException e){
151           e.printStackTrace(System.err);
152       }// End try
153     }
154     String text;
155     Style style;
156   }
157 
158   /** Inner class that defines the behaviour of clear all action.*/
159   protected class ClearAllAction extends AbstractAction{
160     public ClearAllAction(){
161       super("Clear all");
162     }// ClearAllAction
163     public void actionPerformed(ActionEvent e){
164       try{
165         thisLogArea.getDocument().remove(0,thisLogArea.getDocument().getLength());
166       } catch (BadLocationException e1){
167         e1.printStackTrace(Err.getPrintWriter());
168       }// End try
169     }// actionPerformed();
170   }// End class ClearAllAction
171 
172   /** Inner class that defines the behaviour of an OutputStream that writes to
173    *  the LogArea.
174    */
175   class LogAreaOutputStream extends OutputStream{
176     /** This field dictates the style on how to write */
177     private boolean isErr = false;
178     /** Char style*/
179     private Style style = null;
180 
181     /** Constructs an Out or Err LogAreaOutputStream*/
182     public LogAreaOutputStream(boolean anIsErr){
183       isErr = anIsErr;
184       if (isErr){
185         style = addStyle("error", getStyle("default"));
186         StyleConstants.setForeground(style, Color.red);
187       }else {
188         style = addStyle("out",getStyle("default"));
189         StyleConstants.setForeground(style, Color.black);
190       }// End if
191     }// LogAreaOutputStream
192 
193     /** Writes an int which must be a the code of a char, into the LogArea,
194      *  using the style specified in constructor. The int is downcast to a byte.
195      */
196     public void write(int charCode){
197       // charCode int must be a char. Let us be sure of that
198       charCode &= 0x000000FF;
199       // Convert the byte to a char before put it into the log area
200       char c = (char)charCode;
201       // Insert it in the log Area
202       SwingUtilities.invokeLater(new SwingWriter(String.valueOf(c), style));
203     }// write(int charCode)
204 
205     /** Writes an array of bytes into the LogArea,
206      *  using the style specified in constructor.
207      */
208     public void write(byte[] data, int offset, int length){
209       // Insert the string to the log area
210       SwingUtilities.invokeLater(new SwingWriter(new String(data,offset,length),
211                                                  style));
212     }// write(byte[] data, int offset, int length)
213   }////End class LogAreaOutputStream
214 }//End class LogArea