package teamcomm.gui;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import teamcomm.net.logging.LogReplayEvent;
import teamcomm.net.logging.LogReplayEventListener;
import teamcomm.net.logging.LogReplayer;
/**
* Class for an always-on-top window containing controls for replaying the
* contents of a log file.
*
* @author Felix Thielke
*/
public class LogReplayFrame extends JFrame implements LogReplayEventListener {
private static final long serialVersionUID = -2837554836011688982L;
private static final float MAX_REPLAY_SPEED = 128;
private final JFrame parent;
private final JLabel stateLabel = new JLabel("Paused");
private final JLabel timeLabel = new JLabel("00:00");
private final JButton fastRewindButton = new JButton("<<");
private final JButton rewindButton = new JButton("<");
private final JButton pauseButton = new JButton("||");
private final JButton playButton = new JButton(">");
private final JButton fastForwardButton = new JButton(">>");
private float lastSpeed = 0;
/**
* Constructor.
*
* @param parent a window in the center of which this window is initially
* positioned
*/
public LogReplayFrame(final JFrame parent) {
super("Replay log file");
this.parent = parent;
final LogReplayFrame frame = this;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setDefaultCloseOperation(HIDE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
LogReplayer.getInstance().close();
}
});
final JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
contentPane.setBorder(new EmptyBorder(5, 5, 10, 5));
setContentPane(contentPane);
final JPanel infoPanel = new JPanel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.X_AXIS));
infoPanel.setBorder(new EmptyBorder(5, 8, 5, 8));
stateLabel.setHorizontalAlignment(SwingConstants.LEFT);
infoPanel.add(stateLabel);
infoPanel.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(32767, 0)));
timeLabel.setHorizontalAlignment(SwingConstants.RIGHT);
infoPanel.add(timeLabel);
contentPane.add(infoPanel);
contentPane.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(0, 32767)));
final JPanel controlsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
fastRewindButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (lastSpeed < 0) {
LogReplayer.getInstance().setPlaybackSpeed(Math.max(lastSpeed * 2, -MAX_REPLAY_SPEED));
} else {
LogReplayer.getInstance().setPlaybackSpeed(-2);
}
}
});
controlsPanel.add(fastRewindButton);
controlsPanel.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(32767, 0)));
rewindButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LogReplayer.getInstance().setPlaybackSpeed(-1);
}
});
controlsPanel.add(rewindButton);
controlsPanel.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(32767, 0)));
pauseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LogReplayer.getInstance().setPlaybackSpeed(0);
}
});
controlsPanel.add(pauseButton);
controlsPanel.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(32767, 0)));
playButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LogReplayer.getInstance().setPlaybackSpeed(1);
}
});
controlsPanel.add(playButton);
controlsPanel.add(new Box.Filler(new Dimension(), new Dimension(), new Dimension(32767, 0)));
fastForwardButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (lastSpeed > 0) {
LogReplayer.getInstance().setPlaybackSpeed(Math.min(lastSpeed * 2, MAX_REPLAY_SPEED));
} else {
LogReplayer.getInstance().setPlaybackSpeed(2);
}
}
});
controlsPanel.add(fastForwardButton);
contentPane.add(controlsPanel);
setAlwaysOnTop(true);
setResizable(false);
pack();
LogReplayer.getInstance().addListener(frame);
}
});
}
@Override
public void logReplayStatus(final LogReplayEvent e) {
if (e.atBeginning) {
fastRewindButton.setEnabled(false);
rewindButton.setEnabled(false);
} else {
fastRewindButton.setEnabled(true);
if (e.playbackSpeed <= -2) {
if (e.playbackSpeed <= -MAX_REPLAY_SPEED) {
fastRewindButton.setEnabled(false);
}
rewindButton.setEnabled(true);
stateLabel.setText("Fast rewind " + e.playbackSpeed + "x");
} else {
if (e.playbackSpeed < 0) {
rewindButton.setEnabled(false);
stateLabel.setText("Rewinding");
} else {
rewindButton.setEnabled(true);
}
}
}
if (e.atEnd) {
playButton.setEnabled(false);
fastForwardButton.setEnabled(false);
} else {
fastForwardButton.setEnabled(true);
if (e.playbackSpeed >= 2) {
if (e.playbackSpeed >= MAX_REPLAY_SPEED) {
fastForwardButton.setEnabled(false);
}
playButton.setEnabled(true);
stateLabel.setText("Fast forward " + e.playbackSpeed + "x");
} else {
if (e.playbackSpeed > 0) {
playButton.setEnabled(false);
stateLabel.setText("Playing");
} else {
playButton.setEnabled(true);
}
}
}
if (e.playbackSpeed == 0) {
pauseButton.setEnabled(false);
final StringBuilder text = new StringBuilder("Paused");
if (e.atBeginning) {
if (e.atEnd) {
text.append(" (no data)");
} else {
text.append(" (beginning)");
}
} else if (e.atEnd) {
text.append(" (end)");
}
stateLabel.setText(text.toString());
} else {
pauseButton.setEnabled(true);
}
final int minutes = (int) (e.timePosition / 60000);
final byte seconds = (byte) ((e.timePosition / 1000) % 60);
timeLabel.setText((minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds);
lastSpeed = e.playbackSpeed;
}
@Override
public void logReplayStarted() {
fastRewindButton.setEnabled(false);
rewindButton.setEnabled(false);
pauseButton.setEnabled(false);
playButton.setEnabled(true);
fastForwardButton.setEnabled(true);
stateLabel.setText("Paused");
timeLabel.setText("00:00");
setLocationRelativeTo(parent);
setVisible(true);
}
@Override
public void logReplayEnded() {
setVisible(false);
}
}