All Downloads are FREE. Search and download functionalities are using the official Maven repository.

weka.gui.LogWindow Maven / Gradle / Ivy

Go to download

The Waikato Environment for Knowledge Analysis (WEKA), a machine learning workbench. This version represents the developer version, the "bleeding edge" of development, you could say. New functionality gets added to this version.

There is a newer version: 3.9.6
Show newest version
/*
 *   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 3 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, see .
 */

/*
 * LogWindow.java
 * Copyright (C) 2005-2012 University of Waikato, Hamilton, New Zealand
 *
 */

package weka.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.PrintStream;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

import weka.core.Tee;
import weka.core.Utils;

/**
 * Frame that shows the output from stdout and stderr.
 * 
 * @author FracPete (fracpete at waikato dot ac dot nz)
 * @version $Revision: 10216 $
 */
public class LogWindow extends JFrame implements CaretListener, ChangeListener {

  /** for serialization */
  private static final long serialVersionUID = 5650947361381061112L;

  /** the name of the style for stdout */
  public final static String STYLE_STDOUT = "stdout";

  /** the name of the style for stderr */
  public final static String STYLE_STDERR = "stderr";

  /** the color of the style for stdout */
  public final static Color COLOR_STDOUT = Color.BLACK;

  /** the Color of the style for stderr */
  public final static Color COLOR_STDERR = Color.RED;

  /** whether we're debugging - enables output on stdout */
  public final static boolean DEBUG = false;

  /** whether the JTextPane has wordwrap or not */
  public boolean m_UseWordwrap = true;

  /** the output */
  protected JTextPane m_Output = new JTextPane();

  /** the clear button */
  protected JButton m_ButtonClear = new JButton("Clear");

  /** the close button */
  protected JButton m_ButtonClose = new JButton("Close");

  /** the current size */
  protected JLabel m_LabelCurrentSize = new JLabel("currently: 0");

  /** the spinner for the max number of chars */
  protected JSpinner m_SpinnerMaxSize = new JSpinner();

  /** whether to allow wordwrap or not */
  protected JCheckBox m_CheckBoxWordwrap = new JCheckBox("Use wordwrap");

  /** for redirecting stdout */
  protected static Tee m_TeeOut = null;

  /** for redirecting stderr */
  protected static Tee m_TeeErr = null;

  /**
   * inner class for printing to the window, is used instead of standard
   * System.out and System.err
   */
  protected class LogWindowPrintStream extends PrintStream {
    /** the parent */
    protected LogWindow m_Parent = null;

    /** the style of the printstream */
    protected String m_Style = null;

    /**
     * the constructor
     * 
     * @param parent the parent frame
     * @param stream the stream (used for constructor of superclass)
     * @param style the style name associated with this output
     */
    public LogWindowPrintStream(LogWindow parent, PrintStream stream,
      String style) {
      super(stream);

      m_Parent = parent;
      m_Style = style;
    }

    /**
     * flushes the printstream
     */
    @Override
    public synchronized void flush() {
      // ignored
    }

    /**
     * prints the given int
     */
    @Override
    public synchronized void print(int x) {
      print(new Integer(x).toString());
    }

    /**
     * prints the given boolean
     */
    @Override
    public synchronized void print(boolean x) {
      print(new Boolean(x).toString());
    }

