package teamcomm.gui;
import common.Log;
import data.SPLStandardMessage;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import teamcomm.data.AdvancedMessage;
import teamcomm.data.GameState;
import teamcomm.data.RobotState;
import teamcomm.data.event.RobotStateEvent;
import teamcomm.data.event.RobotStateEventListener;
/**
* Class for the windows showing detailed information about robots.
*
* @author Felix Thielke
*/
public class RobotDetailFrame extends JFrame implements RobotStateEventListener {
private static final long serialVersionUID = 4709653396291218508L;
private final RobotState robot;
private final JPanel leftPanel = new JPanel();
private final JPanel rightPanel = new JPanel();
private final Color defaultColor = new JLabel("test").getForeground();
/**
* Constructor.
*
* @param robot robot to create the frame for
* @param anchor panel which triggers the frame on doubleclick
*/
public RobotDetailFrame(final RobotState robot, final JPanel anchor) {
super(robot.getAddress());
this.robot = robot;
final RobotStateEventListener listener = this;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
anchor.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
if (!isVisible()) {
setLocationRelativeTo(anchor);
}
setVisible(true);
update();
repaint();
}
}
});
final JPanel contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(new GridLayout(1, 2, 0, 5));
contentPane.add(leftPanel);
contentPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(defaultColor), robot.getAddress(), TitledBorder.CENTER, TitledBorder.TOP));
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
for (int i = 0; i < 23; i++) {
leftPanel.add(new JLabel(" ", JLabel.LEFT));
}
update();
pack();
setResizable(false);
robot.addListener(listener);
}
});
}
@Override
public void robotStateChanged(final RobotStateEvent e) {
if (isVisible()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
update();
repaint();
}
});
}
}
/**
* Releases resources of this frame.
*/
public void destroy() {
setVisible(false);
robot.removeListener(this);
}
@Override
public void dispose() {
super.dispose();
robot.removeListener(this);
}
/**
* Updates the frame with information of the given robot.
*/
private void update() {
final SPLStandardMessage msg = robot.getLastMessage();
if (msg != null) {
final DecimalFormat df = new DecimalFormat("#.#####");
if (!msg.teamNumValid || msg.teamNum != robot.getTeamNumber()) {
((JLabel) leftPanel.getComponent(0)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(0)).setText("Invalid team no: " + msg.teamNum);
} else {
((JLabel) leftPanel.getComponent(0)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(0)).setText(GameState.getInstance().getTeamName(robot.getTeamNumber(), true, true));
}
if (robot.getPlayerNumber() == null || !msg.playerNumValid) {
((JLabel) leftPanel.getComponent(1)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(1)).setText("Player no: " + msg.playerNum);
} else {
((JLabel) leftPanel.getComponent(1)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(1)).setText("Player no: " + robot.getPlayerNumber());
}
((JLabel) leftPanel.getComponent(2)).setText("Messages: " + robot.getMessageCount());
((JLabel) leftPanel.getComponent(3)).setText("Per second: " + df.format(robot.getMessagesPerSecond()));
if (!msg.valid) {
((JLabel) leftPanel.getComponent(4)).setForeground(Color.red);
}
((JLabel) leftPanel.getComponent(4)).setText("Illegal: " + robot.getIllegalMessageCount() + " (" + Math.round(robot.getIllegalMessageRatio() * 100.0) + "%)");
if (msg.fallenValid) {
((JLabel) leftPanel.getComponent(6)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(6)).setText(msg.fallen ? "fallen" : "upright");
} else {
((JLabel) leftPanel.getComponent(6)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(6)).setText("unknown state");
}
if (msg.intentionValid) {
((JLabel) leftPanel.getComponent(7)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(7)).setText("Activity: " + msg.intention.toString());
} else {
((JLabel) leftPanel.getComponent(7)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(7)).setText("Activity: ?");
}
((JLabel) leftPanel.getComponent(9)).setText("Confidence:");
if (msg.currentPositionConfidenceValid) {
((JLabel) leftPanel.getComponent(10)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(10)).setText("Position: " + msg.currentPositionConfidence + "%");
} else {
((JLabel) leftPanel.getComponent(10)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(10)).setText("Position: " + msg.currentPositionConfidence);
}
if (msg.currentSideConfidenceValid) {
((JLabel) leftPanel.getComponent(11)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(11)).setText("Side: " + msg.currentSideConfidence + "%");
} else {
((JLabel) leftPanel.getComponent(11)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(11)).setText("Side: " + msg.currentSideConfidence);
}
if (msg.averageWalkSpeedValid) {
((JLabel) leftPanel.getComponent(13)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(13)).setText("Avg. walk speed: " + msg.averageWalkSpeed + "mm/s");
} else {
((JLabel) leftPanel.getComponent(13)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(13)).setText("Avg. walk speed: " + msg.averageWalkSpeed);
}
if (msg.maxKickDistanceValid) {
((JLabel) leftPanel.getComponent(14)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(14)).setText("Max. kick distance: " + msg.maxKickDistance + "mm");
} else {
((JLabel) leftPanel.getComponent(14)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(14)).setText("Max. kick distance: " + msg.maxKickDistance);
}
for (int i = 0; i < 5; i++) {
if (msg.suggestionValid[i]) {
((JLabel) leftPanel.getComponent(16 + i)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(16 + i)).setText("Suggestion " + (i + 1) + ": " + msg.suggestion[i].toString());
} else {
((JLabel) leftPanel.getComponent(16 + i)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(16 + i)).setText("Suggestion " + (i + 1) + ": ?");
}
}
if (msg.dataValid) {
((JLabel) leftPanel.getComponent(22)).setForeground(defaultColor);
((JLabel) leftPanel.getComponent(22)).setText("Additional data: " + msg.data.length + "B (" + (msg.data.length * 100 / SPLStandardMessage.SPL_STANDARD_MESSAGE_DATA_SIZE) + "%)");
} else {
((JLabel) leftPanel.getComponent(22)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(22)).setText("Additional data: " + msg.nominalDataBytes + "B");
}
if (!msg.poseValid) {
while (leftPanel.getComponentCount() < 24) {
leftPanel.add(new JLabel(" ", JLabel.LEFT));
}
((JLabel) leftPanel.getComponent(23)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(23)).setText("Invalid pose: x" + df.format(msg.pose[0]) + " y" + df.format(msg.pose[1]) + " t" + df.format(msg.pose[2]));
}
if (!msg.walkingToValid) {
while (leftPanel.getComponentCount() < 25) {
leftPanel.add(new JLabel(" ", JLabel.LEFT));
}
((JLabel) leftPanel.getComponent(24)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(24)).setText("Invalid walking target: x" + df.format(msg.walkingTo[0]) + " y" + df.format(msg.walkingTo[1]));
}
if (!msg.shootingToValid) {
while (leftPanel.getComponentCount() < 26) {
leftPanel.add(new JLabel(" ", JLabel.LEFT));
}
((JLabel) leftPanel.getComponent(25)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(25)).setText("Invalid shooting target: x" + df.format(msg.shootingTo[0]) + " y" + df.format(msg.shootingTo[1]));
}
if (!msg.ballValid) {
while (leftPanel.getComponentCount() < 26) {
leftPanel.add(new JLabel(" ", JLabel.LEFT));
}
((JLabel) leftPanel.getComponent(25)).setForeground(Color.red);
((JLabel) leftPanel.getComponent(25)).setText("Invalid ball data: age " + msg.ballAge + " x" + msg.ball[0] + "/" + msg.ballVel[0] + " y" + msg.ball[1] + "/" + msg.ballVel[1]);
}
}
if (msg instanceof AdvancedMessage) {
final String[] data;
try {
data = ((AdvancedMessage) msg).display();
} catch (final Throwable e) {
Log.error(e.getClass().getSimpleName() + " was thrown while displaying custom message data from " + msg.getClass().getSimpleName() + ": " + e.getMessage());
return;
}
if (data != null && data.length != 0) {
while (rightPanel.getComponentCount() < data.length + 6) {
rightPanel.add(new JLabel(" ", JLabel.LEFT));
}
while (rightPanel.getComponentCount() > data.length + 6) {
rightPanel.remove(rightPanel.getComponentCount() - 1);
}
for (int i = 0; i < data.length; i++) {
if (data[i] != null) {
if (data[i].isEmpty()) {
((JLabel) rightPanel.getComponent(i + 6)).setText(" ");
} else {
((JLabel) rightPanel.getComponent(i + 6)).setText(data[i]);
}
}
}
if (getContentPane().getComponentCount() == 1) {
getContentPane().add(rightPanel);
pack();
}
} else if (getContentPane().getComponentCount() == 2) {
getContentPane().remove(rightPanel);
pack();
}
} else if (getContentPane().getComponentCount() == 2) {
getContentPane().remove(rightPanel);
pack();
}
}
@Override
public void connectionStatusChanged(final RobotStateEvent e) {
}
}