package games.strategy.triplea.ui;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.RelationshipType;
import games.strategy.triplea.Constants;
import games.strategy.util.Triple;
/**
* A panel that shows the current political state, this has no other
* functionality then a view on the current politics.
*/
public class PoliticalStateOverview extends JPanel {
private static final long serialVersionUID = -8445782272897831080L;
public static final String LABEL_SELF = "----";
private final IUIContext m_uic;
private final GameData m_data;
private final boolean m_editable;
private final Set<Triple<PlayerID, PlayerID, RelationshipType>> m_editChanges =
new HashSet<>();
/**
* Constructs this panel
*
* @param data
* gamedata to get the info from
* @param uiContext
* uicontext to use to show this panel.
*/
public PoliticalStateOverview(final GameData data, final IUIContext uiContext, final boolean editable) {
m_uic = uiContext;
m_data = data;
m_editable = editable;
drawPoliticsUI();
}
/**
* does the actual adding of elements to this panel.
*/
private void drawPoliticsUI() {
this.setLayout(new GridBagLayout());
// draw horizontal labels
int currentCell = 1;
final Insets insets = new Insets(5, 2, 5, 2);
for (final PlayerID p : m_data.getPlayerList()) {
this.add(getPlayerLabel(p), new GridBagConstraints(currentCell++, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER,
GridBagConstraints.BOTH, insets, 0, 0));
}
// draw vertical labels and dividers
currentCell = 1;
for (final PlayerID p : m_data.getPlayerList()) {
this.add(new JSeparator(), new GridBagConstraints(0, currentCell++, 20, 1, 0.1, 0.1, GridBagConstraints.WEST,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
this.add(getPlayerLabel(p), new GridBagConstraints(0, currentCell++, 1, 1, 1.0, 1.0, GridBagConstraints.WEST,
GridBagConstraints.BOTH, insets, 0, 0));
}
// draw cells
int x = 1;
int y = 2;
for (final PlayerID pVertical : m_data.getPlayerList()) {
for (final PlayerID pHorizontal : m_data.getPlayerList()) {
if (pHorizontal.equals(pVertical)) {
this.add(new JLabel(PoliticalStateOverview.LABEL_SELF), new GridBagConstraints(x++, y, 1, 1, 1.0, 1.0,
GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0));
} else {
this.add(getRelationshipLabel(pVertical, pHorizontal), new GridBagConstraints(x++, y, 1, 1, 1.0, 1.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0));
}
}
y = y + 2;
x = 1;
}
}
/**
* Gets a label showing the coloured relationshipName between these two
* players.
*/
private JPanel getRelationshipLabel(final PlayerID player1, final PlayerID player2) {
RelationshipType relType = null;
for (final Triple<PlayerID, PlayerID, RelationshipType> changesSoFar : m_editChanges) {
if ((player1.equals(changesSoFar.getFirst()) && player2.equals(changesSoFar.getSecond()))
|| (player2.equals(changesSoFar.getFirst()) && player1.equals(changesSoFar.getSecond()))) {
relType = changesSoFar.getThird();
}
}
if (relType == null) {
m_data.acquireReadLock();
try {
relType = m_data.getRelationshipTracker().getRelationshipType(player1, player2);
} finally {
m_data.releaseReadLock();
}
}
final JComponent relationshipLabel = getRelationshipComponent(player1, player2, relType);
final JPanel relationshipLabelPanel = new JPanel();
relationshipLabelPanel.add(relationshipLabel);
relationshipLabelPanel.setBackground(getRelationshipTypeColor(relType));
return relationshipLabelPanel;
}
private JComponent getRelationshipComponent(final PlayerID player1, final PlayerID player2,
final RelationshipType relType) {
if (!m_editable) {
return new JLabel(relType.getName());
} else {
final JButton button = new JButton(new AbstractAction(relType.getName()) {
private static final long serialVersionUID = 629987410235293178L;
@Override
public void actionPerformed(final ActionEvent e) {
final List<RelationshipType> types =
new ArrayList<>(m_data.getRelationshipTypeList().getAllRelationshipTypes());
types.remove(m_data.getRelationshipTypeList().getNullRelation());
types.remove(m_data.getRelationshipTypeList().getSelfRelation());
final Object[] possibilities = types.toArray();
final RelationshipType chosenRelationship =
(RelationshipType) JOptionPane.showInputDialog(PoliticalStateOverview.this,
"Change Current Relationship between " + player1.getName() + " and " + player2.getName(),
"Change Current Relationship", JOptionPane.PLAIN_MESSAGE, null, possibilities, relType);
if (chosenRelationship != null) {
// remove any old ones
final Iterator<Triple<PlayerID, PlayerID, RelationshipType>> iter = m_editChanges.iterator();
while (iter.hasNext()) {
final Triple<PlayerID, PlayerID, RelationshipType> changesSoFar = iter.next();
if ((player1.equals(changesSoFar.getFirst()) && player2.equals(changesSoFar.getSecond()))
|| (player2.equals(changesSoFar.getFirst()) && player1.equals(changesSoFar.getSecond()))) {
iter.remove();
}
}
// see if there is actually a change
RelationshipType actualRelationship = null;
m_data.acquireReadLock();
try {
actualRelationship = m_data.getRelationshipTracker().getRelationshipType(player1, player2);
} finally {
m_data.releaseReadLock();
}
if (!chosenRelationship.equals(actualRelationship)) {
// add new change
m_editChanges.add(Triple.of(player1, player2, chosenRelationship));
}
// redraw everything
redrawPolitics();
}
}
});
button.setBackground(getRelationshipTypeColor(relType));
return button;
}
}
/**
* returns a color to represent the relationship.
*
* @param relType
* which relationship to get the color for
* @return the color to represent this relationship
*/
private Color getRelationshipTypeColor(final RelationshipType relType) {
final String archeType = relType.getRelationshipTypeAttachment().getArcheType();
if (archeType.equals(Constants.RELATIONSHIP_ARCHETYPE_ALLIED)) {
return Color.green;
}
if (archeType.equals(Constants.RELATIONSHIP_ARCHETYPE_NEUTRAL)) {
return Color.lightGray;
}
if (archeType.equals(Constants.RELATIONSHIP_ARCHETYPE_WAR)) {
return Color.red;
}
throw new IllegalStateException(
"PoliticsUI: RelationshipType: " + relType.getName() + " can only be of archeType Allied, Neutral or War");
}
/**
* Gets a label showing the flag + name of this player.
*
* @param player
* the player to get the label for
* @return the label representing this player
*/
protected JLabel getPlayerLabel(final PlayerID player) {
return new JLabel(player.getName(), new ImageIcon(m_uic.getFlagImageFactory().getFlag(player)), JLabel.LEFT);
}
/**
* Redraw this panel (because of changed politics).
*/
public void redrawPolitics() {
this.removeAll();
this.drawPoliticsUI();
this.revalidate();
}
public Collection<Triple<PlayerID, PlayerID, RelationshipType>> getEditChanges() {
if (!m_editable) {
return null;
}
return m_editChanges;
}
}