package games.strategy.triplea.ui;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.Territory;
import games.strategy.engine.data.Unit;
import games.strategy.triplea.delegate.Matches;
import games.strategy.util.CountDownLatchHandler;
import games.strategy.util.EventThreadJOptionPane;
import games.strategy.util.Match;
import games.strategy.util.Tuple;
/**
* For choosing territories and units for them, during RandomStartDelegate.
*/
public class PickTerritoryAndUnitsPanel extends ActionPanel {
private static final long serialVersionUID = -2672163347536778594L;
private final TripleAFrame m_parent;
private final JLabel m_actionLabel = new JLabel();
private JButton m_doneButton = null;
private JButton m_selectTerritoryButton = null;
private JButton m_selectUnitsButton = null;
private Territory m_pickedTerritory = null;
private Set<Unit> m_pickedUnits = new HashSet<>();
private List<Territory> m_territoryChoices = null;
private List<Unit> m_unitChoices = null;
private int m_unitsPerPick = 1;
private Action m_currentAction = null;
private Territory m_currentHighlightedTerritory = null;
public PickTerritoryAndUnitsPanel(final GameData data, final MapPanel map, final TripleAFrame parent) {
super(data, map);
m_parent = parent;
}
@Override
public String toString() {
return "Pick Territory and Units";
}
@Override
public void display(final PlayerID id) {
super.display(id);
m_pickedTerritory = null;
m_pickedUnits = new HashSet<>();
m_currentAction = null;
m_currentHighlightedTerritory = null;
SwingUtilities.invokeLater(() -> {
removeAll();
m_actionLabel.setText(id.getName() + " Pick Territory and Units");
add(m_actionLabel);
m_selectTerritoryButton = new JButton(SelectTerritoryAction);
add(m_selectTerritoryButton);
m_selectUnitsButton = new JButton(SelectUnitsAction);
add(m_selectUnitsButton);
m_doneButton = new JButton(DoneAction);
add(m_doneButton);
SwingUtilities.invokeLater(() -> m_selectTerritoryButton.requestFocusInWindow());
});
}
public Tuple<Territory, Set<Unit>> waitForPickTerritoryAndUnits(final List<Territory> territoryChoices,
final List<Unit> unitChoices, final int unitsPerPick) {
m_territoryChoices = territoryChoices;
m_unitChoices = unitChoices;
m_unitsPerPick = unitsPerPick;
if (m_currentHighlightedTerritory != null) {
getMap().clearTerritoryOverlay(m_currentHighlightedTerritory);
m_currentHighlightedTerritory = null;
}
if (territoryChoices.size() == 1) {
m_pickedTerritory = territoryChoices.get(0);
m_currentHighlightedTerritory = m_pickedTerritory;
getMap().setTerritoryOverlay(m_currentHighlightedTerritory, Color.WHITE, 200);
}
SwingUtilities.invokeLater(() -> {
if (territoryChoices.size() > 1) {
SelectTerritoryAction.actionPerformed(null);
} else if (unitChoices.size() > 1) {
SelectUnitsAction.actionPerformed(null);
}
});
waitForRelease();
return Tuple.of(this.m_pickedTerritory, this.m_pickedUnits);
}
private void setWidgetActivation() {
SwingUtilities.invokeLater(() -> {
if (!getActive()) {
// current turn belongs to remote player or AI player
DoneAction.setEnabled(false);
SelectUnitsAction.setEnabled(false);
SelectTerritoryAction.setEnabled(false);
} else {
DoneAction.setEnabled(m_currentAction == null);
SelectUnitsAction.setEnabled(m_currentAction == null);
SelectTerritoryAction.setEnabled(m_currentAction == null);
}
});
}
private final Action DoneAction = new AbstractAction("Done") {
private static final long serialVersionUID = -2376988913511268803L;
@Override
public void actionPerformed(final ActionEvent event) {
m_currentAction = DoneAction;
setWidgetActivation();
if (m_pickedTerritory == null || !m_territoryChoices.contains(m_pickedTerritory)) {
EventThreadJOptionPane.showMessageDialog(m_parent, "Must Pick An Unowned Territory",
"Must Pick An Unowned Territory", JOptionPane.WARNING_MESSAGE, new CountDownLatchHandler(true));
m_currentAction = null;
if (m_currentHighlightedTerritory != null) {
getMap().clearTerritoryOverlay(m_currentHighlightedTerritory);
}
m_currentHighlightedTerritory = null;
m_pickedTerritory = null;
setWidgetActivation();
return;
}
if (!m_pickedUnits.isEmpty() && !m_unitChoices.containsAll(m_pickedUnits)) {
EventThreadJOptionPane.showMessageDialog(m_parent, "Invalid Units?!?", "Invalid Units?!?",
JOptionPane.WARNING_MESSAGE, new CountDownLatchHandler(true));
m_currentAction = null;
m_pickedUnits.clear();
setWidgetActivation();
return;
}
if (m_pickedUnits.size() > Math.max(0, m_unitsPerPick)) {
EventThreadJOptionPane.showMessageDialog(m_parent, "Too Many Units?!?", "Too Many Units?!?",
JOptionPane.WARNING_MESSAGE, new CountDownLatchHandler(true));
m_currentAction = null;
m_pickedUnits.clear();
setWidgetActivation();
return;
}
if (m_pickedUnits.size() < m_unitsPerPick) {
if (m_unitChoices.size() < m_unitsPerPick) {
// if we have fewer units than the number we are supposed to pick, set it to all
m_pickedUnits.addAll(m_unitChoices);
} else if (Match.allMatch(m_unitChoices, Matches.unitIsOfType(m_unitChoices.get(0).getType()))) {
// if we have only 1 unit type, set it to that
m_pickedUnits.clear();
m_pickedUnits.addAll(Match.getNMatches(m_unitChoices, m_unitsPerPick, Match.getAlwaysMatch()));
} else {
EventThreadJOptionPane.showMessageDialog(m_parent, "Must Choose Units For This Territory",
"Must Choose Units For This Territory", JOptionPane.WARNING_MESSAGE, new CountDownLatchHandler(true));
m_currentAction = null;
setWidgetActivation();
return;
}
}
m_currentAction = null;
if (m_currentHighlightedTerritory != null) {
getMap().clearTerritoryOverlay(m_currentHighlightedTerritory);
}
m_currentHighlightedTerritory = null;
setWidgetActivation();
release();
}
};
private final Action SelectUnitsAction = new AbstractAction("Select Units") {
private static final long serialVersionUID = 4745335350716395600L;
@Override
public void actionPerformed(final ActionEvent event) {
m_currentAction = SelectUnitsAction;
setWidgetActivation();
final UnitChooser unitChooser = new UnitChooser(m_unitChoices, Collections.emptyMap(),
getData(), false, getMap().getUIContext());
unitChooser.setMaxAndShowMaxButton(m_unitsPerPick);
if (JOptionPane.OK_OPTION == EventThreadJOptionPane.showConfirmDialog(m_parent, unitChooser, "Select Units",
JOptionPane.OK_CANCEL_OPTION, new CountDownLatchHandler(true))) {
m_pickedUnits.clear();
m_pickedUnits.addAll(unitChooser.getSelected());
}
m_currentAction = null;
setWidgetActivation();
}
};
private final Action SelectTerritoryAction = new AbstractAction("Select Territory") {
private static final long serialVersionUID = -8003634505955439651L;
@Override
public void actionPerformed(final ActionEvent event) {
m_currentAction = SelectTerritoryAction;
setWidgetActivation();
getMap().addMapSelectionListener(MAP_SELECTION_LISTENER);
}
};
private final MapSelectionListener MAP_SELECTION_LISTENER = new DefaultMapSelectionListener() {
@Override
public void territorySelected(final Territory territory, final MouseDetails md) {
if (territory == null) {
return;
}
if (m_currentAction == SelectTerritoryAction) {
if (territory == null || !m_territoryChoices.contains(territory)) {
EventThreadJOptionPane.showMessageDialog(m_parent,
"Must Pick An Unowned Territory (will have a white highlight)", "Must Pick An Unowned Territory",
JOptionPane.WARNING_MESSAGE, new CountDownLatchHandler(true));
return;
}
m_pickedTerritory = territory;
SwingUtilities.invokeLater(() -> {
getMap().removeMapSelectionListener(MAP_SELECTION_LISTENER);
m_currentAction = null;
setWidgetActivation();
});
} else {
System.err.println("Should not be able to select a territory outside of the SelectTerritoryAction.");
}
}
@Override
public void mouseMoved(final Territory territory, final MouseDetails md) {
if (!getActive()) {
System.err.println("Should not be able to select a territory when inactive.");
return;
}
if (territory != null) {
// highlight territory
if (m_currentAction == SelectTerritoryAction) {
if (m_currentHighlightedTerritory != territory) {
if (m_currentHighlightedTerritory != null) {
getMap().clearTerritoryOverlay(m_currentHighlightedTerritory);
}
m_currentHighlightedTerritory = territory;
if (m_territoryChoices.contains(m_currentHighlightedTerritory)) {
getMap().setTerritoryOverlay(m_currentHighlightedTerritory, Color.WHITE, 200);
} else {
getMap().setTerritoryOverlay(m_currentHighlightedTerritory, Color.RED, 200);
}
getMap().repaint();
}
}
}
}
};
}