package org.opentrafficsim.remotecontrol;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
/**
* Output stream that writes to a Swing component. Derived from
* https://www.codejava.net/java-se/swing/redirect-standard-output-streams-to-jtextarea
*
* Copyright (c) 2020-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
public class TextAreaOutputStream extends OutputStream
{
/** Swing output object to append all output to. */
private final JTextArea textArea;
/**
* Construct a new TextAreaOutputStream object.
* @param textArea JTextArea; the text area to append the output onto
*/
TextAreaOutputStream(final JTextArea textArea)
{
this.textArea = textArea;
}
/**
* Write to the textArea. May only be called from within the AWT thread!
* @param bytes byte[]; bytes to write
* @param offset int; offset within bytes of the first byte to write
* @param length int; number of bytes to write
*/
public void awtWrite(final byte[] bytes, final int offset, final int length)
{
synchronized (this.textArea)
{
for (int index = offset; index < offset + length; index++)
{
// redirects data to the text area
this.textArea.append(String.valueOf((char) (bytes[index])));
}
// scrolls the text area to the end of data
this.textArea.setCaretPosition(this.textArea.getDocument().getLength());
}
}
/**
* Write to the textArea. May only be called from within the AWT thread!
* @param b int; byte to write
*/
public void awtWrite(final int b)
{
synchronized (this.textArea)
{
// redirects data to the text area
this.textArea.append(String.valueOf((char) b));
// scrolls the text area to the end of data
this.textArea.setCaretPosition(this.textArea.getDocument().getLength());
}
}
/** {@inheritDoc} */
@Override
public void write(final byte[] bytes, final int offset, final int length)
{
if (SwingUtilities.isEventDispatchThread())
{
awtWrite(bytes, offset, length);
}
else
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
/** {@inheritDoc} */
@Override
public void run()
{
awtWrite(bytes, offset, length);
}
});
}
catch (InvocationTargetException | InterruptedException e)
{
e.printStackTrace();
}
}
}
/** {@inheritDoc} */
@Override
public void write(final byte[] bytes)
{
write(bytes, 0, bytes.length);
}
/** {@inheritDoc} */
@Override
public void write(final int b)
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
/** {@inheritDoc} */
@Override
public void run()
{
awtWrite(b);
}
});
}
catch (InvocationTargetException | InterruptedException e)
{
e.printStackTrace();
}
}
}