/*
* $Id$
*
* Copyright (c) 2000-2003 by Brent Easton
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.build.module;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import VASSAL.build.GameModule;
import VASSAL.build.module.dice.RollSet;
import VASSAL.preferences.Prefs;
/**
* @author Brent Easton
*
* Dialog for defining a {@link DieManager.RollSet}
* For use with internet dice rollers
*/
public class MultiRoll extends JDialog implements ActionListener {
private static final long serialVersionUID = 1L;
private JButton rollButton = new JButton("Roll");
private JButton canButton = new JButton("Cancel");
private JButton emailButton = new JButton("Change Email Address");
private JDialog me;
private JPanel serverPanel;
private JLabel serverLabel;
private JPanel emailPanel;
private JLabel emailLabel;
private JPanel descPanel;
private JTextField descText;
private JPanel topPanel;
private JPanel buttonPanel;
private JPanel detailPanel;
protected int lastSelectedRow, lastSelectedCol;
private String description = "";
protected RollRow[] rollRows;
public static final int COL_IDX = 0;
public static final int COL_ROLL = 1;
public static final int COL_DESC = 2;
public static final int COL_NDICE = 3;
public static final int COL_NSIDES = 4;
public static final int COL_ADD = 5;
public static final int COL_TOTAL = 6;
public static final int NUMCOLS = 7;
public static final int MAX_ROLLS = 10;
public static final int ROW_HEIGHT = 20;
public static final int COL1_WIDTH = 31;
public static final int COL2_WIDTH = 30;
public static final int COL3_WIDTH = 137;
public static final int COL4_WIDTH = 50;
public static final int COL5_WIDTH = 50;
public static final int COL6_WIDTH = 25;
public static final int COL7_WIDTH = 35;
protected DieManager dieManager;
protected DieRoll[] rolls = new DieRoll[MAX_ROLLS];
protected boolean[] useDie = new boolean[MAX_ROLLS];
protected String verification = "";
protected boolean rollCancelled = false;
protected boolean singleRoll;
protected MultiRoll() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
rollCancelled = true;
setVisible(false);
}
});
}
public MultiRoll(DieManager d, int dfltNDice, int dfltNSides) {
this();
dieManager = d;
for (int i = 0; i < MAX_ROLLS; i++) {
rolls[i] = new DieRoll("", dfltNDice, dfltNSides);
}
initConfig(dfltNDice, dfltNSides);
clearDie();
}
private void clearDie() {
for (int i = 0; i < MAX_ROLLS; i++) {
useDie[i] = false;
}
}
public boolean wasCancelled() {
return rollCancelled;
}
public void setDescription(String s) {
description = s;
descText.setText(s);
}
public String getDescription() {
return description;
}
public RollSet getRollSet() {
ArrayList<DieRoll> l = new ArrayList<DieRoll>();
for (int i = 0; i < MAX_ROLLS; ++i) {
if (useDie[i]) {
l.add(rolls[i]);
}
}
DieRoll[] rolls = l.toArray(new DieRoll[l.size()]);
return new RollSet(getDescription(), rolls);
}
/*
* Reset the status display before making visible in case preferences
* have been changed.
*/
public void setVisible(boolean b) {
setServerHeader();
setEmailHeader();
super.setVisible(b);
}
// Multi-roll Configuration code
private void initConfig(int nd, int ns) {
setModal(true);
setTitle("Multi Roller");
setSize(380, 206);
setBackground(Color.gray);
// Create a panel to hold all other components
topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.PAGE_AXIS));
// Build the Server/Email header
serverPanel = new JPanel();
serverLabel = new JLabel();
setServerHeader();
serverPanel.add(serverLabel);
topPanel.add(serverPanel);
emailPanel = new JPanel();
emailLabel = new JLabel();
setEmailHeader();
emailPanel.add(emailLabel);
topPanel.add(emailPanel);
// And the body
descPanel = new JPanel();
JLabel descLabel = new JLabel("Roll Description");
descText = new JTextField(20);
descText.setText(GameModule.getGameModule().getChatter().getInputField().getText());
descText.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent e) {
description = descText.getText();
}
});
descPanel.add(descLabel);
descPanel.add(descText);
topPanel.add(descPanel);
detailPanel = new JPanel();
detailPanel.setLayout(new BoxLayout(detailPanel, BoxLayout.PAGE_AXIS));
detailPanel.setBorder(BorderFactory.createLineBorder(Color.black));
detailPanel.add(new HeaderRow());
rollRows = new RollRow[MAX_ROLLS];
for (int i = 0; i < MAX_ROLLS; i++) {
rollRows[i] = new RollRow(i, nd, ns);
detailPanel.add(rollRows[i]);
}
topPanel.add(detailPanel);
// Add Some buttons
buttonPanel = new JPanel();
rollButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
rollCancelled = false;
int dieCount = 0;
for (int i = 0; i < MAX_ROLLS; i++) {
dieCount += useDie[i] ? 1 : 0;
}
if (dieCount == 0) {
JOptionPane.showMessageDialog(me, "No dice selected for Roll.", "Roll Cancelled", JOptionPane.ERROR_MESSAGE);
return;
}
setVisible(false);
}
});
canButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
rollCancelled = true;
setVisible(false);
}
});
emailButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
updateEmailAddress();
}
});
buttonPanel.add(rollButton);
buttonPanel.add(canButton);
buttonPanel.add(emailButton);
add(topPanel, BorderLayout.PAGE_START);
add(buttonPanel, BorderLayout.PAGE_END);
pack();
}
protected void setServerHeader() {
serverLabel.setText("Server: " + dieManager.getServer().getName());
}
private static final String EMAIL_OFF = "Off";
protected void setEmailHeader() {
String label;
Prefs prefs = GameModule.getGameModule().getPrefs();
if (((Boolean) prefs.getValue(DieManager.USE_EMAIL)).booleanValue()) {
label = (String) prefs.getValue(DieManager.SECONDARY_EMAIL);
}
else {
label = EMAIL_OFF;
}
emailLabel.setText("Email: " + label);
}
protected void updateEmailAddress() {
Prefs prefs = GameModule.getGameModule().getPrefs();
String[] aBook = (String[]) prefs.getValue(DieManager.ADDRESS_BOOK);
JPopupMenu popup = new JPopupMenu();
JMenuItem menuItem = new JMenuItem(EMAIL_OFF);
menuItem.addActionListener(this);
popup.add(menuItem);
for (int i = 0; i < aBook.length; i++) {
menuItem = new JMenuItem(aBook[i]);
menuItem.addActionListener(this);
popup.add(menuItem);
}
popup.show(emailButton, emailButton.getX(), emailButton.getY());
}
public void actionPerformed(ActionEvent e) {
String address = e.getActionCommand();
Prefs prefs = GameModule.getGameModule().getPrefs();
if (address.equals(EMAIL_OFF)) {
prefs.setValue(DieManager.USE_EMAIL, Boolean.FALSE);
}
else {
prefs.setValue(DieManager.SECONDARY_EMAIL, address);
prefs.setValue(DieManager.USE_EMAIL, Boolean.TRUE);
}
setEmailHeader();
}
protected static class HeaderRow extends JPanel {
private static final long serialVersionUID = 1L;
public HeaderRow() {
Border raisedbevel = BorderFactory.createRaisedBevelBorder();
Border myBorder = raisedbevel;
//setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
//setBorder(blackline);
JLabel col1 = new JLabel("Roll");
col1.setPreferredSize(new Dimension(COL1_WIDTH, ROW_HEIGHT));
col1.setHorizontalAlignment(JTextField.CENTER);
col1.setBorder(myBorder);
// JLabel col2 = new JLabel("Roll");
// col2.setPreferredSize(new Dimension(COL2_WIDTH, ROW_HEIGHT));
// col2.setHorizontalAlignment(JTextField.CENTER);
// col2.setBorder(myBorder);
JLabel col3 = new JLabel("Details");
col3.setPreferredSize(new Dimension(COL3_WIDTH, ROW_HEIGHT));
col3.setBorder(myBorder);
JLabel col4 = new JLabel("nDice");
col4.setBorder(myBorder);
col4.setHorizontalAlignment(JTextField.CENTER);
col4.setPreferredSize(new Dimension(COL4_WIDTH, ROW_HEIGHT));
JLabel col5 = new JLabel("nSides");
col5.setBorder(myBorder);
col5.setHorizontalAlignment(JTextField.CENTER);
col5.setPreferredSize(new Dimension(COL5_WIDTH, ROW_HEIGHT));
JLabel col6 = new JLabel("add");
col6.setBorder(myBorder);
col6.setPreferredSize(new Dimension(COL6_WIDTH, ROW_HEIGHT));
JLabel col7 = new JLabel("Total");
col7.setBorder(myBorder);
col7.setPreferredSize(new Dimension(COL7_WIDTH, ROW_HEIGHT));
add(col1);
//add(col2);
add(col3);
add(col4);
add(col5);
add(col6);
add(col7);
}
}
class RollRow extends JPanel {
private static final long serialVersionUID = 1L;
int myRow;
boolean selected;
String description;
int nDice, nSides, plus;
boolean reportTotal;
Dimension rowDim = new Dimension(40, ROW_HEIGHT);
StateButton col1;
JCheckBox col2, col7;
JComboBox col4, col5;
JTextField col3, col6;
Border blackline = BorderFactory.createLineBorder(Color.black);
Border raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
Border loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
Border raisedbevel = BorderFactory.createRaisedBevelBorder();
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
Border myBorder = raisedbevel;
public void setEnabled(boolean enabled) {
col3.setEnabled(enabled);
col4.setEnabled(enabled);
col5.setEnabled(enabled);
col6.setEnabled(enabled);
col7.setEnabled(enabled);
}
public RollRow(int row, int nd, int ns) {
myRow = row;
//setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
col1 = new StateButton((row + 1) + "");
col1.setPreferredSize(new Dimension(COL1_WIDTH, ROW_HEIGHT));
col1.setState(useDie[myRow]);
col1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
col1.switchState();
useDie[myRow] = col1.getState();
setEnabled(col1.getState());
}
});
// Roll Description
col3 = new JTextField(12);
col3.setBorder(myBorder);
col3.setPreferredSize(new Dimension(COL3_WIDTH, ROW_HEIGHT));
col3.setText(rolls[myRow].getDescription() + "");
col3.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent e) {
rolls[myRow].setDescription(col3.getText());
}
});
col3.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (!col3.hasFocus()) {
col3.selectAll();
}
}
});
col3.setEnabled(false);
// Number of Dice
int allowableDice[] = dieManager.getServer().getnDiceList();
String diceData[] = new String[allowableDice.length];
int defaultNDIdx = 0;
for (int i = 0; i < diceData.length; i++) {
diceData[i] = allowableDice[i] + "";
if (nd == allowableDice[i])
defaultNDIdx = i;
}
col4 = new JComboBox(diceData);
col4.setSelectedIndex(defaultNDIdx);
col4.setPreferredSize(new Dimension(COL4_WIDTH, ROW_HEIGHT));
col4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
rolls[myRow].setNumDice(Integer.valueOf((String) cb.getSelectedItem()).intValue());
}
});
col4.setEnabled(false);
// Number of Sides
int[] allowableSides = dieManager.getServer().getnSideList();
String sideData[] = new String[allowableSides.length];
int defaultNSIdx = 0;
for (int i = 0; i < sideData.length; i++) {
sideData[i] = allowableSides[i] + "";
if (ns == allowableSides[i])
defaultNSIdx = i;
}
col5 = new JComboBox(sideData);
col5.setSelectedIndex(defaultNSIdx);
col5.setPreferredSize(new Dimension(COL5_WIDTH, ROW_HEIGHT));
col5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
rolls[myRow].setNumSides(Integer.valueOf((String) cb.getSelectedItem()).intValue());
}
});
col5.setEnabled(false);
// Add to Total
col6 = new JTextField(2);
col6.setBorder(myBorder);
col6.setPreferredSize(new Dimension(COL6_WIDTH, ROW_HEIGHT));
col6.setText(rolls[myRow].getPlus() + "");
col6.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent e) {
try {
rolls[myRow].setPlus(Integer.valueOf(col3.getText()).intValue());
}
catch (NumberFormatException ev) {
// TODO use IntConfigurer for col3
rolls[myRow].setPlus(0);
}
}
});
col6.setEnabled(false);
// Report Total Only
col7 = new JCheckBox();
col7.setBorder(myBorder);
col7.setPreferredSize(new Dimension(COL7_WIDTH, ROW_HEIGHT));
col7.setHorizontalAlignment(JCheckBox.CENTER);
col7.setSelected(rolls[myRow].isReportTotal());
col7.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
rolls[myRow].setReportTotal((e.getStateChange() == ItemEvent.SELECTED));
}
});
col7.setEnabled(false);
add(col1);
add(col3);
add(col4);
add(col5);
add(col6);
add(col7);
}
}
/*
* An on/off button that changes state to show it's status
*/
protected static class StateButton extends JButton {
private static final long serialVersionUID = 1L;
boolean state = false;
StateButton(String s, boolean b) {
super(s);
setHorizontalAlignment(JButton.CENTER);
setState(b);
}
StateButton(String s) {
this(s, false);
}
public void setState(boolean b) {
state = b;
if (state) {
setBorder(BorderFactory.createLoweredBevelBorder());
}
else {
setBorder(BorderFactory.createRaisedBevelBorder());
}
}
public boolean getState() {
return state;
}
public void switchState() {
setState(!state);
}
}
}