package cryodex.modules.xwing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import cryodex.CryodexController;
import cryodex.Player;
import cryodex.widget.ComponentUtils;
import cryodex.widget.ConfirmationTextField;
public class XWingRoundPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final List<XWingMatch> matches;
private final List<GamePanel> gamePanels = new ArrayList<GamePanel>();
private JPanel quickEntryPanel;
private JPanel quickEntrySubPanel;
private JTextField roundNumber;
private JComboBox<XWingPlayer> playerCombo;
private final JScrollPane scroll;
private final XWingTournament tournament;
public XWingRoundPanel(XWingTournament t, List<XWingMatch> matches) {
super(new BorderLayout());
this.tournament = t;
this.matches = matches;
this.setBorder(BorderFactory.createLineBorder(Color.black));
int counter = 1;
for (XWingMatch match : matches) {
GamePanel gpanel = new GamePanel(counter, match);
gamePanels.add(gpanel);
counter++;
}
scroll = new JScrollPane(ComponentUtils.addToFlowLayout(buildPanel(), FlowLayout.CENTER));
scroll.setBorder(BorderFactory.createEmptyBorder());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scroll.getVerticalScrollBar().setValue(0);
scroll.getVerticalScrollBar().setUnitIncrement(15);
}
});
this.add(getQuickEntryPanel(), BorderLayout.NORTH);
this.add(scroll, BorderLayout.CENTER);
}
public JPanel getQuickEntryPanel() {
if (quickEntryPanel == null) {
quickEntryPanel = new JPanel(new BorderLayout());
quickEntryPanel.setVisible(CryodexController.getOptions().isShowQuickFind());
ComponentUtils.forceSize(quickEntryPanel, 405, 135);
quickEntrySubPanel = new JPanel(new BorderLayout());
ComponentUtils.forceSize(quickEntrySubPanel, 400, 130);
roundNumber = new JTextField(5);
roundNumber.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
});
List<XWingPlayer> playerList = new ArrayList<XWingPlayer>();
playerList.add(new XWingPlayer(new Player()));
playerList.addAll(tournament.getXWingPlayers());
Collections.sort(playerList);
playerCombo = new JComboBox<XWingPlayer>(playerList.toArray(new XWingPlayer[playerList.size()]));
playerCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
update();
}
});
quickEntryPanel
.add(ComponentUtils.addToFlowLayout(
ComponentUtils.addToHorizontalBorderLayout(new JLabel("Enter table number"), roundNumber,
ComponentUtils.addToHorizontalBorderLayout(new JLabel("or choose a player"), playerCombo, null)),
FlowLayout.CENTER), BorderLayout.NORTH);
quickEntryPanel.add(quickEntrySubPanel);
}
return quickEntryPanel;
}
public void update() {
scroll.getViewport().removeAll();
scroll.getViewport().add(ComponentUtils.addToFlowLayout(buildPanel(), FlowLayout.CENTER));
ComponentUtils.repaint(XWingRoundPanel.this);
Integer i = null;
try {
i = Integer.parseInt(roundNumber.getText());
} catch (NumberFormatException e) {
}
XWingPlayer player = playerCombo.getSelectedIndex() == 0 ? null : (XWingPlayer) playerCombo.getSelectedItem();
if (player != null) {
roundNumber.setEnabled(false);
} else if (i != null) {
playerCombo.setEnabled(false);
} else {
roundNumber.setEnabled(true);
playerCombo.setEnabled(true);
}
GamePanel gamePanel = null;
if (i != null) {
if (i > gamePanels.size()) {
return;
}
gamePanel = gamePanels.get(i - 1);
} else if (player != null) {
for (GamePanel g : gamePanels) {
if (g.getMatch().getPlayer1() == player) {
gamePanel = g;
break;
} else if (g.getMatch().getPlayer2() != null && g.getMatch().getPlayer2() == player) {
gamePanel = g;
break;
}
}
}
if (gamePanel == null) {
return;
}
quickEntrySubPanel.add(gamePanel.getPlayerTitle(), BorderLayout.CENTER);
quickEntrySubPanel.removeAll();
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.EAST;
panel.add(gamePanel.getPlayerTitle(), gbc);
gbc.gridx = 2;
gbc.fill = GridBagConstraints.BOTH;
panel.add(gamePanel.getResultCombo(), gbc);
if (gamePanel.getMatch().getPlayer2() != null) {
gbc.gridy++;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 1;
panel.add(gamePanel.getPlayer1KillLabel(), gbc);
gbc.gridx = 2;
panel.add(gamePanel.getPlayer1KillPointsField(), gbc);
gbc.gridx = 3;
gbc.anchor = GridBagConstraints.WEST;
panel.add(gamePanel.getPlayer1KillPointsField().getIndicator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 1;
panel.add(gamePanel.getPlayer2KillLabel(), gbc);
gbc.gridx = 2;
panel.add(gamePanel.getPlayer2KillPointsField(), gbc);
gbc.gridx = 3;
gbc.anchor = GridBagConstraints.WEST;
panel.add(gamePanel.getPlayer2KillPointsField().getIndicator(), gbc);
}
quickEntrySubPanel.add(panel, BorderLayout.CENTER);
ComponentUtils.repaint(quickEntrySubPanel);
ComponentUtils.repaint(quickEntryPanel);
}
public JPanel buildPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = -1;
for (GamePanel gp : gamePanels) {
gbc.gridy++;
gbc.gridx = 0;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.EAST;
panel.add(gp.getPlayerTitle(), gbc);
gbc.gridx = 2;
gbc.fill = GridBagConstraints.BOTH;
panel.add(gp.getResultCombo(), gbc);
if (gp.getMatch().getPlayer2() != null) {
gbc.gridy++;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 1;
panel.add(gp.getPlayer1KillLabel(), gbc);
gbc.gridx = 2;
panel.add(gp.getPlayer1KillPointsField(), gbc);
gbc.gridx = 3;
gbc.anchor = GridBagConstraints.WEST;
panel.add(gp.getPlayer1KillPointsField().getIndicator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 1;
panel.add(gp.getPlayer2KillLabel(), gbc);
gbc.gridx = 2;
panel.add(gp.getPlayer2KillPointsField(), gbc);
gbc.gridx = 3;
gbc.anchor = GridBagConstraints.WEST;
panel.add(gp.getPlayer2KillPointsField().getIndicator(), gbc);
}
}
return panel;
}
public List<XWingMatch> getMatches() {
return matches;
}
public void resetGamePanels(boolean isTextOnly) {
for (GamePanel gp : gamePanels) {
gp.updateGUI();
}
getQuickEntryPanel().setVisible(CryodexController.getOptions().isShowQuickFind());
ComponentUtils.repaint(this);
}
private class GamePanel implements FocusListener, ActionListener {
private final XWingMatch match;
private JLabel playersTitle;
private JComboBox<String> resultsCombo;
private ConfirmationTextField player1KillPoints;
private ConfirmationTextField player2KillPoints;
private JLabel player1KillLabel;
private JLabel player2KillLabel;
private boolean isLoading = false;
private boolean isChanging = false;
private int tableNumber = -1;
public GamePanel(int tableNumber, XWingMatch match) {
this.tableNumber = tableNumber;
isLoading = true;
this.match = match;
setGUIFromMatch();
isLoading = false;
}
private XWingMatch getMatch() {
return match;
}
private JLabel getPlayerTitle() {
if (playersTitle == null) {
playersTitle = new JLabel("");
playersTitle.setFont(new Font(playersTitle.getFont().getName(), playersTitle.getFont().getStyle(), 20));
playersTitle.setHorizontalAlignment(SwingConstants.RIGHT);
}
return playersTitle;
}
private JLabel getPlayer1KillLabel() {
if (player1KillLabel == null) {
player1KillLabel = new JLabel();
}
return player1KillLabel;
}
private JLabel getPlayer2KillLabel() {
if (player2KillLabel == null) {
player2KillLabel = new JLabel();
}
return player2KillLabel;
}
private String[] getComboValues() {
if (match.getPlayer2() == null) {
String[] values = { "Select a result", "BYE" };
return values;
} else {
String generic = XWingModule.getInstance().getOptions().isEnterOnlyPoints() ? "Enter results" : "Select a result";
String[] values = { generic, "WIN - " + match.getPlayer1().getName(), "WIN - " + match.getPlayer2().getName() };
return values;
}
}
private JComboBox<String> getResultCombo() {
if (resultsCombo == null) {
resultsCombo = new JComboBox<String>(getComboValues());
resultsCombo.setRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
@Override
public void paint(Graphics g) {
setForeground(Color.BLACK);
super.paint(g);
}
});
resultsCombo.addActionListener(GamePanel.this);
}
return resultsCombo;
}
public ConfirmationTextField getPlayer1KillPointsField() {
if (player1KillPoints == null) {
player1KillPoints = new ConfirmationTextField();
player1KillPoints.addFocusListener(GamePanel.this);
ComponentUtils.forceSize(player1KillPoints, 50, 25);
}
return player1KillPoints;
}
public ConfirmationTextField getPlayer2KillPointsField() {
if (player2KillPoints == null) {
player2KillPoints = new ConfirmationTextField();
player2KillPoints.addFocusListener(GamePanel.this);
ComponentUtils.forceSize(player2KillPoints, 50, 25);
}
return player2KillPoints;
}
/**
* This function sets the combo box value to the winner of the match based on points.
*/
private void setResultsCombo() {
boolean enterOnlyPoints = XWingModule.getInstance().getOptions().isEnterOnlyPoints();
if (match.getPlayer1PointsDestroyed() != null || match.getPlayer2PointsDestroyed() != null) {
Integer p1points = match.getPlayer1PointsDestroyed() == null ? 0 : match.getPlayer1PointsDestroyed();
Integer p2points = match.getPlayer2PointsDestroyed() == null ? 0 : match.getPlayer2PointsDestroyed();
if (p1points.equals(p2points)) {
// Only reset the result if it was not enabled before. This
// prevents the combo box from resetting if the result
// didn't actually change.
if (getResultCombo().isEnabled() == false) {
getResultCombo().setSelectedIndex(0);
}
getResultCombo().setEnabled(true);
}
if (p1points > p2points) {
getResultCombo().setSelectedIndex(1);
getResultCombo().setEnabled(!enterOnlyPoints);
}
if (p2points > p1points) {
getResultCombo().setSelectedIndex(2);
getResultCombo().setEnabled(!enterOnlyPoints);
}
} else {
getResultCombo().setSelectedIndex(0);
getResultCombo().setEnabled(!enterOnlyPoints);
}
}
public void markInvalid() {
if (match.isValidResult() == false) {
getPlayerTitle().setForeground(Color.red);
} else {
getPlayerTitle().setForeground(Color.black);
}
}
@Override
public void actionPerformed(ActionEvent arg0) {
triggerChange(true);
}
@Override
public void focusGained(FocusEvent e) {
// DO NOTHING!!!
}
@Override
public void focusLost(FocusEvent e) {
triggerChange(false);
}
private void triggerChange(boolean isComboChange) {
if (isLoading || isChanging) {
return;
}
isChanging = true;
setMatchPointsFromGUI();
// Update combo panel
if (isComboChange == false && XWingModule.getInstance().getOptions().isEnterOnlyPoints()) {
setResultsCombo();
}
setMatchResultFromGUI();
tournament.triggerChange();
// Needed to hide completed matches
updateGUI();
isChanging = false;
}
private void setMatchPointsFromGUI() {
// Set player 1 points
Integer player1points = null;
try {
player1points = Integer.valueOf(player1KillPoints.getText());
} catch (Exception e) {
}
match.setPlayer1PointsDestroyed(player1points);
// Set player 2 points
Integer player2points = null;
try {
player2points = Integer.valueOf(player2KillPoints.getText());
} catch (Exception e) {
}
match.setPlayer2PointsDestroyed(player2points);
}
private void setMatchResultFromGUI() {
switch (getResultCombo().getSelectedIndex()) {
case 0:
match.setWinner(null);
match.setBye(false);
break;
case 1:
if (match.getPlayer2() == null) {
match.setBye(true);
} else {
match.setWinner(match.getPlayer1());
}
break;
case 2:
match.setWinner(match.getPlayer2());
break;
default:
break;
}
}
private void setGUIFromMatch() {
if (match.isMatchComplete()) {
if (match.isBye()) {
getResultCombo().setSelectedIndex(1);
} else {
if (match.getWinner() == match.getPlayer1()) {
getResultCombo().setSelectedIndex(1);
} else if (match.getWinner() == match.getPlayer2()) {
getResultCombo().setSelectedIndex(2);
}
}
}
if (match.getPlayer2() != null) {
if (match.getPlayer1PointsDestroyed() != null) {
getPlayer1KillPointsField().setText(String.valueOf(match.getPlayer1PointsDestroyed()));
}
if (match.getPlayer2PointsDestroyed() != null) {
getPlayer2KillPointsField().setText(String.valueOf(match.getPlayer2PointsDestroyed()));
}
}
// Special exception for bye matches
if(match.getPlayer2() == null && XWingModule.getInstance().getOptions().isEnterOnlyPoints()){
match.setBye(true);
getResultCombo().setSelectedIndex(1);
}
updateGUI();
}
private void updateGUI() {
String titleText = null;
boolean showKillPoints = XWingModule.getInstance().getOptions().isShowKillPoints();
boolean enterOnlyPoints = XWingModule.getInstance().getOptions().isEnterOnlyPoints();
boolean hideCompletedMatches = XWingModule.getInstance().getOptions().isHideCompleted();
boolean visible = hideCompletedMatches == false || match.isMatchComplete() == false;
getPlayer1KillLabel().setVisible(visible && showKillPoints);
getPlayer1KillPointsField().setVisible(visible && showKillPoints);
getPlayer2KillLabel().setVisible(visible && showKillPoints);
getPlayer2KillPointsField().setVisible(visible && showKillPoints);
getPlayerTitle().setVisible(visible);
getResultCombo().setVisible(visible);
if (match.getPlayer2() == null) {
titleText = match.getPlayer1().getName() + " has a BYE";
} else {
titleText = match.getPlayer1().getName() + " VS " + match.getPlayer2().getName();
if (match.isDuplicate()) {
titleText = "(Duplicate)" + titleText;
}
if (CryodexController.getOptions().isShowTableNumbers()) {
titleText = tableNumber + ": " + titleText;
}
getPlayer1KillLabel().setText(match.getPlayer1().getName() + " kill points");
getPlayer2KillLabel().setText(match.getPlayer2().getName() + " kill points");
}
getPlayerTitle().setText(titleText);
if (enterOnlyPoints) {
getResultCombo().setEnabled(false);
if (match.getPlayer1PointsDestroyed() != null && match.getPlayer2PointsDestroyed() != null) {
Integer p1points = match.getPlayer1PointsDestroyed();
Integer p2points = match.getPlayer2PointsDestroyed();
if (p1points.equals(p2points)) {
getResultCombo().setEnabled(true);
}
}
} else {
getResultCombo().setEnabled(true);
}
}
}
public void markInvalid() {
for (GamePanel gamePanel : gamePanels) {
gamePanel.markInvalid();
}
}
}