/src/main/java/org/spoutcraft/launcher/skin/ConsoleFrame.java
Java | 514 lines | 292 code | 50 blank | 172 comment | 27 complexity | da9e9e9f29db4e633f8eedcf87033d6e MD5 | raw file
- /*
- * This file is part of Westeroscraft Launcher.
- *
- * Copyright (c) 2011 Spout LLC <http://www.spout.org/>
- * Westeroscraft Launcher is licensed under the Spout License Version 1.
- *
- * Westeroscraft Launcher is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * In addition, 180 days after any changes are published, you can use the
- * software, incorporating those changes, under the terms of the MIT license,
- * as described in the Spout License Version 1.
- *
- * Westeroscraft Launcher 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License,
- * the MIT license and the Spout License Version 1 along with this program.
- * If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
- * License and see <http://spout.in/licensev1> for the full license,
- * including the MIT license.
- */
- /*
- * This file is part of Spoutcraft Launcher.
- *
- * Copyright (c) 2011 Spout LLC <http://www.spout.org/>
- * Spoutcraft Launcher is licensed under the Spout License Version 1.
- *
- * Spoutcraft Launcher is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * In addition, 180 days after any changes are published, you can use the
- * software, incorporating those changes, under the terms of the MIT license,
- * as described in the Spout License Version 1.
- *
- * Spoutcraft Launcher 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License,
- * the MIT license and the Spout License Version 1 along with this program.
- * If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
- * License and see <http://spout.in/licensev1> for the full license,
- * including the MIT license.
- */
- /*
- * SK's Minecraft Launcher
- * Copyright (C) 2010, 2011 Albert Pham <http://www.sk89q.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 <http://www.gnu.org/licenses/>.
- */
- package org.spoutcraft.launcher.skin;
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.Font;
- import java.awt.Toolkit;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseListener;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.io.Writer;
- import java.util.logging.Handler;
- import java.util.logging.Level;
- import java.util.logging.LogRecord;
- import java.util.logging.Logger;
- import javax.swing.JFrame;
- import javax.swing.JMenuItem;
- import javax.swing.JPopupMenu;
- import javax.swing.JScrollPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextPane;
- import javax.swing.ScrollPaneConstants;
- import javax.swing.WindowConstants;
- import javax.swing.text.AttributeSet;
- import javax.swing.text.BadLocationException;
- import javax.swing.text.DefaultCaret;
- import javax.swing.text.Document;
- import javax.swing.text.JTextComponent;
- import javax.swing.text.SimpleAttributeSet;
- import javax.swing.text.StyleConstants;
- import org.apache.commons.io.IOUtils;
- import org.spoutcraft.launcher.skin.components.LoginFrame;
- import org.spoutcraft.launcher.util.Compatibility;
- /**
- * Console dialog for showing console messages.
- *
- * @author sk89q
- *
- * This code reused and relicensed as LGPLv3 with permission.
- */
- public class ConsoleFrame extends JFrame implements MouseListener {
- private static final long serialVersionUID = 1L;
- private static final Logger rootLogger = Logger.getLogger("launcher");
- private Process trackProc;
- private Handler loggerHandler;
- private JTextComponent textComponent;
- private Document document;
- private int numLines;
- private boolean colorEnabled = false;
- private final SimpleAttributeSet defaultAttributes = new SimpleAttributeSet();
- private final SimpleAttributeSet highlightedAttributes;
- private final SimpleAttributeSet errorAttributes;
- private final SimpleAttributeSet infoAttributes;
- private final SimpleAttributeSet debugAttributes;
- /**
- * Construct the frame.
- *
- * @param numLines number of lines to show at a time
- * @param colorEnabled true to enable a colored console
- */
- public ConsoleFrame(int numLines, boolean colorEnabled) {
- this(numLines, colorEnabled, null, false);
- }
- /**
- * Construct the frame.
- *
- * @param numLines number of lines to show at a time
- * @param colorEnabled true to enable a colored console
- * @param trackProc process to track
- * @param killProcess true to kill the process on console close
- */
- public ConsoleFrame(int numLines, boolean colorEnabled, final Process trackProc, final boolean killProcess) {
- super("Spoutcraft Console");
- this.numLines = numLines;
- this.colorEnabled = colorEnabled;
- this.trackProc = trackProc;
- this.highlightedAttributes = new SimpleAttributeSet();
- StyleConstants.setForeground(highlightedAttributes, Color.BLACK);
- StyleConstants.setBackground(highlightedAttributes, Color.YELLOW);
- this.errorAttributes = new SimpleAttributeSet();
- StyleConstants.setForeground(errorAttributes, new Color(200, 0, 0));
- this.infoAttributes = new SimpleAttributeSet();
- StyleConstants.setForeground(infoAttributes, new Color(200, 0, 0));
- this.debugAttributes = new SimpleAttributeSet();
- StyleConstants.setForeground(debugAttributes, Color.DARK_GRAY);
- setSize(new Dimension(650, 400));
- buildUI();
- Compatibility.setIconImage(this, Toolkit.getDefaultToolkit().getImage(LoginFrame.spoutcraftIcon));
- if (trackProc != null) {
- track(trackProc);
- }
- addMouseListener(this);
- setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent event) {
- if (trackProc != null && killProcess) {
- trackProc.destroy();
- if (loggerHandler != null) {
- rootLogger.removeHandler(loggerHandler);
- }
- event.getWindow().dispose();
- }
- }
- });
- }
- /**
- * Build the interface.
- */
- private void buildUI() {
- if (colorEnabled) {
- JTextPane text = new JTextPane();
- this.textComponent = text;
- } else {
- JTextArea text = new JTextArea();
- this.textComponent = text;
- text.setLineWrap(true);
- }
- textComponent.addMouseListener(this);
- textComponent.setFont(getMonospaceFont());
- textComponent.setEditable(false);
- DefaultCaret caret = (DefaultCaret) textComponent.getCaret();
- caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
- document = textComponent.getDocument();
- document.addDocumentListener(new LimitLinesDocumentListener(numLines, true));
- JScrollPane scrollText = new JScrollPane(textComponent);
- scrollText.setBorder(null);
- scrollText.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
- add(scrollText, BorderLayout.CENTER);
- }
- /**
- * Log a message.
- *
- * @param line line
- */
- public void log(String line) {
- log(line, null);
- }
- /**
- * Log a message given the {@link AttributeSet}.
- *
- * @param line line
- * @param attributes attribute set, or null for none
- */
- public void log(String line, AttributeSet attributes) {
- if (colorEnabled && line.startsWith("(!!)")) {
- attributes = highlightedAttributes;
- }
- try {
- int offset = document.getLength();
- document.insertString(offset, line, (attributes != null && colorEnabled) ? attributes : defaultAttributes);
- textComponent.setCaretPosition(document.getLength());
- } catch (BadLocationException ble) {
- } catch (NullPointerException npe) {
- }
- }
- /**
- * Get an output stream that can be written to.
- *
- * @return output stream
- */
- public ConsoleOutputStream getOutputStream() {
- return getOutputStream((AttributeSet) null);
- }
- /**
- * Get an output stream with the given attribute set.
- *
- * @param attributes attributes
- * @return output stream
- */
- public ConsoleOutputStream getOutputStream(AttributeSet attributes) {
- return new ConsoleOutputStream(attributes);
- }
- /**
- * Get an output stream using the give color.
- *
- * @param color color to use
- * @return output stream
- */
- public ConsoleOutputStream getOutputStream(Color color) {
- SimpleAttributeSet attributes = new SimpleAttributeSet();
- StyleConstants.setForeground(attributes, color);
- return getOutputStream(attributes);
- }
- /**
- * Consume an input stream and print it to the dialog. The consumer
- * will be in a separate daemon thread.
- *
- * @param from stream to read
- */
- public void consume(InputStream from) {
- consume(from, getOutputStream());
- }
- /**
- * Consume an input stream and print it to the dialog. The consumer
- * will be in a separate daemon thread.
- *
- * @param from stream to read
- * @param color color to use
- */
- public void consume(InputStream from, Color color) {
- consume(from, getOutputStream(color));
- }
- /**
- * Consume an input stream and print it to the dialog. The consumer
- * will be in a separate daemon thread.
- *
- * @param from stream to read
- * @param attributes attributes
- */
- public void consume(InputStream from, AttributeSet attributes) {
- consume(from, getOutputStream(attributes));
- }
- /**
- * Internal method to consume a stream.
- *
- * @param from stream to consume
- * @param outputStream console stream to write to
- */
- private void consume(InputStream from, ConsoleOutputStream outputStream) {
- final InputStream in = from;
- final PrintWriter out = new PrintWriter(outputStream, true);
- Thread thread = new Thread(new Runnable() {
- public void run() {
- byte[] buffer = new byte[1024];
- try {
- int len;
- while ((len = in.read(buffer)) != -1) {
- String s = new String(buffer, 0, len);
- System.out.print(s);
- out.append(s);
- out.flush();
- }
- } catch (IOException e) {
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(out);
- }
- }
- });
- thread.setDaemon(true);
- thread.start();
- }
- /**
- * Track a process in a separate daemon thread.
- *
- * @param process process
- */
- private void track(Process process) {
- final PrintWriter out = new PrintWriter(getOutputStream(Color.MAGENTA), true);
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- int code = trackProc.waitFor();
- out.println("Process ended with code " + code);
- } catch (InterruptedException e) {
- out.println("Process tracking interrupted!");
- }
- }
- });
- thread.setDaemon(true);
- thread.start();
- }
- /**
- * Registera global logger listener.
- */
- public void registerLoggerHandler() {
- for (Handler handler : rootLogger.getHandlers()) {
- rootLogger.removeHandler(handler);
- }
- loggerHandler = new ConsoleLoggerHandler();
- rootLogger.addHandler(loggerHandler);
- }
- /**
- * Used to send console messages to the console.
- */
- public final class ConsoleOutputStream extends ByteArrayOutputStream {
- private AttributeSet attributes;
- private ConsoleOutputStream(AttributeSet attributes) {
- this.attributes = attributes;
- }
- @Override
- public void flush() {
- String data = toString();
- if (data.length() == 0) return;
- log(data, attributes);
- reset();
- }
- }
- /**
- * Used to send logger messages to the console.
- */
- private class ConsoleLoggerHandler extends Handler {
- @Override
- public void publish(LogRecord record) {
- Level level = record.getLevel();
- Throwable t = record.getThrown();
- AttributeSet attributes = defaultAttributes;
- if (level.intValue() >= Level.WARNING.intValue()) {
- attributes = errorAttributes;
- } else if (level.intValue() < Level.INFO.intValue()) {
- attributes = debugAttributes;
- }
- log(record.getMessage() + "\n", attributes);
- if (t != null) {
- log(getStackTrace(t) + "\n", attributes);
- }
- }
- @Override
- public void flush() {
- }
- @Override
- public void close() throws SecurityException {
- }
- }
- private static String[] monospaceFontNames = {"Consolas", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Lucida Console"};
- /**
- * Get a supported monospace font.
- *
- * @return font
- */
- public static Font getMonospaceFont() {
- for (String fontName : monospaceFontNames) {
- Font font = Font.decode(fontName + "-11");
- if (!font.getFamily().equalsIgnoreCase("Dialog")) {
- return font;
- }
- }
- return new Font("Monospace", Font.PLAIN, 11);
- }
- /**
- * Get a stack trace as a string.
- *
- * @param t exception
- * @return stack trace
- */
- public static String getStackTrace(Throwable t) {
- Writer result = new StringWriter();
- try {
- PrintWriter printWriter = new PrintWriter(result);
- t.printStackTrace(printWriter);
- } finally {
- IOUtils.closeQuietly(result);
- }
- return result.toString();
- }
- public void mousePressed(MouseEvent e) {
- if (e.isPopupTrigger()) {
- doPop(e);
- }
- }
- public void mouseReleased(MouseEvent e) {
- if (e.isPopupTrigger()) {
- doPop(e);
- }
- }
- public void mouseClicked(MouseEvent e) {
- }
- public void mouseEntered(MouseEvent e) {
- }
- public void mouseExited(MouseEvent e) {
- }
- private void doPop(MouseEvent e) {
- ContextMenu menu = new ContextMenu();
- menu.show(e.getComponent(), e.getX(), e.getY());
- }
- private class ContextMenu extends JPopupMenu {
- private static final long serialVersionUID = 1L;
- JMenuItem copy;
- JMenuItem clear;
- public ContextMenu() {
- copy = new JMenuItem("Copy");
- add(copy);
- copy.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textComponent.copy();
- }
- });
- clear = new JMenuItem("Clear");
- add(clear);
- clear.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textComponent.setText("");
- }
- });
- }
- }
- }