package tools.map.xml.creator;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import games.strategy.util.Triple;
class GameSettingsRow extends DynamicRow {
private boolean isBoolean;
private JComboBox<String> comboBoxSettingName;
private JTextField textFieldValue;
private JComboBox<String> comboBoxEditable;
public static String[] selectionTrueFalse = {"false", "true"};
private JTextField textFieldMinNumber;
private JTextField textFieldMaxNumber;
public GameSettingsRow(final DynamicRowsPanel parentRowPanel, final JPanel stepActionPanel, final String settingName,
final String[] settingNames, final String value, final String editable,
final int minNumber, final int maxNumber) {
super(settingName, parentRowPanel, stepActionPanel);
isBoolean = GameSettingsPanel.isBoolean(settingName);
comboBoxSettingName = new JComboBox<>(settingNames);
comboBoxEditable = new JComboBox<>(selectionTrueFalse);
textFieldValue = new JTextField(value);
textFieldMinNumber = new JTextField(Integer.toString(minNumber));
textFieldMaxNumber = new JTextField(Integer.toString(maxNumber));
Dimension dimension = comboBoxSettingName.getPreferredSize();
dimension.width = INPUT_FIELD_SIZE_LARGE;
comboBoxSettingName.setPreferredSize(dimension);
try {
comboBoxSettingName.setSelectedIndex(Arrays.binarySearch(settingNames, settingName));
} catch (final IllegalArgumentException e) {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.WARNING,
settingName + " is not known (yet)!");
}
comboBoxSettingName.addFocusListener(new FocusListener() {
int prevSelectedIndex = comboBoxSettingName.getSelectedIndex();
@Override
public void focusLost(final FocusEvent arg0) {
if (prevSelectedIndex == comboBoxSettingName.getSelectedIndex()) {
return;
}
final String curr_settingName = (String) comboBoxSettingName.getSelectedItem();
if (currentRowName.equals(curr_settingName)) {
return;
}
if (MapXmlHelper.getGameSettingsMap().containsKey(curr_settingName)) {
JOptionPane.showMessageDialog(stepActionPanel, "Game setting '" + curr_settingName + "' already exists.",
"Input error", JOptionPane.ERROR_MESSAGE);
parentRowPanel.setDataIsConsistent(false);
SwingUtilities.invokeLater(() -> {
comboBoxSettingName.setSelectedIndex(prevSelectedIndex);
comboBoxSettingName.requestFocus();
});
return;
}
// everything is okay with the new value name, lets rename everything
final List<String> newValues = MapXmlHelper.getGameSettingsMap().get(currentRowName);
MapXmlHelper.getGameSettingsMap().remove(currentRowName);
final boolean newIsBoolean = GameSettingsPanel.isBoolean(curr_settingName);
if (newIsBoolean != isBoolean) {
if (newIsBoolean) {
newValues.set(0, "false");
textFieldValue.setText("false");
textFieldMinNumber.setEnabled(false);
textFieldMaxNumber.setEnabled(false);
} else {
newValues.set(0, "0");
textFieldValue.setText("0");
textFieldMinNumber.setEnabled(true);
textFieldMaxNumber.setEnabled(true);
}
newValues.set(2, "0");
textFieldMinNumber.setText("0");
newValues.set(3, "0");
textFieldMaxNumber.setText("0");
isBoolean = newIsBoolean;
SwingUtilities.invokeLater(() -> {
textFieldValue.updateUI();
textFieldMinNumber.updateUI();
textFieldMaxNumber.updateUI();
textFieldValue.requestFocus();
textFieldValue.selectAll();
});
}
MapXmlHelper.getGameSettingsMap().put(curr_settingName, newValues);
currentRowName = curr_settingName;
prevSelectedIndex = comboBoxSettingName.getSelectedIndex();
parentRowPanel.setDataIsConsistent(true);
}
@Override
public void focusGained(final FocusEvent arg0) {}
});
dimension = textFieldValue.getPreferredSize();
dimension.width = INPUT_FIELD_SIZE_SMALL;
textFieldValue.setPreferredSize(dimension);
textFieldValue.addFocusListener(new FocusListener() {
String prevValue = value;
@Override
public void focusLost(final FocusEvent arg0) {
final String inputText = textFieldValue.getText().trim().toLowerCase();
boolean isInputOkay = true;
if (isBoolean) {
final String parsedInputText = Boolean.toString(Boolean.parseBoolean(inputText));
isInputOkay = parsedInputText.equals(inputText);
if (!isInputOkay) {
JOptionPane.showMessageDialog(stepActionPanel, "'" + inputText + "' is not a boolean value.", "Input error",
JOptionPane.ERROR_MESSAGE);
}
} else {
try {
Integer.parseInt(inputText);
} catch (final NumberFormatException e) {
JOptionPane.showMessageDialog(stepActionPanel, "'" + inputText + "' is no integer value.", "Input error",
JOptionPane.ERROR_MESSAGE);
isInputOkay = false;
}
}
if (!isInputOkay) {
textFieldValue.setText(prevValue);
parentRowPanel.setDataIsConsistent(false);
SwingUtilities.invokeLater(() -> {
textFieldValue.updateUI();
textFieldValue.requestFocus();
textFieldValue.selectAll();
});
return;
} else {
SwingUtilities.invokeLater(() -> textFieldValue.updateUI());
}
prevValue = inputText;
// everything is okay with the new value name, lets rename everything
final List<String> newValues = MapXmlHelper.getGameSettingsMap().get(currentRowName);
newValues.set(0, inputText);
parentRowPanel.setDataIsConsistent(true);
}
@Override
public void focusGained(final FocusEvent arg0) {
textFieldValue.selectAll();
}
});
dimension = comboBoxEditable.getPreferredSize();
dimension.width = INPUT_FIELD_SIZE_SMALL;
comboBoxEditable.setPreferredSize(dimension);
comboBoxEditable.setSelectedIndex(Arrays.binarySearch(selectionTrueFalse, editable));
comboBoxEditable.addFocusListener(FocusListenerFocusLost.withAction(() ->
// everything is okay with the new value name, lets rename everything
MapXmlHelper.getGameSettingsMap().get(currentRowName).set(1, (String) comboBoxEditable.getSelectedItem())));
dimension = textFieldMinNumber.getPreferredSize();
dimension.width = INPUT_FIELD_SIZE_SMALL;
textFieldMinNumber.setPreferredSize(dimension);
textFieldMinNumber.setEnabled(!isBoolean);
MapXmlUIHelper.addNewFocusListenerForTextField(textFieldMinNumber, () -> {
final String inputText = textFieldMinNumber.getText().trim();
try {
final int newValue = Integer.parseInt(inputText);
if (newValue < 0) {
throw new NumberFormatException();
}
final Triple<String, String, Integer> oldTriple = MapXmlHelper.getPlayerSequenceMap().get(currentRowName);
MapXmlHelper.getPlayerSequenceMap().put(currentRowName,
Triple.of(oldTriple.getFirst(), oldTriple.getSecond(), newValue));
} catch (final NumberFormatException e) {
textFieldMinNumber.setText("0");
JOptionPane.showMessageDialog(stepActionPanel, "'" + inputText + "' is no integer value.", "Input error",
JOptionPane.ERROR_MESSAGE);
parentRowPanel.setDataIsConsistent(false);
SwingUtilities.invokeLater(() -> {
textFieldMinNumber.updateUI();
textFieldMinNumber.requestFocus();
textFieldMinNumber.selectAll();
});
return;
}
parentRowPanel.setDataIsConsistent(true);
});
dimension = textFieldMaxNumber.getPreferredSize();
dimension.width = INPUT_FIELD_SIZE_SMALL;
textFieldMaxNumber.setPreferredSize(dimension);
textFieldMaxNumber.setEnabled(!isBoolean);
MapXmlUIHelper.addNewFocusListenerForTextField(textFieldMaxNumber, () -> {
final String inputText = textFieldMaxNumber.getText().trim();
try {
final int newValue = Integer.parseInt(inputText);
if (newValue < 0) {
throw new NumberFormatException();
}
final Triple<String, String, Integer> oldTriple = MapXmlHelper.getPlayerSequenceMap().get(currentRowName);
MapXmlHelper.getPlayerSequenceMap().put(currentRowName,
Triple.of(oldTriple.getFirst(), oldTriple.getSecond(), newValue));
} catch (final NumberFormatException e) {
textFieldMaxNumber.setText("0");
JOptionPane.showMessageDialog(stepActionPanel, "'" + inputText + "' is no integer value.", "Input error",
JOptionPane.ERROR_MESSAGE);
parentRowPanel.setDataIsConsistent(false);
SwingUtilities.invokeLater(() -> {
textFieldMaxNumber.updateUI();
textFieldMaxNumber.requestFocus();
textFieldMaxNumber.selectAll();
});
return;
}
parentRowPanel.setDataIsConsistent(true);
});
}
@Override
protected ArrayList<JComponent> getComponentList() {
final ArrayList<JComponent> componentList = new ArrayList<>();
componentList.add(textFieldValue);
componentList.add(comboBoxSettingName);
componentList.add(comboBoxEditable);
componentList.add(textFieldMinNumber);
componentList.add(textFieldMaxNumber);
return componentList;
}
@Override
public void addToParentComponent(final JComponent parent, final GridBagConstraints gbcTemplate) {
parent.add(comboBoxSettingName, gbcTemplate);
final GridBagConstraints gbc_tValue = (GridBagConstraints) gbcTemplate.clone();
gbc_tValue.gridx = 1;
parent.add(textFieldValue, gbc_tValue);
final GridBagConstraints gbc_tEditable = (GridBagConstraints) gbcTemplate.clone();
gbc_tEditable.gridx = 2;
parent.add(comboBoxEditable, gbc_tEditable);
final GridBagConstraints gbc_tMinNumber = (GridBagConstraints) gbcTemplate.clone();
gbc_tMinNumber.gridx = 3;
parent.add(textFieldMinNumber, gbc_tMinNumber);
final GridBagConstraints gbc_tMaxNumber = (GridBagConstraints) gbcTemplate.clone();
gbc_tMaxNumber.gridx = 4;
parent.add(textFieldMaxNumber, gbc_tMaxNumber);
final GridBagConstraints gridBadConstButtonRemove = (GridBagConstraints) gbcTemplate.clone();
gridBadConstButtonRemove.gridx = 5;
parent.add(buttonRemovePerRow, gridBadConstButtonRemove);
}
@Override
protected void adaptRowSpecifics(final DynamicRow newRow) {
final GameSettingsRow newGameSettingsRow = (GameSettingsRow) newRow;
this.comboBoxSettingName.setSelectedIndex(newGameSettingsRow.comboBoxSettingName.getSelectedIndex());
this.textFieldValue.setText(newGameSettingsRow.textFieldValue.getText());
this.comboBoxEditable.setSelectedIndex(newGameSettingsRow.comboBoxEditable.getSelectedIndex());
this.textFieldMinNumber.setText(newGameSettingsRow.textFieldMinNumber.getText());
this.textFieldMaxNumber.setText(newGameSettingsRow.textFieldMaxNumber.getText());
}
@Override
protected void removeRowAction() {
MapXmlHelper.getGameSettingsMap().remove(currentRowName);
}
}