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.zone;
20  
21  import java.awt.Dimension;
22  import java.io.FileInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.swing.JPanel;
31  import javax.swing.JScrollPane;
32  import javax.swing.ScrollPaneConstants;
33  import javax.swing.UIManager;
34  
35  import net.sf.magicproject.clickable.ability.Ability;
36  import net.sf.magicproject.clickable.targetable.Targetable;
37  import net.sf.magicproject.clickable.targetable.card.CardFactory;
38  import net.sf.magicproject.clickable.targetable.player.Player;
39  import net.sf.magicproject.deckbuilder.Deck;
40  import net.sf.magicproject.deckbuilder.DeckReader;
41  import net.sf.magicproject.stack.StackManager;
42  import net.sf.magicproject.test.Test;
43  import net.sf.magicproject.token.IdConst;
44  import net.sf.magicproject.token.IdZones;
45  import net.sf.magicproject.tools.Configuration;
46  import net.sf.magicproject.ui.MUIManager;
47  import net.sf.magicproject.ui.MagicUIComponents;
48  import net.sf.magicproject.ui.component.JExpandedPanel;
49  import net.sf.magicproject.ui.component.TableTop;
50  
51  /***
52   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
53   * @since 0.54.17
54   */
55  public class ZoneManager {
56  
57  	/***
58  	 * Available zones by id.
59  	 */
60  	private Map<Integer, MZone> zonesById;
61  
62  	/***
63  	 * Additionnal zones of game.
64  	 */
65  	static ZoneConfiguration[] additionalZoneConfigurations;
66  
67  	/***
68  	 * additional zones of this player
69  	 */
70  	public final List<ExpandableZone> additionalZones;
71  
72  	/***
73  	 * The initial zone's id where the cards of loaded deck go.
74  	 */
75  	static int defaultZoneId;
76  
77  	/***
78  	 * This is the current expanded zone. Is null if no zone is expanded.
79  	 */
80  	public static ExpandableZone expandedZone;
81  
82  	/***
83  	 * This is the current expanded zone. Is null if no zone is expanded.
84  	 */
85  	static JPanel expandedPanel;
86  
87  	private final JPanel additionalZonesPanel;
88  
89  	/***
90  	 * All available zones.
91  	 */
92  	private final List<MZone> validTargetZones;
93  
94  	/***
95  	 * Creates an ew instance of ZoneManager
96  	 * 
97  	 * @param idPlayer
98  	 *          id of associated player
99  	 * @param handSPanel
100 	 * @param triggeredSPanel
101 	 * @param delayedSPanel
102 	 * @param additionalZonesPanel
103 	 */
104 	public ZoneManager(int idPlayer, JScrollPane handSPanel,
105 			JScrollPane triggeredSPanel, JScrollPane delayedSPanel,
106 			JPanel additionalZonesPanel) {
107 		final boolean rev = idPlayer == 1;
108 		this.additionalZonesPanel = additionalZonesPanel;
109 		this.play = new Play(rev);
110 		this.hand = new Hand(handSPanel, rev);
111 		this.triggeredBuffer = new TriggeredBuffer(triggeredSPanel, rev);
112 		this.delayedBuffer = new DelayedBuffer(delayedSPanel, rev);
113 		this.idPlayer = idPlayer;
114 		this.additionalZones = new ArrayList<ExpandableZone>();
115 		this.validTargetZones = new ArrayList<MZone>();
116 		this.zonesById = new HashMap<Integer, MZone>();
117 		this.zonesById.put(IdZones.PLAY, play);
118 		this.zonesById.put(IdZones.HAND, hand);
119 		this.zonesById.put(IdZones.TRIGGERED, triggeredBuffer);
120 		this.zonesById.put(IdZones.DELAYED, delayedBuffer);
121 		this.zonesById.put(IdZones.STACK, stack);
122 		this.zonesById.put(IdZones.SIDE, side);
123 	}
124 
125 	/***
126 	 * <ul>
127 	 * Structure of stream : Data[size]
128 	 * <li>play sectors [ZoneSector[]]</li>
129 	 * <li>additional zones [ZoneConfiguration[]]</li>
130 	 * <li>default Zone id [int]</li>
131 	 * </ul>
132 	 * 
133 	 * @param inputStream
134 	 *          the stream containing the layout configuration of this zone for a
135 	 *          specified layout
136 	 * @throws IOException
137 	 *           error during the configuration read.
138 	 */
139 	private void initTbsImpl() {
140 		reset();
141 		additionalZones.clear();
142 		validTargetZones.clear();
143 		additionalZonesPanel.removeAll();
144 		final boolean rev = idPlayer == 1;
145 		for (ZoneConfiguration zoneConfiguration : additionalZoneConfigurations) {
146 			final JScrollPane sPanel = new JScrollPane(
147 					ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
148 					ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
149 			ExpandableZone zone = new ExpandableZone(zoneConfiguration, sPanel, rev);
150 			additionalZones.add(zone);
151 			if (zone.canBeGathered()) {
152 				sPanel.setPreferredSize(new Dimension((IdConst.STD_WIDTH + 10) / 2,
153 						CardFactory.cardHeight + 10));
154 			}
155 		}
156 		validTargetZones.add(play);
157 		validTargetZones.add(hand);
158 		validTargetZones.add(stack);
159 		validTargetZones.add(side);
160 
161 		for (ExpandableZone zone : additionalZones) {
162 			if (zone.canBeGathered()) {
163 				if (!rev || !Configuration.getBoolean("reverseSide", false)) {
164 					additionalZonesPanel.add(zone.superPanel, zone.zoneConfiguration
165 							.getLayoutConstraintYou());
166 				} else {
167 					additionalZonesPanel.add(zone.superPanel, zone.zoneConfiguration
168 							.getLayoutConstraintOpponent());
169 				}
170 			}
171 			this.zonesById.put(zone.getZoneId(), zone);
172 			validTargetZones.add(zone);
173 		}
174 		TableTop.getInstance().fillAdditionalZones(StackManager.PLAYERS[idPlayer],
175 				additionalZones);
176 	}
177 
178 	/***
179 	 * <ul>
180 	 * Structure of stream : Data[size]
181 	 * <li>play sectors [ZoneSector[]]</li>
182 	 * <li>additional zones [ZoneConfiguration[]]</li>
183 	 * <li>default Zone id [int]</li>
184 	 * </ul>
185 	 * 
186 	 * @param inputStream
187 	 *          the stream containing the layout configuration of this zone for a
188 	 *          specified layout
189 	 * @throws IOException
190 	 *           error during the configuration read.
191 	 */
192 	public static void initTbs(InputStream inputStream) throws IOException {
193 		additionalZoneConfigurations = new ZoneConfiguration[inputStream.read()];
194 		for (int i = 0; i < additionalZoneConfigurations.length; i++) {
195 			additionalZoneConfigurations[i] = new ZoneConfiguration(inputStream, i
196 					+ IdZones.FIRST_ADDITIONAL_ZONE);
197 		}
198 		defaultZoneId = inputStream.read();
199 		for (Player player : StackManager.PLAYERS) {
200 			player.zoneManager.initTbsImpl();
201 		}
202 	}
203 
204 	/***
205 	 * return the container corresponding to the specified idZone
206 	 * 
207 	 * @param idZone
208 	 *          idplace of matched container
209 	 * @return the container of a specified idZone
210 	 */
211 	public MZone getContainer(int idZone) {
212 		return zonesById.get(idZone);
213 	}
214 
215 	/***
216 	 * 
217 	 */
218 	public static void updateReversed() {
219 		if (StackManager.PLAYERS[1] != null) {
220 			for (Player player : StackManager.PLAYERS) {
221 				final ZoneManager zoneManager = player.zoneManager;
222 				zoneManager.play.updateReversed();
223 				zoneManager.hand.updateReversed();
224 				boolean rev = zoneManager.idPlayer == 1;
225 				if (!zoneManager.additionalZones.isEmpty()) {
226 					zoneManager.additionalZonesPanel.removeAll();
227 					for (ExpandableZone zone : zoneManager.additionalZones) {
228 						if (zone.canBeGathered()) {
229 							if (rev || !Configuration.getBoolean("reverseSide", false)) {
230 								zoneManager.additionalZonesPanel.add(zone.superPanel,
231 										zone.zoneConfiguration.getLayoutConstraintYou());
232 							} else {
233 								zoneManager.additionalZonesPanel.add(zone.superPanel,
234 										zone.zoneConfiguration.getLayoutConstraintOpponent());
235 							}
236 							zone.updateReversed();
237 						}
238 					}
239 				}
240 			}
241 		}
242 	}
243 
244 	/***
245 	 * Set the zone attribut to their default value, and remove all components
246 	 */
247 	public void reset() {
248 		hand.reset();
249 		play.reset();
250 		stack.reset();
251 		delayedBuffer.reset();
252 		triggeredBuffer.reset();
253 		for (MZone zone : additionalZones) {
254 			zone.reset();
255 		}
256 	}
257 
258 	/***
259 	 * Checks all cards corresponding to the specified constraints
260 	 * 
261 	 * @param test
262 	 *          applied to count valid cards
263 	 * @param ability
264 	 *          is the ability owning this test. The card component of this
265 	 *          ability should correspond to the card owning this test too.
266 	 * @return amount of card matching with the specified test
267 	 */
268 	public int countAllCardsOf(Test test, Ability ability) {
269 		int result = 0;
270 		for (MZone zone : validTargetZones) {
271 			result += zone.countAllCardsOf(test, ability);
272 		}
273 		return result;
274 	}
275 
276 	/***
277 	 * Checks all cards corresponding to the specified constraints.
278 	 * 
279 	 * @param test
280 	 *          applied to count valid cards
281 	 * @param ability
282 	 *          is the ability owning this test. The card component of this
283 	 *          ability should correspond to the card owning this test too.
284 	 * @param limit
285 	 *          is the desired count.
286 	 * @param canBePreempted
287 	 *          <code>true</code> if the valid targets can be derterminated
288 	 *          before runtime.
289 	 * @return amount of cards matching with the specified test. Highest value is
290 	 *         <code>limit</code>.
291 	 */
292 	public int countAllCardsOf(Test test, Ability ability, int limit,
293 			boolean canBePreempted) {
294 		int result = 0;
295 		for (MZone zone : validTargetZones) {
296 			if (result >= limit) {
297 				break;
298 			}
299 			result += zone.countAllCardsOf(test, ability, limit - result,
300 					canBePreempted);
301 		}
302 		return result;
303 	}
304 
305 	/***
306 	 * Update some optimization, painter,... etc depending on the current Look And
307 	 * Feel.
308 	 */
309 	public static void updateLookAndFeel() {
310 		if (MUIManager.LF_SUBSTANCE_CLASSNAME.equals(UIManager.getLookAndFeel()
311 				.getClass().getName()))
312 			bgDelegate = new Object();
313 		else {
314 			bgDelegate = null;
315 		}
316 	}
317 
318 	/***
319 	 * Checks all cards corresponding to this constraints
320 	 * 
321 	 * @param test
322 	 *          applied to count valid cards
323 	 * @param list
324 	 *          the list containing the founded cards
325 	 * @param ability
326 	 *          is the ability owning this test. The card component of this
327 	 *          ability should correspond to the card owning this test too.
328 	 */
329 	public void checkAllCardsOf(Test test, List<Targetable> list, Ability ability) {
330 		for (MZone zone : validTargetZones) {
331 			zone.checkAllCardsOf(test, list, ability);
332 		}
333 	}
334 
335 	/***
336 	 * Fill the player's init zone with cards found in the given InputFile
337 	 * 
338 	 * @param deck
339 	 *          the deck of this player.
340 	 * @param dbFile
341 	 *          opened file read containing the available cards
342 	 * @throws IOException
343 	 *           If some other I/O error occurs
344 	 */
345 	public void giveCards(Deck deck, FileInputStream dbFile) throws IOException {
346 		MZone giveToZone = getContainer(defaultZoneId);
347 		giveToZone.setVisible(false);
348 		DeckReader.fillZone(deck, dbFile, getContainer(defaultZoneId),
349 				StackManager.PLAYERS[idPlayer]);
350 		giveToZone.setVisible(true);
351 	}
352 
353 	/***
354 	 * Save wallpaper name and back colors of this panel to a specifeid output
355 	 * stream.
356 	 */
357 	private void saveSettingsInternal() {
358 		play.saveSettings();
359 		hand.saveSettings();
360 		triggeredBuffer.saveSettings();
361 		delayedBuffer.saveSettings();
362 		for (MZone zone : additionalZones) {
363 			zone.saveSettings();
364 		}
365 	}
366 
367 	/***
368 	 * @param sideSPanel
369 	 * @param stackSPanel
370 	 */
371 	public static void init(JScrollPane sideSPanel, JScrollPane stackSPanel) {
372 		side = new Side(sideSPanel);
373 		stack = new Stack(stackSPanel);
374 		expandedPanel = new JExpandedPanel();
375 		expandedPanel.setVisible(false);
376 		MagicUIComponents.magicForm.getContentPane().add(expandedPanel, 0);
377 	}
378 
379 	/***
380 	 * Save editable string settings of zones.
381 	 */
382 	public static void saveSettings() {
383 		StackManager.PLAYERS[0].zoneManager.saveSettingsInternal();
384 		StackManager.PLAYERS[1].zoneManager.saveSettingsInternal();
385 		side.saveSettings();
386 		stack.saveSettings();
387 	}
388 
389 	/***
390 	 * Return the zone name corresponding to the given zone id.
391 	 * 
392 	 * @param idZone
393 	 *          the zone id.
394 	 * @return the zone name corresponding to the given zone id.
395 	 */
396 	public static String getZoneName(int idZone) {
397 		return StackManager.PLAYERS[0].zoneManager.getContainer(idZone)
398 				.getZoneName();
399 	}
400 
401 	/***
402 	 * Return All available zones.
403 	 * 
404 	 * @return All available zones.
405 	 */
406 	public List<MZone> getValidTargetZones() {
407 		return validTargetZones;
408 	}
409 
410 	/***
411 	 * hand of this player
412 	 */
413 	public Hand hand;
414 
415 	/***
416 	 * play zone of this player
417 	 */
418 	public Play play;
419 
420 	/***
421 	 * triggered buffer of this player (TBZ)
422 	 */
423 	public TriggeredBuffer triggeredBuffer;
424 
425 	/***
426 	 * delayed buffer of this player (DBZ)
427 	 */
428 	public DelayedBuffer delayedBuffer;
429 
430 	/***
431 	 * shared stack of players
432 	 */
433 	public static Stack stack;
434 
435 	/***
436 	 * shared side of players
437 	 */
438 	public static Side side;
439 
440 	/***
441 	 * Is the controller of this zone manager
442 	 */
443 	private int idPlayer;
444 
445 	/***
446 	 * The optional Substance background painter.
447 	 */
448 	static Object bgDelegate;
449 
450 }