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  package net.sf.magicproject.clickable.action;
20  
21  import java.awt.BorderLayout;
22  import java.awt.Dimension;
23  import java.awt.event.ActionEvent;
24  import java.awt.event.ActionListener;
25  import java.io.IOException;
26  import java.io.InputStream;
27  
28  import javax.swing.BoxLayout;
29  import javax.swing.JButton;
30  import javax.swing.JLabel;
31  import javax.swing.JPanel;
32  import javax.swing.JScrollPane;
33  import javax.swing.JTabbedPane;
34  import javax.swing.ScrollPaneConstants;
35  import javax.swing.SwingConstants;
36  
37  import net.sf.magicproject.action.WaitChoosenActionChoice;
38  import net.sf.magicproject.action.context.ActionContextWrapper;
39  import net.sf.magicproject.action.handler.ChoosenAction;
40  import net.sf.magicproject.clickable.ability.Ability;
41  import net.sf.magicproject.clickable.targetable.card.CardFactory;
42  import net.sf.magicproject.clickable.targetable.card.MCard;
43  import net.sf.magicproject.database.DatabaseFactory;
44  import net.sf.magicproject.event.context.ContextEventListener;
45  import net.sf.magicproject.network.ConnectionManager;
46  import net.sf.magicproject.network.IdMessages;
47  import net.sf.magicproject.stack.StackManager;
48  import net.sf.magicproject.tools.Log;
49  import net.sf.magicproject.ui.MagicUIComponents;
50  import net.sf.magicproject.ui.UIHelper;
51  import net.sf.magicproject.ui.i18n.LanguageManager;
52  import net.sf.magicproject.ui.wizard.WizardImageIcon;
53  
54  /***
55   * The panel containing all playable action.
56   * 
57   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
58   * @since 0.90
59   */
60  public class ChoosenCostPanel extends JPanel implements ActionListener {
61  
62  	/***
63  	 * Create a new instance of this class.
64  	 */
65  	public ChoosenCostPanel() {
66  		super(new BorderLayout());
67  		final JPanel controlsPanel = new JPanel(null);
68  		final BoxLayout layout0 = new BoxLayout(controlsPanel, BoxLayout.X_AXIS);
69  		controlsPanel.setLayout(layout0);
70  		actionsPanel = new JPanel();
71  		final BoxLayout layout = new BoxLayout(actionsPanel, BoxLayout.Y_AXIS);
72  		actionsPanel.setLayout(layout);
73  		cancelButton = new JButton(LanguageManager.getString("cancel"), UIHelper
74  				.getIcon("cancel.gif"));
75  		cancelButton.setEnabled(false);
76  		final JScrollPane scrollActions = new JScrollPane();
77  		scrollActions
78  				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
79  		scrollActions.setAutoscrolls(true);
80  		scrollActions.setViewportView(actionsPanel);
81  		add(controlsPanel, BorderLayout.SOUTH);
82  		add(scrollActions, BorderLayout.CENTER);
83  
84  		controlsPanel.add(cancelButton);
85  		controlsPanel.add(new JPanel());
86  		controlsPanel.setPreferredSize(new Dimension(1, 30));
87  		miniCard = new JLabel("  ");
88  		miniCard.setHorizontalAlignment(SwingConstants.RIGHT);
89  		controlsPanel.add(miniCard);
90  		cancelButton.addActionListener(this);
91  	}
92  
93  	public void actionPerformed(ActionEvent e) {
94  		if (e.getSource() == cancelButton) {
95  			StackManager.cancel();
96  		}
97  	}
98  
99  	/***
100 	 * 
101 	 *
102 	 */
103 	private void cleanPriv() {
104 		// clean old actions
105 		cancelButton.setEnabled(false);
106 		actionsPanel.removeAll();
107 		currentAction = null;
108 		recordIndex = 0;
109 	}
110 
111 	/***
112 	 * Disable multi-way pay
113 	 */
114 	public void clean() {
115 		cleanPriv();
116 		recordIndex = 1;
117 		((WizardImageIcon) miniCard.getIcon())
118 				.setImage(DatabaseFactory.scaledBackImage);
119 
120 		// desactive the ChoosenAction panel
121 		((JTabbedPane) getParent()).setSelectedIndex(0);
122 		// miniCard.repaint();
123 	}
124 
125 	/***
126 	 * <ul>
127 	 * Initialize UI
128 	 * <li>Remove all existing JChoosenAction componnents
129 	 * <li>Set the card's picture withe the appropriate tooltip
130 	 * <li>Fill the panel with the JChoosenAction components associated to the
131 	 * given <code>contextes</code>
132 	 * <li>Bring to front this panel
133 	 * </ul>
134 	 * 
135 	 * @param card
136 	 *          the card owning the played ability
137 	 * @param contextes
138 	 *          the Action contextes of the played ability
139 	 */
140 	public void initUI(MCard card, ActionContextWrapper... contextes) {
141 		((WizardImageIcon) miniCard.getIcon()).setCard(card);
142 		cleanPriv();
143 		miniCard.setToolTipText(StackManager.tokenCard.getTooltipString());
144 		for (ActionContextWrapper context : contextes) {
145 			if (context != null && context.action instanceof ChoosenAction) {
146 				actionsPanel.add(new JChoosenAction(context));
147 			}
148 		}
149 		if (actionsPanel.getComponentCount() == 0) {
150 			throw new InternalError("No choosenAction");
151 		}
152 
153 		// active the ChoosenAction panel
154 		((JTabbedPane) getParent())
155 				.setSelectedComponent(MagicUIComponents.choosenCostPanel);
156 	}
157 
158 	/***
159 	 * Reset the UI and execute the first ChoosenAction.
160 	 * 
161 	 * @param card
162 	 *          the card owning the played ability
163 	 * @param contextes
164 	 *          the Action contextes of the played ability
165 	 * @return Always false.TODO Modifying choosenAction order is not yet
166 	 *         implemented
167 	 */
168 	public boolean reset(MCard card, ActionContextWrapper[] contextes) {
169 		initUI(card, contextes);
170 
171 		StackManager.actionManager.currentAction = WaitChoosenActionChoice
172 				.getInstance();
173 
174 		// automatically play the first ChoosenAction
175 		StackManager.actionManager.completeChoosenAction(WaitChoosenActionChoice
176 				.getInstance().succeedClickOn(
177 						(JChoosenAction) actionsPanel.getComponent(0)));
178 
179 		/*
180 		 * if (actionsPanel.getComponentCount() == 1) { // play automatically this
181 		 * action StackManager.actionManager.currentAction =
182 		 * WaitChoosenActionChoice.instance; StackManager.actionManager
183 		 * .completeChoosenAction(WaitChoosenActionChoice.instance
184 		 * .succeedClickOn(((JCostAction) actionsPanel.getComponent(0)))); return
185 		 * false; // return reActivate(((JCostAction) //
186 		 * actionsPanel.getComponent(0)).context.contextID); }
187 		 * StackManager.actionManager.waitActionChoice();
188 		 */
189 		return false;
190 	}
191 
192 	/***
193 	 * Reactivate this manager giving the choice to highlight.
194 	 * 
195 	 * @param contextID
196 	 *          the action context id
197 	 * @return true if there is no more ChoosenAction to activate. Othervise false
198 	 *         value indicate a ChoosenAction has been activated. public boolean
199 	 *         reActivate(int contextID) { if
200 	 *         (!StackManager.actionManager.getActionContext(contextID).isCompleted()) { //
201 	 *         the action to activate is not completed if (currentAction != null) { //
202 	 *         first disactivate the current action currentAction.disHighLight();
203 	 *         currentAction = null; } for (int index = 0; index <
204 	 *         actionsPanel.getComponentCount(); index++) { if
205 	 *         (actionsPanel.getComponent(index) instanceof JChoosenAction) {
206 	 *         currentAction = (JChoosenAction) actionsPanel.getComponent(index);
207 	 *         if (currentAction.context.contextID == contextID) { return
208 	 *         currentAction.setSelected(); } } } throw new InternalError( "could
209 	 *         not find the ChoosenAction with contextID=" + contextID); } // the
210 	 *         action to is already completed return true; }
211 	 */
212 
213 	/***
214 	 * Initialize
215 	 */
216 	public void initialize() {
217 		miniCard.setToolTipText(CardFactory.ttHeader + "??");
218 		miniCard
219 				.setIcon(new WizardImageIcon(DatabaseFactory.scaledBackImage, null));
220 		ttClick = "<br><br><b>"
221 				+ LanguageManager.getString("clickchoosenaction.tooltip") + "</b>";
222 	}
223 
224 	/***
225 	 * Set the current ChoosenAction as completed. Incrementing the internal
226 	 * execution count and setting the record index.
227 	 * 
228 	 * @param ability
229 	 *          the current ability.
230 	 * @param context
231 	 *          the context of current ability.
232 	 * @param actionContext
233 	 *          the context of current action.
234 	 * @return true if the current ChoosenAction is completed and if this action
235 	 *         has not to be repeated.
236 	 */
237 	public boolean completeAction(Ability ability, ContextEventListener context,
238 			ActionContextWrapper actionContext) {
239 		// increment counter
240 		actionContext.done++;
241 		// notify refresh descrition text
242 		if (actionContext.done >= actionContext.repeat) {
243 			// completly done
244 			actionContext.recordIndex = recordIndex++;
245 			actionContext.refreshText(ability, context);
246 			return true;
247 		}
248 		actionContext.refreshText(ability, context);
249 		return false;
250 	}
251 
252 	/***
253 	 * Find the first uncompleted action, and execute it.
254 	 * 
255 	 * @return true if an uncompleted has been found.
256 	 */
257 	public boolean playFirstUncompleted() {
258 		for (int index = 0; index < actionsPanel.getComponentCount(); index++) {
259 			if (actionsPanel.getComponent(index) instanceof JChoosenAction) {
260 				currentAction = (JChoosenAction) actionsPanel.getComponent(index);
261 				if (!currentAction.context.isCompleted()) {
262 					return currentAction.setSelected();
263 				}
264 			}
265 		}
266 		// no more uncompleted action
267 		return true;
268 	}
269 
270 	/***
271 	 * This method is invoked when opponent has clicked on this object. this call
272 	 * should be done from the net.sf.magicproject.network listener
273 	 * 
274 	 * @param input
275 	 *          input stream of our net.sf.magicproject.network connection
276 	 * @throws IOException
277 	 *           if error occured when reading the message
278 	 */
279 	public void clickOn(InputStream input) throws IOException {
280 		// waiting for player information
281 		JChoosenAction action = (JChoosenAction) actionsPanel.getComponent(input
282 				.read());
283 		Log.debug("clickOn(VirtualInput):" + action.context.action);
284 		StackManager.actionManager.succeedClickOn(action);
285 	}
286 
287 	/***
288 	 * Send to opponent the message indicating that we've clicked on this card
289 	 * 
290 	 * @param action
291 	 *          the choosen action.
292 	 */
293 	public void sendClickToOpponent(JChoosenAction action) {
294 		for (int index = 0; index < actionsPanel.getComponentCount(); index++) {
295 			if (actionsPanel.getComponent(index) instanceof JChoosenAction
296 					&& actionsPanel.getComponent(index) == action) {
297 				ConnectionManager.sendToOpponent(IdMessages.MSG_CLICK_ACTION, index);
298 				return;
299 			}
300 		}
301 		throw new InternalError("could not find the ChoosenAction to send");
302 	}
303 
304 	/***
305 	 * The current record index the completed action would obtain.
306 	 */
307 	private int recordIndex;
308 
309 	/***
310 	 * The selected action. Is null if no action is selected.
311 	 */
312 	private JChoosenAction currentAction;
313 
314 	private JLabel miniCard;
315 
316 	/***
317 	 * Panel containing card of ability to pay
318 	 */
319 	private JPanel actionsPanel;
320 
321 	/***
322 	 * The cancel button allowing to cancel the current spell.
323 	 */
324 	public JButton cancelButton;
325 
326 	static String ttClick;
327 }