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.clickable.targetable.card;
21  
22  import java.awt.Color;
23  import java.awt.Component;
24  import java.awt.Image;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.net.URL;
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.TreeMap;
31  
32  import javax.swing.Icon;
33  import javax.swing.ImageIcon;
34  import javax.swing.JMenuItem;
35  import javax.swing.JPopupMenu;
36  
37  import net.sf.magicproject.clickable.targetable.player.Player;
38  import net.sf.magicproject.database.DatabaseFactory;
39  import net.sf.magicproject.deckbuilder.MdbLoader;
40  import net.sf.magicproject.stack.StackManager;
41  import net.sf.magicproject.token.IdConst;
42  import net.sf.magicproject.tools.Configuration;
43  import net.sf.magicproject.tools.MToolKit;
44  import net.sf.magicproject.tools.Picture;
45  import net.sf.magicproject.tools.StatePicture;
46  import net.sf.magicproject.ui.MagicUIComponents;
47  import net.sf.magicproject.ui.TooltipFilter;
48  import net.sf.magicproject.ui.UIHelper;
49  import net.sf.magicproject.ui.i18n.LanguageManager;
50  import net.sf.magicproject.ui.i18n.LanguageManagerMDB;
51  import net.sf.magicproject.zone.MZone;
52  
53  /***
54   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
55   * @since 0.80
56   */
57  public final class CardFactory {
58  
59  	/***
60  	 * The key identifying the "gathered" zone text/action.
61  	 */
62  	public static final String STR_GATHER = "gather";
63  
64  	/***
65  	 * The key identifying the "expand" zone text/action.
66  	 */
67  	public static final String STR_EXPAND = "expand";
68  
69  	private static final float CONFIG_SCALE = 0.25f;
70  
71  	/***
72  	 * Rotate angle * PI
73  	 */
74  	public static final double ROTATE_SCALE = 0.015625d * 2 * Math.PI;
75  
76  	private static final String CONFIG_KEY_SCALE = "scale";
77  
78  	/***
79  	 * The color identifying the playable activated abilities.
80  	 */
81  	public static final Color ACTIVATED_COLOR = Color.yellow;
82  
83  	/***
84  	 * Custom colors of Power/Toughness
85  	 */
86  	public static Color powerToughnessColor;
87  
88  	/***
89  	 * Creates a new instance of the CardFactory.
90  	 */
91  	private CardFactory() {
92  		super();
93  	}
94  
95  	/***
96  	 * Initialize the preview card picture
97  	 * 
98  	 * @return the preview card picture
99  	 */
100 	public static Picture initPreview() {
101 		try {
102 			DatabaseFactory.backImage = Picture.loadImage(
103 					MToolKit.getTbsPicture(MdbLoader.backPicture, false),
104 					new URL(MdbLoader.artURL + "/" + MdbLoader.backPicture)).getContent();
105 		} catch (Throwable e) {
106 			// ignore this error
107 		}
108 		try {
109 			if (DatabaseFactory.backImage == null) {
110 				DatabaseFactory.backImage = Picture.loadImage(
111 						MToolKit.getTbsPicture("default.jpg"), null).getContent();
112 			}
113 			try {
114 				DatabaseFactory.damageImage = Picture.loadImage(
115 						MToolKit.getTbsPicture(MdbLoader.damagePicture, false),
116 						new URL(MdbLoader.artURL + "/" + MdbLoader.damagePicture))
117 						.getContent();
118 			} catch (Throwable e) {
119 				// ignore this error
120 			}
121 			if (DatabaseFactory.damageImage == null) {
122 				DatabaseFactory.damageImage = Picture.loadImage(
123 						MToolKit.getTbsPicture("default.jpg"), null).getContent();
124 			}
125 			DatabaseFactory.scaledBackImage = Picture.getScaledImage(DatabaseFactory.backImage);
126 			DatabaseFactory.damageScaledImage= Picture.getScaledImage(DatabaseFactory.damageImage);
127 		} catch (Throwable e) {
128 			// ignore this error
129 		}
130 		previewCard = new Picture(IdConst.STD_WIDTH, IdConst.STD_HEIGHT);
131 		return previewCard;
132 	}
133 
134 	/***
135 	 * Return an instance of CardModel. There is only one instance of CardModel by
136 	 * card having the same name.
137 	 * 
138 	 * @param cardName
139 	 *          the card name
140 	 * @return a new instance of CardModel if this card has not yet been loaded,
141 	 *         or a shared instance.
142 	 */
143 	public static CardModel getCardModel(String cardName) {
144 		CardModel res = loadedCards.get(cardName);
145 		if (res == null) {
146 			res = new CardModelImpl(cardName);
147 			loadedCards.put(cardName, res);
148 		}
149 		return res;
150 	}
151 
152 	/***
153 	 * Return an instance of CardModel. There is only one instance of CardModel by
154 	 * card withe the same name.
155 	 * 
156 	 * @param cardName
157 	 *          the card name
158 	 * @return a newly created instance of CardModel if this card has not yet been
159 	 *         loaded, or a shared instance.
160 	 * @param inputStream
161 	 *          the input stream containing the data of this card.
162 	 */
163 	public static CardModel getCardModel(String cardName, InputStream inputStream) {
164 		if (cardName.startsWith("_")) {
165 			String realCardName = cardName.substring(1);
166 			CardModel res = loadedCards.get(realCardName);
167 			if (res == null) {
168 				if (inputStream == null) {
169 					// MDB is not available
170 					return new CardModelImpl(realCardName);
171 				}
172 				res = new CardModelImpl(realCardName, inputStream);
173 				loadedCards.put(realCardName, res);
174 			} else if (inputStream != null) {
175 				// consume the stream
176 				new CardModelImpl("", inputStream);
177 			}
178 			return res;
179 		}
180 
181 		CardModel res = loadedCards.get(cardName);
182 		if (res == null) {
183 			res = new CardModelImpl(cardName, inputStream);
184 			loadedCards.put(cardName, res);
185 		}
186 		return res;
187 	}
188 
189 	/***
190 	 * All settings defined in the properties file and relating cards are managed
191 	 * here. Also, initialize the tooltip headers and topics to display fastest
192 	 * the tooltip of card.
193 	 */
194 	public static void initSettings() {
195 		ttPower = "<br><b>" + LanguageManager.getString("power") + ": </b>";
196 		ttToughness = "<br><b>" + LanguageManager.getString("toughness") + ": </b>";
197 		ttState = "<br><b>" + LanguageManager.getString("states") + ": </b>";
198 		ttDamage = "<br><b>" + LanguageManager.getString("damages") + ": </b>";
199 		ttProperties = "<br><b>" + LanguageManager.getString("properties")
200 				+ ": </b>";
201 		ttColors = "<br><b>" + LanguageManager.getString("colors") + ": </b>";
202 		ttTypes = "<br><b>" + LanguageManager.getString("types") + ": </b>";
203 		ttHeader = "<html><b>" + LanguageManager.getString("cardname") + ": </b>";
204 		ttHeaderAbility = "<html><b>"
205 				+ LanguageManager.getString("activatedability")
206 				+ ": </b><br>&nbsp;&nbsp;";
207 
208 		ttAbility = "<br><br><b>" + LanguageManager.getString("activatedability")
209 				+ ": </b><font color='#336600'>";
210 		ttAbiltityEnd = "</font>";
211 
212 		ttManacost = "<br><b>" + LanguageManager.getString("manacost") + " :</b>";
213 		ttManapaid = ")<br><b>" + LanguageManager.getString("manapaid") + " :</b>";
214 
215 		ttAdvancedAability = "<br><br><img src='file:///"
216 				+ MToolKit.getIconPath("warn.gif") + "'><font color='#660000'><b>"
217 				+ LanguageManager.getString("advanceactivatedability") + ": </b>";
218 		ttAdvancedAabilityEnd = "</font>";
219 
220 		// credits
221 		ttRulesAuthor = "<br><br><b>" + LanguageManager.getString("rulesauthor")
222 				+ ": </b>";
223 
224 		ttSource = "<br><b>" + LanguageManager.getString("source") + ": </b>";
225 
226 		contextMenu = new JPopupMenu(LanguageManager.getString("options"));
227 		contextMenu.setFont(MToolKit.defaultFont);
228 		countItem = new JMenuItem("", UIHelper.getIcon("count.gif"));
229 		countItem.setFont(MToolKit.defaultFont);
230 		expandItem = new JMenuItem(LanguageManager.getString(STR_EXPAND), UIHelper
231 				.getIcon(STR_EXPAND + IdConst.TYPE_PIC));
232 		expandItem.setToolTipText("<html>" + MagicUIComponents.HTML_ICON_TIP
233 				+ LanguageManager.getString("expandTTtip2"));
234 		expandItem.setActionCommand(STR_EXPAND);
235 		expandItem.addActionListener(SystemCard.instance);
236 		expandItem.setFont(MToolKit.defaultFont);
237 		gatherItem = new JMenuItem(LanguageManager.getString(STR_GATHER), UIHelper
238 				.getIcon(STR_GATHER + IdConst.TYPE_PIC));
239 		gatherItem.setToolTipText("<html>" + MagicUIComponents.HTML_ICON_TIP
240 				+ LanguageManager.getString("expandTTtip2"));
241 		gatherItem.setActionCommand(STR_GATHER);
242 		gatherItem.addActionListener(SystemCard.instance);
243 		gatherItem.setFont(MToolKit.defaultFont);
244 		javaDebugItem = new JMenuItem(LanguageManager.getString("javadebug"),
245 				UIHelper.getIcon("javadebug.gif"));
246 		javaDebugItem.addActionListener(SystemCard.instance);
247 		databaseCardInfoItem = new JMenuItem(LanguageManager
248 				.getString("databasecard"), UIHelper.getIcon("databasecard.gif"));
249 		databaseCardInfoItem.addActionListener(SystemCard.instance);
250 		updateColor(Configuration.getString("border-color", "auto"));
251 		updateScale();
252 	}
253 
254 	/***
255 	 * Update the scale, sizes and random angle of all cards of current game.
256 	 */
257 	public static void updateAllCardsUI() {
258 		updateScale();
259 		for (Player player : StackManager.PLAYERS) {
260 			for (MZone zone : player.zoneManager.getValidTargetZones()) {
261 				for (Component card : zone.getComponents()) {
262 					((MCard) card).getMUI().updateMUI();
263 					((MCard) card).getDatabase().updateMUI();
264 					((MCard) card).getMUI().updateSizes();
265 				}
266 			}
267 		}
268 	}
269 
270 	/***
271 	 * Update the card border's color and other UI colors requiring only a global
272 	 * repaint to update the UI.
273 	 * 
274 	 * @param colorStr
275 	 *          is the new card border's color
276 	 */
277 	public static void updateColor(String colorStr) {
278 		if (colorStr != null) {
279 			if ("white".equals(colorStr)) {
280 				borderColor = Color.WHITE;
281 			} else if ("gold".equals(colorStr)) {
282 				borderColor = Color.YELLOW.darker().darker();
283 			} else if ("black".equals(colorStr)) {
284 				borderColor = Color.BLACK;
285 			} else {
286 				// Auto
287 				borderColor = null;
288 			}
289 		}
290 		powerToughnessColor = new Color(Configuration.getInt("powerToughnessColor",
291 				Color.BLUE.getRGB()));
292 	}
293 
294 	/***
295 	 * Save editable string settings of cards
296 	 */
297 	public static void saveSettings() {
298 		if (Color.WHITE.equals(borderColor)) {
299 			borderColor = Color.WHITE;
300 			Configuration.setProperty("border-color", "white");
301 		} else if (Color.YELLOW.darker().darker().equals(borderColor)) {
302 			Configuration.setProperty("border-color", "gold");
303 		} else if (Color.BLACK.equals(borderColor)) {
304 			Configuration.setProperty("border-color", "black");
305 		} else {
306 			// Auto
307 			Configuration.setProperty("border-color", "auto");
308 		}
309 	}
310 
311 	/***
312 	 * Read from the specified stream the state picture options. The current
313 	 * offset of the stream must pointing on the number of state pictures.
314 	 * <ul>
315 	 * Structure of InputStream : Data[size]
316 	 * <li>number of states [1]</li>
317 	 * <li>state picture name i + \0 [...]</li>
318 	 * <li>state value i + \0 [...]</li>
319 	 * <li>state picture x i [2]</li>
320 	 * <li>state picture y i [2]</li>
321 	 * <li>state picture width i [2]</li>
322 	 * <li>state picture height i [2]</li>
323 	 * </ul>
324 	 * <br>
325 	 * Read from the specified stream the tooltip filters. The current offset of
326 	 * the stream must pointing on the number of tooltip filters.
327 	 * <ul>
328 	 * Structure of stream : Data[size]
329 	 * <li>display powerANDtoughness yes=1,no=0 [1]</li>
330 	 * <li>display states yes=1,no=0 [1]</li>
331 	 * <li>display types yes=1,no=0 [1]</li>
332 	 * <li>display colors yes=1,no=0 [1]</li>
333 	 * <li>display properties yes=1,no=0 [1]</li>
334 	 * <li>display damage yes=1,no=0 [1]</li>
335 	 * <li>filter [...]</li>
336 	 * </ul>
337 	 * 
338 	 * @param inputFile
339 	 *          the stream containing settings.
340 	 * @throws IOException
341 	 *           If some other I/O error occurs
342 	 */
343 	public static void init(InputStream inputFile) throws IOException {
344 		loadedCards.clear();
345 		// load state pictures of card
346 		statePictures = new StatePicture[inputFile.read()];
347 		for (int i = 0; i < statePictures.length; i++) {
348 			statePictures[i] = new StatePicture(inputFile);
349 		}
350 
351 		// load tooltip filters
352 		tooltipFilters = new TooltipFilter[inputFile.read()];
353 		for (int i = 0; i < tooltipFilters.length; i++) {
354 			tooltipFilters[i] = new TooltipFilter(inputFile);
355 		}
356 
357 		// read types name exportation (this list must be sorted)
358 		int count = inputFile.read();
359 		exportedTypeNames = new String[count];
360 		exportedTypeValues = new int[count];
361 		for (int i = 0; i < count; i++) {
362 			exportedTypeNames[i] = LanguageManagerMDB.getString(MToolKit
363 					.readString(inputFile));
364 			exportedTypeValues[i] = MToolKit.readInt16(inputFile);
365 		}
366 
367 		// read properties name exportation (this list must be sorted)
368 		exportedProperties = new TreeMap<Integer, String>();
369 		for (int i = MToolKit.readInt16(inputFile); i-- > 0;) {
370 			final Integer key = new Integer(MToolKit.readInt16(inputFile));
371 			exportedProperties.put(key, LanguageManagerMDB.getString(MToolKit
372 					.readString(inputFile)));
373 		}
374 
375 		// property pictures
376 		if (propertyPicturesHTML != null) {
377 			propertyPicturesHTML.clear();
378 			propertyPictures.clear();
379 		} else {
380 			propertyPictures = new HashMap<Integer, Image>();
381 			propertyPicturesHTML = new HashMap<Integer, String>();
382 		}
383 		for (int i = MToolKit.readInt16(inputFile); i-- > 0;) {
384 			final int property = MToolKit.readInt16(inputFile);
385 			final Integer key = new Integer(property);
386 			final String pictureStr = MToolKit.readString(inputFile);
387 			if (pictureStr.length() > 0) {
388 				propertyPicturesHTML.put(key, "<img src='file:///"
389 						+ MToolKit.getTbsHtmlPicture("properties/" + pictureStr)
390 						+ "'>&nbsp;");
391 				propertyPictures.put(key, Picture.loadImage(MToolKit
392 						.getTbsPicture("properties/" + pictureStr)));
393 			}
394 		}
395 
396 		// Add system card
397 		loadedCards.put("system", new CardModelImpl("system"));
398 	}
399 
400 	/***
401 	 * Update the scaling transformation for all cards
402 	 */
403 	public static void updateScale() {
404 		float scale = getScale();
405 		cardWidth = (int) (IdConst.STD_WIDTH * scale);
406 		cardHeight = (int) (IdConst.STD_HEIGHT * scale);
407 
408 		// TODO perspective view for card --> not yet implemented
409 		// atImageSpace.concatenate(new AffineTransform(0.8f,0,-0.1f,1,10,0));
410 	}
411 
412 	/***
413 	 * Returns the scale of images of cards.
414 	 * 
415 	 * @return the scale of images of cards.
416 	 */
417 	public static float getScale() {
418 		return Configuration.getFloat(CONFIG_KEY_SCALE, CONFIG_SCALE);
419 	}
420 
421 	/***
422 	 * The loaded cards. Card name is the key.
423 	 */
424 	private static Map<String, CardModel> loadedCards = new HashMap<String, CardModel>(
425 			100);
426 
427 	/***
428 	 * the state pictures check during each paint of cards
429 	 */
430 	static StatePicture[] statePictures;
431 
432 	/***
433 	 * the tooltip filters of cards
434 	 */
435 	static TooltipFilter[] tooltipFilters;
436 
437 	/***
438 	 * The associated menu to context menu of the clicked card.
439 	 */
440 	static JPopupMenu contextMenu;
441 
442 	/***
443 	 * Scaled height of card to display
444 	 */
445 	public static int cardHeight;
446 
447 	/***
448 	 * Scaled width of card to display
449 	 */
450 	public static int cardWidth;
451 
452 	/***
453 	 * The border color of all card
454 	 */
455 	public static Color borderColor;
456 
457 	/***
458 	 * The "power" topic string part of tooltip
459 	 */
460 	static String ttPower;
461 
462 	/***
463 	 * The "toughness" topic string part of tooltip
464 	 */
465 	static String ttToughness;
466 
467 	/***
468 	 * The "state" topic string part of tooltip
469 	 */
470 	static String ttState;
471 
472 	/***
473 	 * The "damage" topic string part of tooltip
474 	 */
475 	static String ttDamage;
476 
477 	/***
478 	 * The "properties" topic string part of tooltip
479 	 */
480 	static String ttProperties;
481 
482 	/***
483 	 * The "colors" topic string part of tooltip
484 	 */
485 	static String ttColors;
486 
487 	/***
488 	 * The "rules author" topics string part of tooltip
489 	 */
490 	static String ttRulesAuthor;
491 
492 	/***
493 	 * The "activated ability" topic string part of tooltip
494 	 */
495 	static String ttAbility;
496 
497 	static String ttAbiltityEnd;
498 
499 	static String ttAdvancedAability;
500 
501 	static String ttAdvancedAabilityEnd;
502 
503 	/***
504 	 * The "types" topic string part of tooltip
505 	 */
506 	static String ttTypes;
507 
508 	/***
509 	 * The "header" and "cardname" topics string part of tooltip
510 	 */
511 	public static String ttHeader;
512 
513 	/***
514 	 * The "header" and "ability name" topics string part of tooltip
515 	 */
516 	static String ttHeaderAbility;
517 
518 	/***
519 	 * The "count card" item of context menu
520 	 */
521 	public static JMenuItem countItem;
522 
523 	/***
524 	 * The "expand panel" item of context menu
525 	 */
526 	public static JMenuItem expandItem;
527 
528 	/***
529 	 * The "gathered panel" item of context menu
530 	 */
531 	public static JMenuItem gatherItem;
532 
533 	/***
534 	 * The available type names.
535 	 */
536 	public static String[] exportedTypeNames;
537 
538 	/***
539 	 * The available type values.
540 	 */
541 	public static int[] exportedTypeValues;
542 
543 	/***
544 	 * The available properties.
545 	 */
546 	public static Map<Integer, String> exportedProperties;
547 
548 	/***
549 	 * The available properties pictures as Html.
550 	 */
551 	public static Map<Integer, String> propertyPicturesHTML;
552 
553 	/***
554 	 * The available properties pictures as Image.
555 	 */
556 	public static Map<Integer, Image> propertyPictures;
557 
558 	/***
559 	 * The warning Icon.
560 	 */
561 	public static final Icon WARNING_PICTURE = new ImageIcon("images/warn.gif");
562 
563 	/***
564 	 * Mana cost header
565 	 */
566 	static String ttManacost;
567 
568 	/***
569 	 * Mana paid header
570 	 */
571 	static String ttManapaid;
572 
573 	/***
574 	 * the back image of all Magic card
575 	 */
576 	public static Picture previewCard = null;
577 
578 	/***
579 	 * The java debug display. Show java attributes of a card.
580 	 */
581 	static JMenuItem javaDebugItem;
582 
583 	/***
584 	 * Activate the the "database" tab of a card.
585 	 */
586 	static JMenuItem databaseCardInfoItem;
587 
588 	/***
589 	 * The "source" topic string part of tooltip
590 	 */
591 	static String ttSource;
592 
593 	/***
594 	 * The last known card name.
595 	 */
596 	static String lastCardName;
597 
598 }