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