    /**
     * prints the given string
     */
    @Override
    public synchronized void print(String x) {
      StyledDocument doc;
      doc = m_Parent.m_Output.getStyledDocument();

      try {
        // insert text
        doc.insertString(doc.getLength(), x, doc.getStyle(m_Style));

        // move cursor to end
        m_Parent.m_Output.setCaretPosition(doc.getLength());

        // trim size if necessary
        m_Parent.trim();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    /**
     * prints the given object
     */
    @Override
    public synchronized void print(Object x) {
      String line;
      Throwable t;
      StackTraceElement[] trace;
      int i;

      if (x instanceof Throwable) {
        t = (Throwable) x;
        trace = t.getStackTrace();
        line = t.getMessage() + "\n";
        for (i = 0; i < trace.length; i++) {
          line += "\t" + trace[i].toString() + "\n";
        }
        x = line;
      }

      if (x == null) {
        print("null");
      } else {
        print(x.toString());
      }
    }

    /**
     * prints a new line
     */
    @Override
    public synchronized void println() {
      print("\n");
    }

    /**
     * prints the given int
     */
    @Override
    public synchronized void println(int x) {
      print(x);
      println();
    }

    /**
     * prints the given boolean
     */
    @Override
    public synchronized void println(boolean x) {
      print(x);
      println();
    }

    /**
     * prints the given string
     */
    @Override
    public synchronized void println(String x) {
      print(x);
      println();
    }

    /**
     * prints the given object (for Throwables we print the stack trace)
     */
    @Override
    public synchronized void println(Object x) {
      print(x);
      println();
    }
  }

  /**
   * creates the frame
   */
  public LogWindow() {
    super("Weka - Log");

    createFrame();

    // styles
    StyledDocument doc;
    Style style;
    boolean teeDone;

    doc = m_Output.getStyledDocument();
    style = StyleContext.getDefaultStyleContext().getStyle(
      StyleContext.DEFAULT_STYLE);
    style = doc.addStyle(STYLE_STDOUT, style);
    StyleConstants.setFontFamily(style, "monospaced");
    StyleConstants.setForeground(style, COLOR_STDOUT);

    style = StyleContext.getDefaultStyleContext().getStyle(
      StyleContext.DEFAULT_STYLE);
    style = doc.addStyle(STYLE_STDERR, style);
    StyleConstants.setFontFamily(style, "monospaced");
    StyleConstants.setForeground(style, COLOR_STDERR);

    // print streams (instantiate only once!)
    teeDone = !((m_TeeOut == null) && (m_TeeErr == null));
    if (!DEBUG) {
      if (!teeDone) {
        m_TeeOut = new Tee(System.out);
        System.setOut(m_TeeOut);
      }
      m_TeeOut.add(new LogWindowPrintStream(this, m_TeeOut.getDefault(),
        STYLE_STDOUT));
    }

    if (!teeDone) {
      m_TeeErr = new Tee(System.err);
      System.setErr(m_TeeErr);
    }
    m_TeeErr.add(new LogWindowPrintStream(this, m_TeeErr.getDefault(),
      STYLE_STDERR));
  }

  /**
   * creates the frame and all its components
   */
  protected void createFrame() {
    JPanel panel;
    JPanel panel2;
    JPanel panel3;
    JPanel panel4;
    SpinnerNumberModel model;
    int width;
    JLabel label;

    // set layout
    setSize(600, 400);
    width = getBounds().width;
    setLocation(getGraphicsConfiguration().getBounds().width - width,
      getLocation().y);
    getContentPane().setLayout(new BorderLayout());

    // output
    getContentPane().add(new JScrollPane(m_Output), BorderLayout.CENTER);
    setWordwrap(m_UseWordwrap);

    // button(s)
    panel = new JPanel(new BorderLayout());
    getContentPane().add(panel, BorderLayout.SOUTH);
    panel3 = new JPanel(new BorderLayout());
    panel.add(panel3, BorderLayout.SOUTH);
    panel2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    panel3.add(panel2, BorderLayout.EAST);

    m_ButtonClear.setMnemonic('C');
    m_ButtonClear.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        clear();
      }
    });
    panel2.add(m_ButtonClear);

