/*
* PrincessBehaviorDialog.java
*
* Derived from megamek.client.ui.swing.BotConfigDialog Copyright (C) 2000-2011 Ben Mazur (bmazur@sev.org)
*
* This file is part of MekHQ.
*
* MekHQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MekHQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.gui.dialog;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import megamek.client.bot.princess.BehaviorSettings;
import megamek.client.bot.princess.BehaviorSettingsFactory;
import megamek.client.bot.princess.PrincessException;
import megamek.client.ui.Messages;
import megamek.client.ui.swing.HelpDialog;
import megamek.common.logging.LogLevel;
import megamek.common.logging.Logger;
/**
* Code copied from megamek.client.ui.swing.BotConfigDialog and modified
* to function as a BehaviorSettings editor rather than a BotClient generator.
*
*/
public class PrincessBehaviorDialog extends JDialog implements ActionListener {
/**
*
*/
private static final long serialVersionUID = -1697757949925940582L;
private static final String UNIT_TARGET = Messages.getString("BotConfigDialog.targetUnit");
private static final String BUILDING_TARGET = Messages.getString("BotConfigDialog.targetBuilding");
private BehaviorSettings princessBehavior;
private BehaviorSettingsFactory behaviorSettingsFactory = BehaviorSettingsFactory.getInstance();
private JComboBox<String> verbosityCombo;
private JTextField targetId;
private JComboBox<String> targetTypeCombo;
private JButton addTargetButton;
private JButton removeTargetButton;
private JButton princessHelpButton;
private JList<String> targetsList;
private DefaultListModel<String> targetsListModel = new DefaultListModel<>();
private JCheckBox forcedWithdrawalCheck;
private JCheckBox goHomeCheck;
private JCheckBox autoFleeCheck;
private JComboBox<String> homeEdgeCombo; //The board edge to be used in a forced withdrawal.
private JSlider aggressionSlidebar;
private JSlider fallShameSlidebar;
private JSlider herdingSlidebar;
private JSlider selfPreservationSlidebar;
private JSlider braverySlidebar;
private JComboBox<String> princessBehaviorNames;
private JTextField nameField;
public boolean dialogAborted = true; // did user not click Ok button?
private final JButton butOK = new JButton(Messages.getString("Okay")); //$NON-NLS-1$
public PrincessBehaviorDialog(JFrame parent,
BehaviorSettings princessBehavior, String name) {
super(parent, name + " behavior", true);
try {
this.princessBehavior = princessBehavior.getCopy();
} catch (PrincessException e) {
e.printStackTrace();
}
setLayout(new BorderLayout());
JScrollPane princessScroll = new JScrollPane(princessPanel());
add(princessScroll, BorderLayout.CENTER);
butOK.addActionListener(this);
add(okayPanel(), BorderLayout.SOUTH);
nameField.setText(name);
validate();
pack();
setSize(new Dimension(600, 600));
setLocationRelativeTo(parent);
}
public BehaviorSettings getBehaviorSettings() {
return princessBehavior;
}
private boolean resetPrincessBehavior() {
princessBehavior = behaviorSettingsFactory.getBehavior((String) princessBehaviorNames.getSelectedItem());
if (princessBehavior == null) {
princessBehavior = new BehaviorSettings();
return false;
}
return true;
}
private void setPrincessFields() {
verbosityCombo.setSelectedIndex(0);
forcedWithdrawalCheck.setSelected(princessBehavior.isForcedWithdrawal());
goHomeCheck.setSelected(princessBehavior.shouldGoHome());
autoFleeCheck.setSelected(princessBehavior.shouldAutoFlee());
autoFleeCheck.setEnabled(goHomeCheck.isSelected());
selfPreservationSlidebar.setValue(princessBehavior.getSelfPreservationIndex());
aggressionSlidebar.setValue(princessBehavior.getHyperAggressionIndex());
fallShameSlidebar.setValue(princessBehavior.getFallShameIndex());
homeEdgeCombo.setSelectedIndex(princessBehavior.getHomeEdge().getIndex());
herdingSlidebar.setValue(princessBehavior.getHerdMentalityIndex());
braverySlidebar.setValue(princessBehavior.getBraveryIndex());
targetsListModel.clear();
for (String t : princessBehavior.getStrategicBuildingTargets()) {
//noinspection unchecked
targetsListModel.addElement(t);
}
repaint();
}
private void getPrincessFields() {
princessBehavior.setForcedWithdrawal(forcedWithdrawalCheck.isSelected());
princessBehavior.setGoHome(goHomeCheck.isSelected());
princessBehavior.setAutoFlee(autoFleeCheck.isSelected());
princessBehavior.setSelfPreservationIndex(selfPreservationSlidebar.getValue());
princessBehavior.setHyperAggressionIndex(aggressionSlidebar.getValue());
princessBehavior.setFallShameIndex(fallShameSlidebar.getValue());
princessBehavior.setHomeEdge(homeEdgeCombo.getSelectedIndex());
princessBehavior.setHerdMentalityIndex(herdingSlidebar.getValue());
princessBehavior.setBraveryIndex(braverySlidebar.getValue());
//Strategic targets?
}
private JLabel buildSliderLabel(String caption) {
Font slideFont = new Font(Font.SANS_SERIF, Font.PLAIN, 8);
JLabel label = new JLabel(caption);
label.setFont(slideFont);
return label;
}
private JSlider buildSlider(String minMsgProperty, String maxMsgProperty, String toolTip, String title) {
JSlider thisSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 10, 5);
Hashtable<Integer, JLabel> sliderLabels = new Hashtable<>(3);
sliderLabels.put(0, buildSliderLabel("0 - " + minMsgProperty));
sliderLabels.put(10, buildSliderLabel("10 - " + maxMsgProperty));
sliderLabels.put(5, buildSliderLabel("5"));
thisSlider.setToolTipText(toolTip);
thisSlider.setLabelTable(sliderLabels);
thisSlider.setPaintLabels(true);
thisSlider.setMinorTickSpacing(1);
thisSlider.setMajorTickSpacing(2);
thisSlider.setSnapToTicks(true);
thisSlider.setBorder(new TitledBorder(new LineBorder(Color.black), title));
thisSlider.setEnabled(true);
return thisSlider;
}
private JPanel okayPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2));
JPanel namepanel = new JPanel(new FlowLayout());
namepanel.add(new JLabel(Messages.getString("BotConfigDialog.nameLabel")));
nameField = new JTextField();
nameField.setText(Messages.getString("BotConfigDialog.namefield.default"));
nameField.setColumns(12);
nameField.setToolTipText(Messages.getString("BotConfigDialog.namefield.tooltip"));
namepanel.add(nameField);
panel.add(namepanel);
butOK.addActionListener(this);
panel.add(butOK);
panel.validate();
return panel;
}
private JPanel buildSliderPanel() {
JPanel panel = new JPanel();
GridBagConstraints constraints = new GridBagConstraints();
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
//Initialize constraints.
constraints.gridheight = 1;
constraints.gridwidth = 0;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.insets = new Insets(0, 0, 0, 0);
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.HORIZONTAL;
//Row 1
constraints.gridy = 0;
constraints.gridx = 0;
braverySlidebar = buildSlider(Messages.getString("BotConfigDialog.braverySliderMin"),
Messages.getString("BotConfigDialog.braverySliderMax"),
Messages.getString("BotConfigDialog.braveryTooltip"),
Messages.getString("BotConfigDialog.braverySliderTitle"));
panel.add(braverySlidebar, constraints);
//Row 2
constraints.gridy++;
selfPreservationSlidebar = buildSlider(Messages.getString("BotConfigDialog.selfPreservationSliderMin"),
Messages.getString("BotConfigDialog.selfPreservationSliderMax"),
Messages.getString("BotConfigDialog.selfPreservationTooltip"),
Messages.getString("BotConfigDialog.selfPreservationSliderTitle"));
panel.add(selfPreservationSlidebar, constraints);
//Row 3
constraints.gridy++;
aggressionSlidebar = buildSlider(Messages.getString("BotConfigDialog.aggressionSliderMin"),
Messages.getString("BotConfigDialog.aggressionSliderMax"),
Messages.getString("BotConfigDialog.aggressionTooltip"),
Messages.getString("BotConfigDialog.aggressionSliderTitle"));
panel.add(aggressionSlidebar, constraints);
//Row 4
constraints.gridy++;
herdingSlidebar = buildSlider(Messages.getString("BotConfigDialog.herdingSliderMin"),
Messages.getString("BotConfigDialog.herdingSliderMax"),
Messages.getString("BotConfigDialog.herdingToolTip"),
Messages.getString("BotConfigDialog.herdingSliderTitle"));
panel.add(herdingSlidebar, constraints);
//Row 5
constraints.gridy++;
fallShameSlidebar = buildSlider(Messages.getString("BotConfigDialog.fallShameSliderMin"),
Messages.getString("BotConfigDialog.fallShameSliderMax"),
Messages.getString("BotConfigDialog.fallShameToolTip"),
Messages.getString("BotConfigDialog.fallShameSliderTitle"));
panel.add(fallShameSlidebar, constraints);
panel.setBorder(new TitledBorder(new LineBorder(Color.black, 1), "Behavior Settings"));
return panel;
}
private JPanel princessPanel() {
//Setup layout.
JPanel panel = new JPanel();
GridBagConstraints constraints = new GridBagConstraints();
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
//Initialize constraints.
constraints.gridheight = 1;
constraints.gridwidth = 1;
constraints.insets = new Insets(2, 2, 2, 2);
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.fill = GridBagConstraints.HORIZONTAL;
//Row 1 Column 1
constraints.gridy = 0;
constraints.gridx = 0;
JLabel behaviorNameLabel = new JLabel(Messages.getString("BotConfigDialog.behaviorNameLabel"));
panel.add(behaviorNameLabel, constraints);
//Row 1 Column 2
constraints.gridx++;
constraints.gridwidth = 2;
princessBehaviorNames = new JComboBox<>(behaviorSettingsFactory.getBehaviorNames());
princessBehaviorNames.setSelectedItem(BehaviorSettingsFactory.DEFAULT_BEHAVIOR_DESCRIPTION);
princessBehaviorNames.setToolTipText(Messages.getString("BotConfigDialog.behaviorToolTip"));
princessBehaviorNames.addActionListener(this);
princessBehaviorNames.setEditable(true);
panel.add(princessBehaviorNames, constraints);
//Row 2 Column 1
constraints.gridx = 0;
constraints.gridwidth = 1;
constraints.gridy++;
JLabel verbosityLabel = new JLabel(Messages.getString("BotConfigDialog.verbosityLabel"));
panel.add(verbosityLabel, constraints);
//Row 2 Column 2;
constraints.gridx++;
constraints.gridwidth = 2;
verbosityCombo = new JComboBox<>(LogLevel.getLogLevelNames());
verbosityCombo.setToolTipText(Messages.getString("BotConfigDialog.verbosityToolTip"));
verbosityCombo.setSelectedIndex(0);
panel.add(verbosityCombo, constraints);
//Row 3 Column 1.
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 1;
forcedWithdrawalCheck = new JCheckBox(Messages.getString("BotConfigDialog.forcedWithdrawalCheck"));
forcedWithdrawalCheck.setToolTipText(Messages.getString("BotConfigDialog.forcedWithdrawalTooltip"));
panel.add(forcedWithdrawalCheck, constraints);
//Row 3 Column 2.
constraints.gridx++;
goHomeCheck = new JCheckBox(Messages.getString("BotConfigDialog.goHomeCheck"));
goHomeCheck.setToolTipText(Messages.getString("BotConfigDialog.goHomeTooltip"));
goHomeCheck.addActionListener(this);
panel.add(goHomeCheck, constraints);
//Row 3 Column 3.
constraints.gridx++;
autoFleeCheck = new JCheckBox(Messages.getString("BotConfigDialog.autoFleeCheck"));
autoFleeCheck.setToolTipText(Messages.getString("BotConfigDialog.autoFleeTooltip"));
autoFleeCheck.addActionListener(this);
autoFleeCheck.setEnabled(false);
panel.add(autoFleeCheck, constraints);
//Row 4 Column 1.
constraints.gridy++;
constraints.gridx = 0;
JLabel homeEdgeLabel = new JLabel(Messages.getString("BotConfigDialog.homeEdgeLabel"));
layout.setConstraints(homeEdgeLabel, constraints);
panel.add(homeEdgeLabel);
//Row 4 Column 2.
constraints.gridx++;
constraints.gridwidth = 2;
homeEdgeCombo = new JComboBox<>(new String[]{Messages.getString("BotConfigDialog.northEdge"),
Messages.getString("BotConfigDialog.southEdge"),
Messages.getString("BotConfigDialog.westEdge"),
Messages.getString("BotConfigDialog.eastEdge")});
homeEdgeCombo.setToolTipText(Messages.getString("BotConfigDialog.homeEdgeTooltip"));
homeEdgeCombo.setSelectedIndex(0);
panel.add(homeEdgeCombo, constraints);
//Row 5.
constraints.gridx = 0;
constraints.gridy++;
constraints.gridwidth = 3;
JPanel sliderPanel = buildSliderPanel();
layout.setConstraints(sliderPanel, constraints);
panel.add(sliderPanel);
//Row 6 Column 1.
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 1;
JLabel targetsLabel = new JLabel(Messages.getString("BotConfigDialog.targetsLabel"));
panel.add(targetsLabel, constraints);
//Row 6 Column 2.
constraints.gridx++;
targetTypeCombo = new JComboBox<>(new String[]{BUILDING_TARGET, UNIT_TARGET});
targetTypeCombo.setToolTipText(Messages.getString("BotConfigDialog.targetTypeTooltip"));
targetTypeCombo.setSelectedIndex(0);
panel.add(targetTypeCombo, constraints);
// Row 6 Column 3.
constraints.gridx++;
targetId = new JTextField();
targetId.setToolTipText(Messages.getString("BotConfigDialog.princessTargetIdToolTip"));
targetId.setColumns(4);
panel.add(targetId, constraints);
//Row 7.
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 3;
panel.add(buildStrategicTargetsButtonPanel(), constraints);
//Row 8
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 3;
targetsList = new JList<>(targetsListModel);
targetsList.setToolTipText(Messages.getString("BotConfigDialog.princessStrategicTargetsToolTip"));
targetsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
targetsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
targetsList.setLayoutOrientation(JList.VERTICAL);
JScrollPane targetScroller = new JScrollPane(targetsList);
targetScroller.setAlignmentX(LEFT_ALIGNMENT);
panel.add(targetScroller, constraints);
//Row 9, Column 2
constraints.gridy++;
constraints.gridx = 1;
constraints.gridwidth = 1;
princessHelpButton = new JButton(Messages.getString("BotConfigDialog.princessHelpButtonCaption"));
princessHelpButton.addActionListener(this);
panel.add(princessHelpButton, constraints);
setPrincessFields();
panel.validate();
return panel;
}
private JPanel buildStrategicTargetsButtonPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 1, 1));
addTargetButton = new JButton(Messages.getString("BotConfigDialog.princessAddTargetButtonCaption"));
addTargetButton.setToolTipText(Messages.getString("BotConfigDialog.princessAddTargetButtonToolTip"));
addTargetButton.addActionListener(this);
panel.add(addTargetButton);
removeTargetButton = new JButton(Messages.getString("BotConfigDialog.princessRemoveTargetButtonCaption"));
removeTargetButton.setToolTipText(Messages.getString("BotConfigDialog.princessRemoveTargetButtonToolTip"));
removeTargetButton.addActionListener(this);
panel.add(removeTargetButton);
return panel;
}
private void launchPrincessHelp() {
try {
// Get the correct help file.
StringBuilder helpPath = new StringBuilder("file:///");
helpPath.append(System.getProperty("user.dir"));
if (!helpPath.toString().endsWith(File.separator)) {
helpPath.append(File.separator);
}
helpPath.append(Messages.getString("BotConfigDialog.princessHelpPath"));
URL helpUrl = new URL(helpPath.toString());
// Launch the help dialog.
HelpDialog helpDialog = new HelpDialog(Messages.getString("BotConfigDialog.princessHelp.title"), helpUrl);
helpDialog.setVisible(true);
} catch (MalformedURLException e) {
handleError("launchPrincessHelp", e);
}
}
public void actionPerformed(ActionEvent e) {
if (butOK.equals(e.getSource())) {
getPrincessFields();
dialogAborted = false;
setVisible(false);
} else if (addTargetButton.equals(e.getSource())) {
String data = targetTypeCombo.getSelectedItem() + ": " + targetId.getText();
targetsListModel.addElement(data);
} else if (removeTargetButton.equals(e.getSource())) {
targetsListModel.removeElementAt(targetsList.getSelectedIndex());
} else if (princessBehaviorNames.equals(e.getSource())) {
if (resetPrincessBehavior()) {
setPrincessFields();
}
} else if (goHomeCheck.equals(e.getSource())) {
if (!goHomeCheck.isSelected()) {
autoFleeCheck.setSelected(false);
}
autoFleeCheck.setEnabled(goHomeCheck.isSelected());
} else if (princessHelpButton.equals(e.getSource())) {
launchPrincessHelp();
}
}
private void handleError(String method, Throwable t) {
JOptionPane.showMessageDialog(this, t.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE);
new Logger().log(getClass(), method, t);
}
public String getBotName() {
return nameField.getText();
}
}