001    /**
002     * A dialog box that allows a user to start a new game of Antichess. The user
003     * chooses the type (human or computer) of each player, the amount of time
004     * allotted to each, and the number of powerups to be placed on each side of the
005     * board.
006     */
007    
008    package ui;
009    
010    import java.awt.Dimension;
011    import java.awt.event.ActionEvent;
012    import java.awt.event.ActionListener;
013    import java.awt.event.WindowEvent;
014    import java.awt.event.WindowListener;
015    
016    import javax.swing.Box;
017    import javax.swing.BoxLayout;
018    import javax.swing.ButtonGroup;
019    import javax.swing.JButton;
020    import javax.swing.JFrame;
021    import javax.swing.JLabel;
022    import javax.swing.JPanel;
023    import javax.swing.JRadioButton;
024    import javax.swing.JTextField;
025    import javax.swing.WindowConstants;
026    
027    public class NewGameDialog extends JFrame
028                    implements ActionListener, WindowListener {
029            
030            static final long serialVersionUID = 666;
031    
032            private JRadioButton wHuman;
033            private JRadioButton wCPU;
034            private JRadioButton bHuman;
035            private JRadioButton bCPU;
036    
037            private JTextField wTime;
038            private JTextField bTime;
039    
040            private JTextField powerupField;
041    
042            private JButton beginButton;
043    
044            private boolean successful; // false unless the begin button was pressed
045    
046            /**
047             * Private constructor. To use a NewGameDialog, use the static showDialog
048             * method.
049             */
050            private NewGameDialog() {
051                    JPanel mainPanel;
052                    JPanel topPanel;
053                    JPanel whitePanel;
054                    JPanel wTimePanel;
055                    JPanel blackPanel;
056                    JPanel bTimePanel;
057                    JPanel powerupPanel;
058                    JPanel buttonPanel;
059    
060                    wHuman = new JRadioButton("Human");
061                    wCPU = new JRadioButton("CPU");
062                    ButtonGroup wGroup = new ButtonGroup();
063                    wGroup.add(wHuman);
064                    wGroup.add(wCPU);
065                    wHuman.setSelected(true);
066    
067                    wTime = new JTextField("5:00", 1);
068    
069                    wTimePanel = new JPanel();
070                    wTimePanel.setLayout(new BoxLayout(wTimePanel, BoxLayout.X_AXIS));
071                    wTimePanel.add(new JLabel("Time:"));
072                    wTimePanel.add(Box.createRigidArea(new Dimension(5, 5)));
073                    wTimePanel.add(wTime);
074    
075                    whitePanel = new JPanel();
076                    whitePanel.setLayout(new BoxLayout(whitePanel, BoxLayout.Y_AXIS));
077                    whitePanel.add(new JLabel("White"));
078                    whitePanel.add(Box.createRigidArea(new Dimension(5, 5)));
079                    whitePanel.add(wHuman);
080                    whitePanel.add(wCPU);
081                    whitePanel.add(Box.createRigidArea(new Dimension(5, 5)));
082                    whitePanel.add(wTimePanel);
083    
084                    bHuman = new JRadioButton("Human");
085                    bCPU = new JRadioButton("CPU");
086                    ButtonGroup bGroup = new ButtonGroup();
087                    bGroup.add(bHuman);
088                    bGroup.add(bCPU);
089                    bHuman.setSelected(true);
090    
091                    bTime = new JTextField("5:00", 1);
092    
093                    bTimePanel = new JPanel();
094                    bTimePanel.setLayout(new BoxLayout(bTimePanel, BoxLayout.X_AXIS));
095                    bTimePanel.add(new JLabel("Time:"));
096                    bTimePanel.add(Box.createRigidArea(new Dimension(5, 5)));
097                    bTimePanel.add(bTime);
098    
099                    blackPanel = new JPanel();
100                    blackPanel.setLayout(new BoxLayout(blackPanel, BoxLayout.Y_AXIS));
101                    blackPanel.add(new JLabel("Black"));
102                    blackPanel.add(Box.createRigidArea(new Dimension(5, 5)));
103                    blackPanel.add(bHuman);
104                    blackPanel.add(bCPU);
105                    blackPanel.add(Box.createRigidArea(new Dimension(5, 5)));
106                    blackPanel.add(bTimePanel);
107    
108                    topPanel = new JPanel();
109                    topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));
110                    topPanel.add(Box.createRigidArea(new Dimension(15, 5)));
111                    topPanel.add(whitePanel);
112                    topPanel.add(Box.createRigidArea(new Dimension(30, 5)));
113                    topPanel.add(blackPanel);
114                    topPanel.add(Box.createRigidArea(new Dimension(15, 5)));
115    
116                    beginButton = new JButton("Begin");
117                    buttonPanel = new JPanel();
118                    buttonPanel.add(beginButton);
119    
120                    powerupField = new JTextField("0", 5);
121                    powerupPanel = new JPanel();
122                    powerupPanel.setLayout(new BoxLayout(powerupPanel, BoxLayout.X_AXIS));
123                    powerupPanel.add(Box.createHorizontalGlue());
124                    powerupPanel.add(new JLabel("Powerups per side:"));
125                    powerupPanel.add(Box.createRigidArea(new Dimension(5, 5)));
126                    powerupPanel.add(powerupField);
127                    powerupPanel.add(Box.createHorizontalGlue());
128                    powerupField.setMaximumSize(powerupField.getPreferredSize());
129    
130                    mainPanel = new JPanel();
131                    mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
132                    mainPanel.add(topPanel);
133                    mainPanel.add(Box.createRigidArea(new Dimension(5, 20)));
134                    mainPanel.add(powerupPanel);
135                    mainPanel.add(Box.createRigidArea(new Dimension(5, 5)));
136                    mainPanel.add(buttonPanel);
137    
138                    this.add(mainPanel);
139    
140                    beginButton.addActionListener(this);
141                    this.addWindowListener(this);
142    
143                    successful = false;
144    
145                    this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
146    
147                    this.setTitle("New Game");
148                    this.setSize(this.getPreferredSize());
149                    this.setVisible(true);
150                    this.setSize(this.getPreferredSize());
151            }
152    
153            /**
154             * @requires s is of the form [seconds] or [minutes]:[seconds], or else s is
155             *      the empty String "".
156             * @return an integer representing the time in milliseconds represented by
157             *      the String argument. (If s is the empty String or cannot be parsed, 0 is
158             *  returned.)
159             */
160            private int parseTime(String s) {
161                    s = s.trim();
162    
163                    if (s.length() == 0) {
164                            return 0;
165                    }
166    
167                    int minutes;
168                    int seconds;
169    
170                    // No colon; s is just a number of seconds
171                    try {
172                            if (s.indexOf(":") == -1) {
173                                    minutes = 0;
174                                    seconds = Integer.parseInt(s);
175                            }
176    
177                            // s has the form [minutes]:[seconds]
178                            else {
179                                    minutes = Integer.parseInt(s.substring(0, s.indexOf(":")));
180                                    seconds = Integer.parseInt(s.substring(s.indexOf(":") + 1));
181                            }
182                            return ((60 * minutes) + seconds) * 1000;
183                    }
184    
185                    // If the
186                    catch (NumberFormatException x) {
187                            return 0;
188                    }
189            }
190    
191            /**
192             * @return a GameSettings object corresponding to the options the user has
193             *      selected
194             *  [Returns null if the window was closed by some method other than
195             *  the Begin button.]
196             */
197            private GameSettings getInfo() {
198                    int wt = parseTime(wTime.getText());
199                    int bt = parseTime(bTime.getText());
200    
201                    // If the contents of powerupField can't be parsed, don't add powerups
202                    try {
203                            int numPairs = Integer.parseInt(powerupField.getText());
204                            return new GameSettings(wHuman.isSelected(), wt,
205                                            bHuman.isSelected(), bt, numPairs);
206                    }
207                    catch (NumberFormatException x) {
208                            return new GameSettings(wHuman.isSelected(), wt,
209                                            bHuman.isSelected(), bt, 0);
210                    }
211            }
212            /**
213             * @return true if the window was closed using the Begin button
214             */
215            private boolean wasSuccessful() {
216                    return successful;
217            }
218    
219            /**
220             * @return a GameSettings object based on the options the user had selected
221             *      upon pressing the Begin button.
222             *      [If the user closed the window some other way, this method returns
223             *      null.]
224             */
225            public synchronized static GameSettings showDialog() {
226                    NewGameDialog n = new NewGameDialog();
227                    n.setSize(n.getPreferredSize());
228                    GameSettings g = n.getAnswer();
229                    n.dispose();
230                    n = null;
231                    return g;
232            }
233    
234            /**
235             * Called when the user presses the Begin button. Hides the dialog and
236             * notifies the waiting thread that the user has made a decision.
237             */
238            public synchronized void actionPerformed(ActionEvent e) {
239                    successful = true;
240                    this.setVisible(false);
241                    this.notify();
242            }
243    
244            /**
245             * Waits until the dialog is rendered invisible (by the user pressing the
246             * Begin button), then looks at the options selected by the user and returns
247             * the appropriate GameSettings object.
248             */
249            private synchronized GameSettings getAnswer() {
250    
251                    while(this.isVisible()) {
252                            try {
253                                    this.wait();
254                            } catch (InterruptedException e) {}
255                    }
256                    GameSettings choice = this.getInfo();
257                    if (this.wasSuccessful()) {
258                            return choice;
259                    }
260                    else {
261                            return null;
262                    }
263            }
264    
265            public void windowOpened(WindowEvent e) {
266    
267            }
268    
269            // Notify the waiting call to getAnswer() when the window is closed
270            public synchronized void windowClosed(WindowEvent e) {
271                    notifyAll();
272            }
273            
274            public void windowDeactivated(WindowEvent e) {
275    
276            }
277            
278            public void windowClosing(WindowEvent e) {
279    
280            }
281            
282            public void windowIconified(WindowEvent e) {
283    
284            }
285            
286            public void windowDeiconified(WindowEvent e) {
287    
288            }
289            
290            public void windowActivated(WindowEvent e) {
291    
292            }
293    
294    }