View Javadoc

1   /*
2    *   Magic-Project is a turn based strategy simulator
3    *   Copyright (C) 2003-2007 Fabrice Daugan
4    *
5    *   This program is free software; you can redistribute it and/or modify it 
6    * under the terms of the GNU General Public License as published by the Free 
7    * Software Foundation; either version 2 of the License, or (at your option) any
8    * later version.
9    *
10   *   This program is distributed in the hope that it will be useful, but WITHOUT 
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
13   * details.
14   *
15   *   You should have received a copy of the GNU General Public License along  
16   * with this program; if not, write to the Free Software Foundation, Inc., 
17   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   * 
19   */
20  package net.sf.magicproject.ui.wizard;
21  
22  import java.awt.Dimension;
23  import java.awt.event.ActionEvent;
24  import java.awt.event.ItemEvent;
25  import java.awt.event.ItemListener;
26  
27  import javax.swing.BoxLayout;
28  import javax.swing.JButton;
29  import javax.swing.JComboBox;
30  import javax.swing.JFormattedTextField;
31  import javax.swing.JLabel;
32  import javax.swing.JOptionPane;
33  import javax.swing.JPanel;
34  import javax.swing.JPasswordField;
35  import javax.swing.JTextField;
36  import javax.swing.SwingConstants;
37  import javax.swing.text.NumberFormatter;
38  
39  import net.sf.magicproject.DeckBuilder;
40  import net.sf.magicproject.deckbuilder.Deck;
41  import net.sf.magicproject.deckbuilder.DeckConstraint;
42  import net.sf.magicproject.deckbuilder.DeckConstraints;
43  import net.sf.magicproject.deckbuilder.DeckReader;
44  import net.sf.magicproject.tools.Configuration;
45  import net.sf.magicproject.tools.MToolKit;
46  import net.sf.magicproject.ui.UIHelper;
47  import net.sf.magicproject.ui.component.PasswordChecker;
48  import net.sf.magicproject.ui.i18n.LanguageManager;
49  
50  import org.jvnet.lafwidget.LafWidget;
51  
52  /***
53   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
54   * @since 0.81
55   */
56  public class Network extends YesNo implements ItemListener {
57  
58  	/***
59  	 * Minimal port number.
60  	 */
61  	protected static final int MINIMAL_PORT = 1000;
62  
63  	/***
64  	 * Maximal port number
65  	 */
66  	protected static final int MAXIMAL_PORT = 65535;
67  
68  	/***
69  	 * Creates a new instance of Nextwork <br>
70  	 * 
71  	 * @param title
72  	 *          the title of this wizard.
73  	 * @param description
74  	 *          the description appendend to the title of this wizard. This
75  	 *          content will be displayed as Html.
76  	 * @param okButton
77  	 *          the 'ok button' label.
78  	 * @param width
79  	 *          the preferred width.
80  	 * @param height
81  	 *          the preferred height.
82  	 */
83  	public Network(String title, String description, String okButton, int width,
84  			int height) {
85  		super(title, description, "wiz_run.gif", okButton, LanguageManager
86  				.getString("cancel"), width, height);
87  
88  		// client deck file
89  		final JPanel deckPanel = setSizes(new JLabel(LanguageManager
90  				.getString("wiz_network.deck")
91  				+ " : "));
92  		deckList = new JComboBox(Configuration.getArray("decks.deck"));
93  		deckList.setEditable(true);
94  		deckList.setSelectedIndex(0);
95  		deckList.setToolTipText("<html>"
96  				+ LanguageManager.getString("wiz_network.deck.tooltip"));
97  		deckList
98  				.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE, MAXIMAL_TXT_SIZE));
99  		deckList.setPrototypeDisplayValue(new Object());
100 		deckList.addItemListener(this);
101 		addCheckValidity(deckList);
102 		deckPanel.add(deckList);
103 		deckBtn = new JButton("...");
104 		deckBtn.setMnemonic('.');
105 		deckBtn.setToolTipText("<html>"
106 				+ LanguageManager.getString("wiz_network.deck.browse.tooltip"));
107 		deckBtn.setPreferredSize(new Dimension(MAXIMAL_TXT_SIZE, MAXIMAL_TXT_SIZE));
108 		deckBtn.setMaximumSize(deckBtn.getPreferredSize());
109 		deckBtn.addActionListener(this);
110 		deckPanel.add(deckBtn);
111 
112 		// JDeckBuilder button
113 		jdeckBuilderBtn = new JButton(UIHelper.getIcon("menu_tools_jdb.gif"));
114 		jdeckBuilderBtn.setToolTipText("<html>"
115 				+ LanguageManager.getString("menu_tools_jdb.tooltip"));
116 		jdeckBuilderBtn.setPreferredSize(deckBtn.getPreferredSize());
117 		jdeckBuilderBtn.setMaximumSize(deckBtn.getPreferredSize());
118 		jdeckBuilderBtn.addActionListener(this);
119 		deckPanel.add(jdeckBuilderBtn);
120 		gameParamPanel.add(deckPanel);
121 
122 		// Deck constraints
123 		final JPanel deckConstraint = setSizes(new JLabel(LanguageManager
124 				.getString("wiz_network.deck.constraint")
125 				+ " : "));
126 		constraintList = new JComboBox();
127 		for (DeckConstraint constraint : DeckConstraints.getDeckConstraints()) {
128 			constraintList.addItem(constraint);
129 		}
130 		String constraint = Configuration.getString("decks.constraint",
131 				DeckConstraints.DECK_CONSTRAINT_NAME_NONE);
132 		constraintList.setEditable(false);
133 		constraintList.setSelectedItem(DeckConstraints
134 				.getDeckConstraint(constraint));
135 		constraintList.setToolTipText("<html>"
136 				+ LanguageManager.getString("wiz_network.deck.constraint.tooltip"));
137 		constraintList.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE,
138 				MAXIMAL_TXT_SIZE));
139 		deckConstraint.add(constraintList);
140 
141 		validator = new JButton(UIHelper.getIcon("wiz_network.deck.validator.gif"));
142 		validator.setToolTipText("<html>"
143 				+ LanguageManager.getString("wiz_network.deck.validator.tooltip"));
144 		validator.setPreferredSize(deckBtn.getPreferredSize());
145 		validator.setMaximumSize(deckBtn.getPreferredSize());
146 		validator.addActionListener(this);
147 		deckConstraint.add(validator);
148 
149 		gameParamPanel.add(deckConstraint);
150 
151 		// port of connection
152 		final JPanel gamePortPanelClient = setSizes(new JLabel(LanguageManager
153 				.getString("wiz_network.port")
154 				+ " : "));
155 		final NumberFormatter format = new NumberFormatter();
156 		format.setMinimum(MINIMAL_PORT);
157 		format.setMaximum(Short.MAX_VALUE);
158 		portTxt = new JFormattedTextField(format);
159 		portTxt.setValue(Configuration.getInt("port", 1299));
160 		portTxt.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE, MAXIMAL_TXT_SIZE));
161 		addCheckValidity(portTxt);
162 		gamePortPanelClient.add(portTxt);
163 		gameParamPanel.add(gamePortPanelClient);
164 
165 		// IP of server
166 		JPanel gameIPPanelClient = setSizes(new JLabel(LanguageManager
167 				.getString("wiz_network.ip")
168 				+ " : "));
169 		ipTxt = new JTextField(Configuration.getString("ip", "127.0.0.1"));
170 		ipTxt.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE, MAXIMAL_TXT_SIZE));
171 		gameIPPanelClient.add(ipTxt);
172 		gameParamPanel.add(gameIPPanelClient);
173 
174 		// password of game to join
175 		JPanel clientPasswordPanel = setSizes(new JLabel(UIHelper
176 				.getIcon("pswd.gif")));
177 		passwordTxt = new JPasswordField();
178 		passwordTxt.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE,
179 				MAXIMAL_TXT_SIZE));
180 		passwordTxt.putClientProperty(LafWidget.PASSWORD_STRENGTH_CHECKER,
181 				new PasswordChecker());
182 		clientPasswordPanel.add(passwordTxt);
183 		gameParamPanel.add(clientPasswordPanel);
184 	}
185 
186 	@Override
187 	protected boolean checkValidity() {
188 		try {
189 			if (getSelectedDeck() == null || getSelectedDeck().length() == 0) {
190 				wizardInfo.resetError(LanguageManager
191 						.getString("wiz_network.deck.missed"));
192 			} else if (MToolKit.getFile(getSelectedDeck()) == null
193 					|| !MToolKit.getFile(getSelectedDeck()).exists()
194 					|| !MToolKit.getFile(getSelectedDeck()).isFile()) {
195 				wizardInfo.resetError(LanguageManager
196 						.getString("wiz_network.deck.notfound"));
197 			} else if (portTxt.getText().length() == 0) {
198 				wizardInfo.resetError(LanguageManager
199 						.getString("wiz_network.port.missed"));
200 			} else if ((Integer) portTxt.getValue() < 0
201 					|| (Integer) portTxt.getValue() > Short.MAX_VALUE) {
202 				wizardInfo.resetError(LanguageManager
203 						.getString("wiz_network.port.outofrange"));
204 			} else {
205 				return true;
206 			}
207 		} catch (NumberFormatException e) {
208 			// Ignore this error
209 		}
210 		return false;
211 	}
212 
213 	/***
214 	 * Return the selected deck file.
215 	 * 
216 	 * @return the selected deck file.
217 	 */
218 	private String getSelectedDeck() {
219 		return (String) deckList.getSelectedItem();
220 	}
221 
222 	@Override
223 	public void actionPerformed(ActionEvent event) {
224 		final Object source = event.getSource();
225 		if (source == deckBtn) {
226 			/*
227 			 * invoked when server user chooses a deck file
228 			 */
229 			final String dekFile = MToolKit.getDeckFile();
230 			if (dekFile != null) {
231 				deckList.removeAllItems();
232 				for (String item : Configuration.getArray("decks.deck"))
233 					deckList.addItem(item);
234 
235 				deckList.setSelectedItem(dekFile);
236 				if (checkValidity()) {
237 					wizardInfo.reset();
238 				}
239 			}
240 		} else if (source == jdeckBuilderBtn) {
241 			// open the deck builder
242 			dispose();
243 			DeckBuilder.loadFromMagic();
244 		} else if (source == validator) {
245 			// validate the deck
246 			try {
247 				if (validateDeck()) {
248 					JOptionPane.showMessageDialog(this, LanguageManager.getString("ok"));
249 				}
250 			} catch (Exception e) {
251 				e.printStackTrace();
252 			}
253 		} else {
254 			super.actionPerformed(event);
255 		}
256 	}
257 
258 	/***
259 	 * Initialize the preferred size of given label in order to obtain an right
260 	 * alligned label text.
261 	 * 
262 	 * @param label
263 	 *          the label to add to the returned JPanel component.
264 	 * @return the created JPanel component containig the givent label. The
265 	 *         returned panel has it's maximum size set in order to have a correct
266 	 *         gap between each created panel this way.
267 	 */
268 	protected JPanel setSizes(JLabel label) {
269 		JPanel res = new JPanel();
270 		res.setLayout(new BoxLayout(res, BoxLayout.X_AXIS));
271 		res
272 				.setMaximumSize(new Dimension(UNBOUNDED_TXT_SIZE, MAXIMAL_TXT_SIZE + 10));
273 		label.setPreferredSize(new Dimension(MARGIN_SIZE, MAXIMAL_TXT_SIZE));
274 		label.setMinimumSize(label.getPreferredSize());
275 		label.setMaximumSize(label.getPreferredSize());
276 		label.setHorizontalAlignment(SwingConstants.RIGHT);
277 		res.add(label);
278 		return res;
279 	}
280 
281 	/***
282 	 * Validate the current deck. When the validate success, the deck is updated.
283 	 * 
284 	 * @return <code>true</code> if the selected deck exists and is valid.
285 	 * @throws Exception
286 	 *           if the deck could not be validated.
287 	 */
288 	protected boolean validateDeck() throws Exception {
289 		String deckName = getSelectedDeck();
290 		this.deck = DeckReader.getDeck(this, deckName);
291 		if (this.deck == null) {
292 			return false;
293 		}
294 		return DeckReader.validateDeck(this, deck, (DeckConstraint) constraintList
295 				.getSelectedItem());
296 	}
297 
298 	/***
299 	 * The textfield containing
300 	 */
301 	protected final JTextField ipTxt;
302 
303 	/***
304 	 * The recent deck lists
305 	 */
306 	protected final JComboBox deckList;
307 
308 	/***
309 	 * The available constraints
310 	 */
311 	protected final JComboBox constraintList;
312 
313 	/***
314 	 * The button used to open your file browser
315 	 */
316 	private final JButton deckBtn;
317 
318 	/***
319 	 * The textfiled containing the password to use for connection.
320 	 */
321 	protected final JPasswordField passwordTxt;
322 
323 	/***
324 	 * The button used to open the deck builder
325 	 */
326 	private final JButton jdeckBuilderBtn;
327 
328 	/***
329 	 * The button used to validate the deck.
330 	 */
331 	private final JButton validator;
332 
333 	/***
334 	 * The validated deck.
335 	 */
336 	protected Deck deck;
337 
338 	/***
339 	 * The textfield containing the port number used for connection.
340 	 */
341 	protected final JFormattedTextField portTxt;
342 
343 	public void itemStateChanged(ItemEvent e) {
344 		if (checkValidity())
345 			wizardInfo.reset();
346 
347 	}
348 
349 }