    m_ButtonClose.setMnemonic('l');
    m_ButtonClose.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        close();
      }
    });
    panel2.add(m_ButtonClose);

    // size + current size + wordwrap
    panel2 = new JPanel(new GridLayout(1, 3));
    panel3.add(panel2, BorderLayout.WEST);

    // size
    panel4 = new JPanel(new FlowLayout());
    panel2.add(panel4);
    model = (SpinnerNumberModel) m_SpinnerMaxSize.getModel();
    model.setMinimum(new Integer(1));
    model.setStepSize(new Integer(1000));
    model.setValue(new Integer(100000));
    model.addChangeListener(this);

    label = new JLabel("max. Size");
    label.setDisplayedMnemonic('m');
    label.setLabelFor(m_SpinnerMaxSize);

    panel4.add(label);
    panel4.add(m_SpinnerMaxSize);

    // current size
    panel4 = new JPanel(new FlowLayout());
    panel2.add(panel4);
    panel4.add(m_LabelCurrentSize);

    // wordwrap
    panel4 = new JPanel(new FlowLayout());
    panel2.add(panel4);
    m_CheckBoxWordwrap.setSelected(m_UseWordwrap);
    m_CheckBoxWordwrap.addItemListener(new ItemListener() {
      @Override
      public void itemStateChanged(ItemEvent e) {
        setWordwrap(m_CheckBoxWordwrap.isSelected());
      }
    });
    panel4.add(m_CheckBoxWordwrap);
  }

  /**
   * clears the output
   */
  public void clear() {
    m_Output.setText("");
  }

  /**
   * closes the frame
   */
  public void close() {
    setVisible(false);
  }

  /**
   * trims the JTextPane, if too big
   */
  public void trim() {
    StyledDocument doc;
    int size;
    int maxSize;
    int pos;

    doc = m_Output.getStyledDocument();

    // too large?
    size = doc.getLength();
    maxSize = ((Integer) m_SpinnerMaxSize.getValue()).intValue();
    if (size > maxSize) {
      try {
        // determine EOL after which to cut
        pos = size - maxSize;
        while (!doc.getText(pos, 1).equals("\n")) {
          pos++;
        }
        while (doc.getText(pos, 1).equals("\n")) {
          pos++;
        }
        // delete text
        doc.remove(0, pos);
      } catch (Exception ex) {
        // don't print it, otherwise we get an endless loop!
        if (DEBUG) {
          System.out.println(ex);
        }
      }
    }

    // move cursor to end
    m_Output.setCaretPosition(doc.getLength());
  }

  /**
   * returns a string representation (#RGB) of the given color
   */
  protected String colorToString(Color c) {
    String result;

    result = "#" + Utils.padLeft(Integer.toHexString(c.getRed()), 2)
      + Utils.padLeft(Integer.toHexString(c.getGreen()), 2)
      + Utils.padLeft(Integer.toHexString(c.getBlue()), 2);

    result = result.replaceAll("\\ ", "0").toUpperCase();

    return result;
  }

  /**
   * toggles the wordwrap
* override wordwrap from: * http://forum.java.sun.com/thread.jspa?threadID=498535&messageID=2356174 */ public void setWordwrap(boolean wrap) { Container parent; JTextPane outputOld; m_UseWordwrap = wrap; if (m_CheckBoxWordwrap.isSelected() != m_UseWordwrap) { m_CheckBoxWordwrap.setSelected(m_UseWordwrap); } // create new JTextPane parent = m_Output.getParent(); outputOld = m_Output; if (m_UseWordwrap) { m_Output = new JTextPane(); } else { m_Output = new JTextPane() { private static final long serialVersionUID = -8275856175921425981L; @Override public void setSize(Dimension d) { if (d.width < getGraphicsConfiguration().getBounds().width) { d.width = getGraphicsConfiguration().getBounds().width; } super.setSize(d); } @Override public boolean getScrollableTracksViewportWidth() { return false; } }; } m_Output.setEditable(false); m_Output.addCaretListener(this); m_Output.setDocument(outputOld.getDocument()); m_Output.setCaretPosition(m_Output.getDocument().getLength()); // m_Output.setToolTipText( // "stdout = " + colorToString(COLOR_STDOUT) + ", " // + "stderr = " + colorToString(COLOR_STDERR)); parent.add(m_Output); parent.remove(outputOld); } /** * Called when the caret position is updated. */ @Override public void caretUpdate(CaretEvent e) { m_LabelCurrentSize.setText("currently: " + m_Output.getStyledDocument().getLength()); if (DEBUG) { System.out.println(e); } } /** * Invoked when the target of the listener has changed its state. */ @Override public void stateChanged(ChangeEvent e) { // check max size if Spinner is changed if (e.getSource() == m_SpinnerMaxSize.getModel()) { trim(); validate(); caretUpdate(null); } } /** * for testing only */ public static void main(String[] args) { LogWindow log; LookAndFeel.setLookAndFeel(); log = new LogWindow(); log.setVisible(true); log.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // test output System.out.print("a"); System.err.print("a"); System.out.print("a"); System.out.println(); System.err.println(new java.util.Date()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy