1
2
3
4
5 package spellcast.ui;
6
7 import java.awt.BorderLayout;
8 import java.awt.Dimension;
9 import java.awt.GridBagConstraints;
10 import java.awt.GridBagLayout;
11 import java.awt.Insets;
12 import java.awt.event.ActionEvent;
13 import java.awt.event.ActionListener;
14 import java.beans.PropertyChangeListener;
15 import java.net.InetAddress;
16 import java.util.Iterator;
17 import javax.swing.BorderFactory;
18 import javax.swing.JButton;
19 import javax.swing.JComboBox;
20 import javax.swing.JDialog;
21 import javax.swing.JFrame;
22 import javax.swing.JLabel;
23 import javax.swing.JPanel;
24 import javax.swing.JScrollPane;
25 import javax.swing.JTable;
26 import javax.swing.JTextField;
27 import javax.swing.ListSelectionModel;
28 import javax.swing.ScrollPaneConstants;
29 import javax.swing.SwingUtilities;
30 import javax.swing.event.DocumentEvent;
31 import javax.swing.event.DocumentListener;
32 import javax.swing.event.ListSelectionEvent;
33 import javax.swing.event.ListSelectionListener;
34 import javax.swing.event.SwingPropertyChangeSupport;
35 import javax.swing.table.DefaultTableCellRenderer;
36 import org.apache.log4j.Logger;
37 import spellcast.model.PropertyUpdater;
38 import spellcast.net.ServerStatus;
39
40 /***
41 * The Connection Dialog allows the user to select a spellcast server to connect to.
42 * <p>
43 * A JText field is displayed with the label "Server Address" into which a manual address
44 * can be entered. Pressing enter in the manual address will attempt to connect to the
45 * address specified.
46 * <p>
47 * A JList displays all "Available Local Servers" and displays the name of the game,
48 * the number of players and the ip address of the server in the list. Clicking on a server
49 * in the list will fill in the manual ip address field with the ip address of the selected server.
50 * Double clicking on the item will connect to the address of the selected item.
51 * <p>
52 * In the South area are three buttons for "Connect", "Create" and "Cancel".
53 * <p>
54 * This class will fire CONNECT_PROP and SHOW_NEW_GAME_DIALOG_PROP property change events.
55 *
56 * @author Barrie Treloar
57 */
58 public class ConnectionDialog
59 extends JDialog
60 implements PropertyUpdater, UIProperties {
61 private JButton join;
62 private JButton create;
63 private JButton cancel;
64 private JComboBox profileList;
65 private JTextField serverAddress;
66 private ServerListTableModel serverList;
67 private JTable availableServers;
68 private AvailableServerListUpdater updater;
69
70 private SwingPropertyChangeSupport propertySupport;
71
72 private static final Logger logger = Logger.getLogger("client.connect");
73
74 public ConnectionDialog() {
75 super((JFrame) null, "Connect to Spellcast Server", false);
76
77 propertySupport = new SwingPropertyChangeSupport(this);
78
79 createSouthPanel();
80 createCenterPanel();
81 createEventListeners();
82 pack();
83
84 updater = new AvailableServerListUpdater(serverList);
85 }
86
87 public void addPropertyChangeListener(PropertyChangeListener listener) {
88 propertySupport.addPropertyChangeListener(listener);
89 }
90
91 public void removePropertyChangeListener(PropertyChangeListener listener) {
92 propertySupport.removePropertyChangeListener(listener);
93 }
94
95 /***
96 * Start the server list updater
97 */
98 private void start() {
99 updater.start();
100 }
101
102 /***
103 * Stop the server list updater.
104 */
105 private void stop() {
106 updater.stop();
107 }
108
109 public void setVisible(boolean isVisible) {
110 super.setVisible(isVisible);
111 if (isVisible) {
112 SwingUtilities.invokeLater(new Runnable() {
113 public void run() {
114 java.util.List profiles = WizardProfiles.loadProfiles();
115 WizardProfile defaultProfile = WizardProfiles.loadDefaultProfile();
116 profileList.removeAllItems();
117 Iterator profileIterator = profiles.listIterator();
118 while (profileIterator.hasNext()) {
119 profileList.addItem(profileIterator.next());
120 }
121 profileList.setSelectedItem(defaultProfile);
122
123 availableServers.getSelectionModel().clearSelection();
124 serverList.clear();
125
126 serverAddress.setText("");
127 join.setEnabled(false);
128 }
129 });
130 start();
131 }
132 else {
133 stop();
134 }
135 }
136
137 private void createSouthPanel() {
138 JPanel p = new JPanel();
139 GridBagLayout gridbag = new GridBagLayout();
140 p.setLayout(gridbag);
141 GridBagConstraints c = new GridBagConstraints();
142
143 c.insets = new Insets(4, 4, 4, 4);
144 c.fill = GridBagConstraints.HORIZONTAL;
145
146 c.weightx = 1.0;
147 JLabel empty = new JLabel(" ");
148 gridbag.setConstraints(empty, c);
149 p.add(empty);
150
151 c.weightx = 0.0;
152 join = new JButton("Join");
153 join.setEnabled(false);
154 join.setDefaultCapable(true);
155 join.addActionListener(new ActionListener() {
156 public void actionPerformed(ActionEvent e) {
157 join();
158 }
159 });
160 getRootPane().setDefaultButton(join);
161 gridbag.setConstraints(join, c);
162 p.add(join);
163
164 create = new JButton("Create");
165 create.addActionListener(new ActionListener() {
166 public void actionPerformed(ActionEvent e) {
167 propertySupport.firePropertyChange(SHOW_NEW_GAME_DIALOG_PROP, null, null);
168 setVisible(false);
169 }
170 });
171 gridbag.setConstraints(create, c);
172 p.add(create);
173
174 cancel = new JButton("Cancel");
175 cancel.addActionListener(new ActionListener() {
176 public void actionPerformed(ActionEvent e) {
177 setVisible(false);
178 }
179 });
180 gridbag.setConstraints(cancel, c);
181 p.add(cancel);
182
183 getContentPane().add(p, BorderLayout.SOUTH);
184 }
185
186 private void createCenterPanel() {
187 JPanel p = new JPanel();
188 p.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
189
190 GridBagLayout gridbag = new GridBagLayout();
191 p.setLayout(gridbag);
192 GridBagConstraints c = new GridBagConstraints();
193
194 c.insets = new Insets(4, 4, 4, 4);
195
196 c.anchor = GridBagConstraints.WEST;
197 JLabel profileLabel = new JLabel("Wizard Profile");
198 gridbag.setConstraints(profileLabel, c);
199 p.add(profileLabel);
200
201 c.gridwidth = GridBagConstraints.REMAINDER;
202 profileList = new JComboBox();
203 profileList.setEditable(false);
204 gridbag.setConstraints(profileList, c);
205 p.add(profileList);
206
207 c.gridwidth = 1;
208 JLabel serverAddressLabel = new JLabel("Server Address");
209 gridbag.setConstraints(serverAddressLabel, c);
210 p.add(serverAddressLabel);
211
212 c.gridwidth = GridBagConstraints.REMAINDER;
213 serverAddress = new JTextField(12);
214 serverAddress.addActionListener(new ActionListener() {
215 public void actionPerformed(ActionEvent e) {
216 join();
217 }
218 });
219 gridbag.setConstraints(serverAddress, c);
220 p.add(serverAddress);
221 serverAddressLabel.setLabelFor(serverAddress);
222
223 JLabel availableServersLabel = new JLabel("Available Local Servers");
224 gridbag.setConstraints(availableServersLabel, c);
225 p.add(availableServersLabel);
226
227 serverList = new ServerListTableModel();
228 availableServers = new JTable(serverList);
229 availableServers.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
230 availableServers.setCellSelectionEnabled(false);
231 availableServers.setColumnSelectionAllowed(false);
232 availableServers.setRowSelectionAllowed(true);
233 availableServers.getTableHeader().setReorderingAllowed(false);
234 availableServers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
235 availableServers
236 .getSelectionModel()
237 .addListSelectionListener(new ListSelectionListener() {
238 public void valueChanged(ListSelectionEvent e) {
239 int selectedRow = availableServers.getSelectedRow();
240 if (selectedRow >= 0) {
241 ServerStatus s = serverList.get(selectedRow);
242 serverAddress.setText(
243 s.getServerIPAddress().getHostAddress() + ":" + s.getPort());
244 }
245 }
246 });
247 availableServers.setShowGrid(true);
248 availableServers.setPreferredScrollableViewportSize(new Dimension(350, 75));
249 availableServers
250 .setDefaultRenderer(InetAddress.class, new DefaultTableCellRenderer() {
251 public void setValue(Object value) {
252 setText(((InetAddress) value).getHostAddress());
253 }
254 });
255 availableServers.setDefaultRenderer(
256 Number.class,
257 new DefaultTableCellRenderer());
258
259 c.anchor = GridBagConstraints.CENTER;
260 c.fill = GridBagConstraints.BOTH;
261 c.weightx = 1.0;
262 c.weighty = 1.0;
263 JScrollPane availableServersScrollPane =
264 new JScrollPane(
265 availableServers,
266 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
267 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
268 availableServersScrollPane.setColumnHeaderView(
269 availableServers.getTableHeader());
270 gridbag.setConstraints(availableServersScrollPane, c);
271 p.add(availableServersScrollPane);
272
273 getContentPane().add(p, BorderLayout.CENTER);
274 }
275
276 private void createEventListeners() {
277 serverAddress.getDocument().addDocumentListener(new DocumentListener() {
278 public void insertUpdate(DocumentEvent e) {
279 join.setEnabled(true);
280 }
281
282 public void removeUpdate(DocumentEvent e) {
283 if (serverAddress.getText().trim().equals("")) {
284 join.setEnabled(false);
285 }
286 else {
287 join.setEnabled(true);
288 }
289 }
290
291 public void changedUpdate(DocumentEvent e) {
292 if (serverAddress.getText().trim().equals("")) {
293 join.setEnabled(false);
294 }
295 else {
296 join.setEnabled(true);
297 }
298 }
299 });
300 }
301
302 private void join() {
303 WizardProfile wp = (WizardProfile) profileList.getSelectedItem();
304 if (wp != null) {
305 setVisible(false);
306 ConnectToServerEvent evt =
307 new ConnectToServerEvent(
308 serverAddress.getText().trim(),
309 wp.wizardName,
310 wp.gender);
311 propertySupport.firePropertyChange(CONNECT_PROP, null, evt);
312 }
313 }
314 }