Working Card Rendering
3243
Mage.Client/replay_pid1108.log
Normal file
4232
Mage.Client/replay_pid7632.log
Normal file
3737
Mage.Client/replay_pid8632.log
Normal file
|
@ -277,6 +277,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
try {
|
try {
|
||||||
UIManager.put("desktop", new Color(0, 0, 0, 0));
|
UIManager.put("desktop", new Color(0, 0, 0, 0));
|
||||||
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
|
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
|
||||||
|
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
// stop JSplitPane from eating F6 and F8 or any other function keys
|
// stop JSplitPane from eating F6 and F8 or any other function keys
|
||||||
{
|
{
|
||||||
Object value = UIManager.get("SplitPane.ancestorInputMap");
|
Object value = UIManager.get("SplitPane.ancestorInputMap");
|
||||||
|
|
|
@ -92,6 +92,7 @@ import mage.view.CardView;
|
||||||
import mage.view.CounterView;
|
import mage.view.CounterView;
|
||||||
import mage.view.PermanentView;
|
import mage.view.PermanentView;
|
||||||
import mage.view.StackAbilityView;
|
import mage.view.StackAbilityView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -191,7 +192,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
||||||
gSmall.drawImage(ImageHelper.scaleImage(image, Config.dimensions.frameWidth, Config.dimensions.frameHeight), 0, 0, this);
|
gSmall.drawImage(ImageHelper.scaleImage(image, Config.dimensions.frameWidth, Config.dimensions.frameHeight), 0, 0, this);
|
||||||
|
|
||||||
gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
|
gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
|
||||||
gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
|
gImage.drawString(card.getName()+"TEST", CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
|
||||||
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
||||||
gImage.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_TEXT_MAX_LEFT, POWBOX_TEXT_MAX_TOP);
|
gImage.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_TEXT_MAX_LEFT, POWBOX_TEXT_MAX_TOP);
|
||||||
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||||
|
@ -205,9 +206,9 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
||||||
gImage.dispose();
|
gImage.dispose();
|
||||||
|
|
||||||
gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.nameFontSize));
|
gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.nameFontSize));
|
||||||
gSmall.drawString(card.getName(), Config.dimensions.contentXOffset, Config.dimensions.nameYOffset);
|
gSmall.drawString(card.getName()+"TEST2", Config.dimensions.contentXOffset, Config.dimensions.nameYOffset);
|
||||||
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
if (card.getCardTypes().contains(CardType.CREATURE)) {
|
||||||
gSmall.drawString(card.getPower() + "/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
gSmall.drawString(card.getPower() + "/-/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
||||||
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
} else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||||
gSmall.drawString(card.getLoyalty(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
gSmall.drawString(card.getLoyalty(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop);
|
||||||
}
|
}
|
||||||
|
@ -319,6 +320,19 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
||||||
return sbType.toString();
|
return sbType.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void drawDetailed(Graphics2D g) {
|
||||||
|
// Get the size of the card
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.drawRoundRect(0, 0, width, height, 4, 4);
|
||||||
|
g.setColor(Color.white);
|
||||||
|
g.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
|
||||||
|
g.drawString(card.getName(), 0, 0);
|
||||||
|
Logger.getLogger(Card.class).info("Drawing");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
@ -355,6 +369,8 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent(Graphics graphics) {
|
public void paintComponent(Graphics graphics) {
|
||||||
|
drawDetailed((Graphics2D)graphics);
|
||||||
|
/*
|
||||||
Graphics2D g2 = (Graphics2D) graphics;
|
Graphics2D g2 = (Graphics2D) graphics;
|
||||||
g2.drawImage(small, 0, 0, this);
|
g2.drawImage(small, 0, 0, this);
|
||||||
|
|
||||||
|
@ -365,6 +381,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
||||||
g2.setColor(Color.BLACK);
|
g2.setColor(Color.BLACK);
|
||||||
}
|
}
|
||||||
g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1);
|
g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,21 +34,16 @@
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Component id="panelControl" alignment="0" pref="467" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
<Component id="panelCardArea" alignment="0" max="32767" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="panelControl" pref="703" max="32767" attributes="0"/>
|
|
||||||
<Component id="panelCardArea" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="panelControl" min="-2" pref="25" max="-2" attributes="0"/>
|
<Component id="panelControl" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||||
<Component id="panelCardArea" pref="86" max="32767" attributes="0"/>
|
<Component id="panelCardArea" pref="179" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -81,15 +76,7 @@
|
||||||
<Component id="lblLandCount" min="-2" max="-2" attributes="0"/>
|
<Component id="lblLandCount" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="lblCreatureCount" min="-2" max="-2" attributes="0"/>
|
<Component id="lblCreatureCount" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="lblSorceryCount" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="lblInstantCount" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="lblEnchantmentCount" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
|
|
||||||
<Component id="lblArtifactCount" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="chkPiles" min="-2" max="-2" attributes="0"/>
|
<Component id="chkPiles" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
<Component id="cbSortBy" min="-2" max="-2" attributes="0"/>
|
<Component id="cbSortBy" min="-2" max="-2" attributes="0"/>
|
||||||
|
@ -97,7 +84,7 @@
|
||||||
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="jToggleCardView" min="-2" max="-2" attributes="0"/>
|
<Component id="jToggleCardView" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="62" max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -109,11 +96,7 @@
|
||||||
<Component id="lblCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="lblCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="lblLandCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="lblLandCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="lblCreatureCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="lblCreatureCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="lblSorceryCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="lblInstantCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="lblEnchantmentCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="chkPiles" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="chkPiles" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="lblArtifactCount" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="cbSortBy" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="cbSortBy" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
<Component id="jToggleListView" min="-2" max="-2" attributes="0"/>
|
||||||
|
@ -177,60 +160,6 @@
|
||||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="lblSorceryCount">
|
|
||||||
<Properties>
|
|
||||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
|
||||||
<Image iconType="3" name="/buttons/type_sorcery.png"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="text" type="java.lang.String" value="999"/>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" value="Number of sorceries."/>
|
|
||||||
<Property name="verticalAlignment" type="int" value="1"/>
|
|
||||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
|
||||||
<Color id="Default Cursor"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="focusable" type="boolean" value="false"/>
|
|
||||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
|
||||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
|
||||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JLabel" name="lblInstantCount">
|
|
||||||
<Properties>
|
|
||||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
|
||||||
<Image iconType="3" name="/buttons/type_instant.png"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="text" type="java.lang.String" value="999"/>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" value="Number of instants."/>
|
|
||||||
<Property name="verticalAlignment" type="int" value="1"/>
|
|
||||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
|
||||||
<Color id="Default Cursor"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="focusable" type="boolean" value="false"/>
|
|
||||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
|
||||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
|
||||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JLabel" name="lblEnchantmentCount">
|
|
||||||
<Properties>
|
|
||||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
|
||||||
<Image iconType="3" name="/buttons/type_enchantment.png"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="text" type="java.lang.String" value="999"/>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" value="Number of enchantments."/>
|
|
||||||
<Property name="verticalAlignment" type="int" value="1"/>
|
|
||||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
|
||||||
<Color id="Default Cursor"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="focusable" type="boolean" value="false"/>
|
|
||||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
|
||||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
|
||||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JCheckBox" name="chkPiles">
|
<Component class="javax.swing.JCheckBox" name="chkPiles">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" value="Piles"/>
|
<Property name="text" type="java.lang.String" value="Piles"/>
|
||||||
|
@ -324,24 +253,6 @@
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleCardViewActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleCardViewActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="lblArtifactCount">
|
|
||||||
<Properties>
|
|
||||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
|
||||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
|
||||||
<Image iconType="3" name="/buttons/type_artifact.png"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="text" type="java.lang.String" value="999"/>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" value="Number of artifacts"/>
|
|
||||||
<Property name="verticalAlignment" type="int" value="1"/>
|
|
||||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
|
||||||
<Color id="Default Cursor"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="focusable" type="boolean" value="false"/>
|
|
||||||
<Property name="inheritsPopupMenu" type="boolean" value="false"/>
|
|
||||||
<Property name="requestFocusEnabled" type="boolean" value="false"/>
|
|
||||||
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JScrollPane" name="panelCardArea">
|
<Container class="javax.swing.JScrollPane" name="panelCardArea">
|
||||||
|
|
|
@ -211,7 +211,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, lblSorceryCount, lblInstantCount, lblEnchantmentCount, lblArtifactCount));
|
mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, null, null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if you use the deck ediot to build a free deck, numbers can be set directly in deck and sideboard
|
// if you use the deck ediot to build a free deck, numbers can be set directly in deck and sideboard
|
||||||
|
@ -418,10 +418,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
this.lblCount.setText(Integer.toString(count));
|
this.lblCount.setText(Integer.toString(count));
|
||||||
this.lblCreatureCount.setText(Integer.toString(creatureCount));
|
this.lblCreatureCount.setText(Integer.toString(creatureCount));
|
||||||
this.lblLandCount.setText(Integer.toString(landCount));
|
this.lblLandCount.setText(Integer.toString(landCount));
|
||||||
this.lblSorceryCount.setText(Integer.toString(sorceryCount));
|
|
||||||
this.lblInstantCount.setText(Integer.toString(instantCount));
|
|
||||||
this.lblEnchantmentCount.setText(Integer.toString(enchantmentCount));
|
|
||||||
this.lblArtifactCount.setText(Integer.toString(artifactCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MageCard addCard(CardView card, BigCard bigCard, UUID gameId) {
|
private MageCard addCard(CardView card, BigCard bigCard, UUID gameId) {
|
||||||
|
@ -482,14 +478,10 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
lblCount = new javax.swing.JLabel();
|
lblCount = new javax.swing.JLabel();
|
||||||
lblLandCount = new javax.swing.JLabel();
|
lblLandCount = new javax.swing.JLabel();
|
||||||
lblCreatureCount = new javax.swing.JLabel();
|
lblCreatureCount = new javax.swing.JLabel();
|
||||||
lblSorceryCount = new javax.swing.JLabel();
|
|
||||||
lblInstantCount = new javax.swing.JLabel();
|
|
||||||
lblEnchantmentCount = new javax.swing.JLabel();
|
|
||||||
chkPiles = new javax.swing.JCheckBox();
|
chkPiles = new javax.swing.JCheckBox();
|
||||||
cbSortBy = new javax.swing.JComboBox();
|
cbSortBy = new javax.swing.JComboBox();
|
||||||
jToggleListView = new javax.swing.JToggleButton();
|
jToggleListView = new javax.swing.JToggleButton();
|
||||||
jToggleCardView = new javax.swing.JToggleButton();
|
jToggleCardView = new javax.swing.JToggleButton();
|
||||||
lblArtifactCount = new javax.swing.JLabel();
|
|
||||||
panelCardArea = new javax.swing.JScrollPane();
|
panelCardArea = new javax.swing.JScrollPane();
|
||||||
cardArea = new javax.swing.JLayeredPane();
|
cardArea = new javax.swing.JLayeredPane();
|
||||||
|
|
||||||
|
@ -537,39 +529,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
lblCreatureCount.setRequestFocusEnabled(false);
|
lblCreatureCount.setRequestFocusEnabled(false);
|
||||||
lblCreatureCount.setVerifyInputWhenFocusTarget(false);
|
lblCreatureCount.setVerifyInputWhenFocusTarget(false);
|
||||||
|
|
||||||
lblSorceryCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
|
||||||
lblSorceryCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_sorcery.png"))); // NOI18N
|
|
||||||
lblSorceryCount.setText("999");
|
|
||||||
lblSorceryCount.setToolTipText("Number of sorceries.");
|
|
||||||
lblSorceryCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
|
||||||
lblSorceryCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
|
||||||
lblSorceryCount.setFocusable(false);
|
|
||||||
lblSorceryCount.setInheritsPopupMenu(false);
|
|
||||||
lblSorceryCount.setRequestFocusEnabled(false);
|
|
||||||
lblSorceryCount.setVerifyInputWhenFocusTarget(false);
|
|
||||||
|
|
||||||
lblInstantCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
|
||||||
lblInstantCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_instant.png"))); // NOI18N
|
|
||||||
lblInstantCount.setText("999");
|
|
||||||
lblInstantCount.setToolTipText("Number of instants.");
|
|
||||||
lblInstantCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
|
||||||
lblInstantCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
|
||||||
lblInstantCount.setFocusable(false);
|
|
||||||
lblInstantCount.setInheritsPopupMenu(false);
|
|
||||||
lblInstantCount.setRequestFocusEnabled(false);
|
|
||||||
lblInstantCount.setVerifyInputWhenFocusTarget(false);
|
|
||||||
|
|
||||||
lblEnchantmentCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
|
||||||
lblEnchantmentCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_enchantment.png"))); // NOI18N
|
|
||||||
lblEnchantmentCount.setText("999");
|
|
||||||
lblEnchantmentCount.setToolTipText("Number of enchantments.");
|
|
||||||
lblEnchantmentCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
|
||||||
lblEnchantmentCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
|
||||||
lblEnchantmentCount.setFocusable(false);
|
|
||||||
lblEnchantmentCount.setInheritsPopupMenu(false);
|
|
||||||
lblEnchantmentCount.setRequestFocusEnabled(false);
|
|
||||||
lblEnchantmentCount.setVerifyInputWhenFocusTarget(false);
|
|
||||||
|
|
||||||
chkPiles.setText("Piles");
|
chkPiles.setText("Piles");
|
||||||
chkPiles.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
chkPiles.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||||
chkPiles.setMargin(new java.awt.Insets(3, 2, 2, 2));
|
chkPiles.setMargin(new java.awt.Insets(3, 2, 2, 2));
|
||||||
|
@ -619,17 +578,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
lblArtifactCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
|
||||||
lblArtifactCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_artifact.png"))); // NOI18N
|
|
||||||
lblArtifactCount.setText("999");
|
|
||||||
lblArtifactCount.setToolTipText("Number of artifacts");
|
|
||||||
lblArtifactCount.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
|
||||||
lblArtifactCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
|
||||||
lblArtifactCount.setFocusable(false);
|
|
||||||
lblArtifactCount.setInheritsPopupMenu(false);
|
|
||||||
lblArtifactCount.setRequestFocusEnabled(false);
|
|
||||||
lblArtifactCount.setVerifyInputWhenFocusTarget(false);
|
|
||||||
|
|
||||||
javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl);
|
javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl);
|
||||||
panelControl.setLayout(panelControlLayout);
|
panelControl.setLayout(panelControlLayout);
|
||||||
panelControlLayout.setHorizontalGroup(
|
panelControlLayout.setHorizontalGroup(
|
||||||
|
@ -641,14 +589,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(lblCreatureCount)
|
.addComponent(lblCreatureCount)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(lblSorceryCount)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(lblInstantCount)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(lblEnchantmentCount)
|
|
||||||
.addGap(4, 4, 4)
|
|
||||||
.addComponent(lblArtifactCount)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(chkPiles)
|
.addComponent(chkPiles)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
@ -656,7 +596,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 62, Short.MAX_VALUE))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
panelControlLayout.setVerticalGroup(
|
panelControlLayout.setVerticalGroup(
|
||||||
panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
@ -666,11 +606,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
.addComponent(lblCount)
|
.addComponent(lblCount)
|
||||||
.addComponent(lblLandCount)
|
.addComponent(lblLandCount)
|
||||||
.addComponent(lblCreatureCount)
|
.addComponent(lblCreatureCount)
|
||||||
.addComponent(lblSorceryCount)
|
.addComponent(chkPiles))
|
||||||
.addComponent(lblInstantCount)
|
|
||||||
.addComponent(lblEnchantmentCount)
|
|
||||||
.addComponent(chkPiles)
|
|
||||||
.addComponent(lblArtifactCount))
|
|
||||||
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
.addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
@ -686,21 +622,27 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 467, Short.MAX_VALUE)
|
||||||
.addGap(1, 1, 1)
|
.addComponent(panelCardArea)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(panelControl, javax.swing.GroupLayout.DEFAULT_SIZE, 703, Short.MAX_VALUE)
|
|
||||||
.addComponent(panelCardArea)))
|
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 0, 0)
|
.addGap(2, 2, 2)
|
||||||
.addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE))
|
.addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed
|
||||||
|
currentView = this;
|
||||||
|
panelCardArea.setViewportView(cardArea);
|
||||||
|
cbSortBy.setEnabled(true);
|
||||||
|
chkPiles.setEnabled(true);
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView");
|
||||||
|
redrawCards();
|
||||||
|
}//GEN-LAST:event_jToggleCardViewActionPerformed
|
||||||
|
|
||||||
private void jToggleListViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleListViewActionPerformed
|
private void jToggleListViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleListViewActionPerformed
|
||||||
currentView = mainModel;
|
currentView = mainModel;
|
||||||
panelCardArea.setViewportView(mainTable);
|
panelCardArea.setViewportView(mainTable);
|
||||||
|
@ -720,15 +662,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
drawCards(sortSetting);
|
drawCards(sortSetting);
|
||||||
}//GEN-LAST:event_chkPilesActionPerformed
|
}//GEN-LAST:event_chkPilesActionPerformed
|
||||||
|
|
||||||
private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed
|
|
||||||
currentView = this;
|
|
||||||
panelCardArea.setViewportView(cardArea);
|
|
||||||
cbSortBy.setEnabled(true);
|
|
||||||
chkPiles.setEnabled(true);
|
|
||||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView");
|
|
||||||
redrawCards();
|
|
||||||
}//GEN-LAST:event_jToggleCardViewActionPerformed
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.ButtonGroup bgView;
|
private javax.swing.ButtonGroup bgView;
|
||||||
private javax.swing.JLayeredPane cardArea;
|
private javax.swing.JLayeredPane cardArea;
|
||||||
|
@ -736,13 +669,9 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
||||||
private javax.swing.JCheckBox chkPiles;
|
private javax.swing.JCheckBox chkPiles;
|
||||||
private javax.swing.JToggleButton jToggleCardView;
|
private javax.swing.JToggleButton jToggleCardView;
|
||||||
private javax.swing.JToggleButton jToggleListView;
|
private javax.swing.JToggleButton jToggleListView;
|
||||||
private javax.swing.JLabel lblArtifactCount;
|
|
||||||
private javax.swing.JLabel lblCount;
|
private javax.swing.JLabel lblCount;
|
||||||
private javax.swing.JLabel lblCreatureCount;
|
private javax.swing.JLabel lblCreatureCount;
|
||||||
private javax.swing.JLabel lblEnchantmentCount;
|
|
||||||
private javax.swing.JLabel lblInstantCount;
|
|
||||||
private javax.swing.JLabel lblLandCount;
|
private javax.swing.JLabel lblLandCount;
|
||||||
private javax.swing.JLabel lblSorceryCount;
|
|
||||||
private javax.swing.JScrollPane panelCardArea;
|
private javax.swing.JScrollPane panelCardArea;
|
||||||
private javax.swing.JPanel panelControl;
|
private javax.swing.JPanel panelControl;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
|
@ -16,31 +16,26 @@
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="deckAreaSplitPane" alignment="0" pref="740" max="32767" attributes="0"/>
|
<Component id="deckAreaSplitPane" alignment="0" pref="918" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="deckAreaSplitPane" alignment="0" pref="568" max="32767" attributes="0"/>
|
<Component id="deckAreaSplitPane" alignment="0" pref="377" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JSplitPane" name="deckAreaSplitPane">
|
<Container class="javax.swing.JSplitPane" name="deckAreaSplitPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="orientation" type="int" value="0"/>
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
<Property name="resizeWeight" type="double" value="0.8"/>
|
<Border info="null"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="resizeWeight" type="double" value="0.6"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="mage.client.cards.CardsList" name="deckList">
|
|
||||||
<Constraints>
|
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
|
||||||
<JSplitPaneConstraints position="left"/>
|
|
||||||
</Constraint>
|
|
||||||
</Constraints>
|
|
||||||
</Component>
|
|
||||||
<Component class="mage.client.cards.CardsList" name="sideboardList">
|
<Component class="mage.client.cards.CardsList" name="sideboardList">
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
|
@ -48,6 +43,13 @@
|
||||||
</Constraint>
|
</Constraint>
|
||||||
</Constraints>
|
</Constraints>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="mage.client.cards.CardsList" name="deckList">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
|
<JSplitPaneConstraints position="left"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
|
|
@ -118,23 +118,23 @@ public class DeckArea extends javax.swing.JPanel {
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
deckAreaSplitPane = new javax.swing.JSplitPane();
|
deckAreaSplitPane = new javax.swing.JSplitPane();
|
||||||
deckList = new mage.client.cards.CardsList();
|
|
||||||
sideboardList = new mage.client.cards.CardsList();
|
sideboardList = new mage.client.cards.CardsList();
|
||||||
|
deckList = new mage.client.cards.CardsList();
|
||||||
|
|
||||||
deckAreaSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
deckAreaSplitPane.setBorder(null);
|
||||||
deckAreaSplitPane.setResizeWeight(0.8);
|
deckAreaSplitPane.setResizeWeight(0.6);
|
||||||
deckAreaSplitPane.setLeftComponent(deckList);
|
|
||||||
deckAreaSplitPane.setRightComponent(sideboardList);
|
deckAreaSplitPane.setRightComponent(sideboardList);
|
||||||
|
deckAreaSplitPane.setLeftComponent(deckList);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE)
|
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 918, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE)
|
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class UpdateCountsCallback {
|
||||||
private final javax.swing.JLabel lblCount;
|
private final javax.swing.JLabel lblCount;
|
||||||
private final javax.swing.JLabel lblCreatureCount;
|
private final javax.swing.JLabel lblCreatureCount;
|
||||||
private final javax.swing.JLabel lblLandCount;
|
private final javax.swing.JLabel lblLandCount;
|
||||||
private final javax.swing.JLabel lblSoerceryCount;
|
private final javax.swing.JLabel lblSorceryCount;
|
||||||
private final javax.swing.JLabel lblInstantCount;
|
private final javax.swing.JLabel lblInstantCount;
|
||||||
private final javax.swing.JLabel lblEnchantmentCount;
|
private final javax.swing.JLabel lblEnchantmentCount;
|
||||||
private final javax.swing.JLabel lblArtifactCount;
|
private final javax.swing.JLabel lblArtifactCount;
|
||||||
|
@ -20,19 +20,26 @@ public class UpdateCountsCallback {
|
||||||
this.lblCount = count;
|
this.lblCount = count;
|
||||||
this.lblCreatureCount = creatures;
|
this.lblCreatureCount = creatures;
|
||||||
this.lblLandCount = lands;
|
this.lblLandCount = lands;
|
||||||
this.lblSoerceryCount = sorceries;
|
this.lblSorceryCount = sorceries;
|
||||||
this.lblInstantCount = instants;
|
this.lblInstantCount = instants;
|
||||||
this.lblEnchantmentCount = enchantments;
|
this.lblEnchantmentCount = enchantments;
|
||||||
this.lblArtifactCount = artifacts;
|
this.lblArtifactCount = artifacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(int count, int creatures, int lands, int sorceries, int instants, int enchantments, int artifacts) {
|
public void update(int count, int creatures, int lands, int sorceries, int instants, int enchantments, int artifacts) {
|
||||||
|
if (this.lblCount != null)
|
||||||
this.lblCount.setText(Integer.toString(count));
|
this.lblCount.setText(Integer.toString(count));
|
||||||
|
if (this.lblCreatureCount != null)
|
||||||
this.lblCreatureCount.setText(Integer.toString(creatures));
|
this.lblCreatureCount.setText(Integer.toString(creatures));
|
||||||
|
if (this.lblLandCount != null)
|
||||||
this.lblLandCount.setText(Integer.toString(lands));
|
this.lblLandCount.setText(Integer.toString(lands));
|
||||||
this.lblSoerceryCount.setText(Integer.toString(sorceries));
|
if (this.lblSorceryCount != null)
|
||||||
|
this.lblSorceryCount.setText(Integer.toString(sorceries));
|
||||||
|
if (this.lblInstantCount != null)
|
||||||
this.lblInstantCount.setText(Integer.toString(instants));
|
this.lblInstantCount.setText(Integer.toString(instants));
|
||||||
|
if (this.lblEnchantmentCount != null)
|
||||||
this.lblEnchantmentCount.setText(Integer.toString(enchantments));
|
this.lblEnchantmentCount.setText(Integer.toString(enchantments));
|
||||||
|
if (this.lblArtifactCount != null)
|
||||||
this.lblArtifactCount.setText(Integer.toString(artifacts));
|
this.lblArtifactCount.setText(Integer.toString(artifacts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,11 @@
|
||||||
<Component id="exitButton" min="-2" pref="100" max="-2" attributes="0"/>
|
<Component id="exitButton" min="-2" pref="100" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="tabsPanel" alignment="0" max="32767" attributes="0"/>
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="tabsPanel" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
|
@ -146,7 +150,7 @@
|
||||||
<Property name="toolTipText" type="java.lang.String" value="Write the card's name on the card to make the card name more recognizable."/>
|
<Property name="toolTipText" type="java.lang.String" value="Write the card's name on the card to make the card name more recognizable."/>
|
||||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||||
<Color id="Standardcursor"/>
|
<Color id="Default Cursor"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Events>
|
<Events>
|
||||||
|
@ -3945,7 +3949,7 @@
|
||||||
<Component id="checkBoxEndTurnOthers" min="-2" max="-2" attributes="0"/>
|
<Component id="checkBoxEndTurnOthers" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
<Component id="phases_stopSettings" pref="260" max="32767" attributes="0"/>
|
<Component id="phases_stopSettings" pref="266" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -4147,11 +4151,15 @@
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="panelCardImages" alignment="0" max="32767" attributes="0"/>
|
<Component id="panelCardImages" max="32767" attributes="0"/>
|
||||||
<Component id="panelBackgroundImages" alignment="0" max="32767" attributes="0"/>
|
<Component id="jPanel1" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
|
<Component id="panelBackgroundImages" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -4160,11 +4168,13 @@
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="panelCardImages" min="-2" max="-2" attributes="0"/>
|
<Component id="panelCardImages" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="panelBackgroundImages" min="-2" max="-2" attributes="0"/>
|
<Component id="panelBackgroundImages" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="90" max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -4189,23 +4199,20 @@
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="txtImageFolderPath" max="32767" attributes="0"/>
|
<Component id="txtImageFolderPath" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="btnBrowseImageLocation" min="-2" max="-2" attributes="0"/>
|
<Component id="btnBrowseImageLocation" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="labelNumberOfDownloadThreads" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="cbNumberOfDownloadThreads" min="-2" pref="153" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="cbUseDefaultImageFolder" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||||
<Component id="cbCheckForNewImages" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Group type="102" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="147" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
@ -4213,12 +4220,20 @@
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="cbSaveToZipFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="cbSaveToZipFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="-2" pref="40" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
|
||||||
<Component id="cbPreferedImageLanguage" min="-2" pref="153" max="-2" attributes="0"/>
|
<Component id="cbPreferedImageLanguage" min="-2" pref="153" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="labelNumberOfDownloadThreads" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="cbNumberOfDownloadThreads" min="-2" pref="153" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="0" pref="251" max="32767" attributes="0"/>
|
</Group>
|
||||||
|
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="231" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
@ -4228,14 +4243,13 @@
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
|
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="txtImageFolderPath" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="txtImageFolderPath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="btnBrowseImageLocation" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="btnBrowseImageLocation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
|
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="cbSaveToZipFiles" min="-2" max="-2" attributes="0"/>
|
<Component id="cbSaveToZipFiles" min="-2" max="-2" attributes="0"/>
|
||||||
|
@ -4249,7 +4263,6 @@
|
||||||
<Component id="cbPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="cbPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="labelPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="labelPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="48" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -4473,6 +4486,61 @@
|
||||||
</Component>
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||||
|
<TitledBorder title="Card rendering:">
|
||||||
|
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||||
|
<EtchetBorder/>
|
||||||
|
</Border>
|
||||||
|
</TitledBorder>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="cbCardRenderImageFallback" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="cbCardRenderShowReminderText" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="cbCardRenderImageFallback" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="cbCardRenderShowReminderText" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="7" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="cbCardRenderImageFallback">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Fall back to plain image based rendering"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCardRenderImageFallbackActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="cbCardRenderShowReminderText">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Show reminder text in rendered card textboxes"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCardRenderShowReminderTextActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JPanel" name="tabSounds">
|
<Container class="javax.swing.JPanel" name="tabSounds">
|
||||||
|
@ -5579,7 +5647,7 @@
|
||||||
<Component id="jLabel17" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel17" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="111" max="32767" attributes="0"/>
|
<EmptySpace pref="91" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
|
|
@ -118,6 +118,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip";
|
public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip";
|
||||||
public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage";
|
public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage";
|
||||||
|
|
||||||
|
public static final String KEY_CARD_RENDERING_FALLBACK = "cardRenderingFallback";
|
||||||
|
public static final String KEY_CARD_RENDERING_REMINDER_TEXT = "cardRenderingReminderText";
|
||||||
|
|
||||||
public static final String KEY_BACKGROUND_IMAGE = "backgroundImage";
|
public static final String KEY_BACKGROUND_IMAGE = "backgroundImage";
|
||||||
public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage";
|
public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage";
|
||||||
public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault";
|
public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault";
|
||||||
|
@ -464,6 +467,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
cbUseRandomBattleImage = new javax.swing.JCheckBox();
|
cbUseRandomBattleImage = new javax.swing.JCheckBox();
|
||||||
jLabel14 = new javax.swing.JLabel();
|
jLabel14 = new javax.swing.JLabel();
|
||||||
jLabel15 = new javax.swing.JLabel();
|
jLabel15 = new javax.swing.JLabel();
|
||||||
|
jPanel1 = new javax.swing.JPanel();
|
||||||
|
cbCardRenderImageFallback = new javax.swing.JCheckBox();
|
||||||
|
cbCardRenderShowReminderText = new javax.swing.JCheckBox();
|
||||||
tabSounds = new javax.swing.JPanel();
|
tabSounds = new javax.swing.JPanel();
|
||||||
sounds_clips = new javax.swing.JPanel();
|
sounds_clips = new javax.swing.JPanel();
|
||||||
cbEnableGameSounds = new javax.swing.JCheckBox();
|
cbEnableGameSounds = new javax.swing.JCheckBox();
|
||||||
|
@ -1385,7 +1391,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.add(jLabelEndOfTurn)
|
.add(jLabelEndOfTurn)
|
||||||
.add(checkBoxEndTurnOthers))
|
.add(checkBoxEndTurnOthers))
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||||
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)
|
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1439,41 +1445,43 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.add(panelCardImagesLayout.createSequentialGroup()
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(panelCardImagesLayout.createSequentialGroup()
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.add(24, 24, 24)
|
.addContainerGap()
|
||||||
.add(txtImageFolderPath)
|
.add(txtImageFolderPath)
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(btnBrowseImageLocation))
|
.add(btnBrowseImageLocation))
|
||||||
.add(panelCardImagesLayout.createSequentialGroup()
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
|
||||||
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
|
||||||
.add(labelNumberOfDownloadThreads)
|
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
|
||||||
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(cbUseDefaultImageFolder)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||||
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.add(cbCheckForNewImages)
|
.add(cbCheckForNewImages)
|
||||||
|
.add(147, 147, 147))
|
||||||
|
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
|
||||||
.add(panelCardImagesLayout.createSequentialGroup()
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||||
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
|
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.add(labelPreferedImageLanguage))
|
.add(labelPreferedImageLanguage))
|
||||||
.add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles))
|
.add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles))
|
||||||
.add(40, 40, 40)
|
.add(20, 20, 20)
|
||||||
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
|
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||||
.add(0, 251, Short.MAX_VALUE)))
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.add(labelNumberOfDownloadThreads)
|
||||||
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
|
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
|
||||||
|
.add(cbUseDefaultImageFolder))
|
||||||
|
.add(0, 231, Short.MAX_VALUE)))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
panelCardImagesLayout.setVerticalGroup(
|
panelCardImagesLayout.setVerticalGroup(
|
||||||
panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(panelCardImagesLayout.createSequentialGroup()
|
.add(panelCardImagesLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
|
||||||
.add(cbUseDefaultImageFolder)
|
.add(cbUseDefaultImageFolder)
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||||
.add(txtImageFolderPath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
.add(txtImageFolderPath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.add(btnBrowseImageLocation))
|
.add(btnBrowseImageLocation))
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.add(cbCheckForNewImages)
|
.add(cbCheckForNewImages)
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(cbSaveToZipFiles)
|
.add(cbSaveToZipFiles)
|
||||||
|
@ -1484,8 +1492,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||||
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.add(labelPreferedImageLanguage))
|
.add(labelPreferedImageLanguage)))
|
||||||
.addContainerGap(48, Short.MAX_VALUE))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images setting:"));
|
panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images setting:"));
|
||||||
|
@ -1592,6 +1599,41 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.add(jLabel15)))
|
.add(jLabel15)))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card rendering:"));
|
||||||
|
|
||||||
|
cbCardRenderImageFallback.setText("Fall back to plain image based rendering");
|
||||||
|
cbCardRenderImageFallback.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cbCardRenderImageFallbackActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cbCardRenderShowReminderText.setText("Show reminder text in rendered card textboxes");
|
||||||
|
cbCardRenderShowReminderText.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cbCardRenderShowReminderTextActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
|
||||||
|
jPanel1.setLayout(jPanel1Layout);
|
||||||
|
jPanel1Layout.setHorizontalGroup(
|
||||||
|
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
|
.add(jPanel1Layout.createSequentialGroup()
|
||||||
|
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
|
.add(cbCardRenderImageFallback)
|
||||||
|
.add(cbCardRenderShowReminderText))
|
||||||
|
.add(0, 0, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
jPanel1Layout.setVerticalGroup(
|
||||||
|
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
|
.add(jPanel1Layout.createSequentialGroup()
|
||||||
|
.add(cbCardRenderImageFallback)
|
||||||
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
|
.add(cbCardRenderShowReminderText)
|
||||||
|
.add(0, 7, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
|
||||||
org.jdesktop.layout.GroupLayout tabImagesLayout = new org.jdesktop.layout.GroupLayout(tabImages);
|
org.jdesktop.layout.GroupLayout tabImagesLayout = new org.jdesktop.layout.GroupLayout(tabImages);
|
||||||
tabImages.setLayout(tabImagesLayout);
|
tabImages.setLayout(tabImagesLayout);
|
||||||
tabImagesLayout.setHorizontalGroup(
|
tabImagesLayout.setHorizontalGroup(
|
||||||
|
@ -1600,17 +1642,22 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.add(tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
.add(tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(panelCardImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.add(panelCardImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.add(tabImagesLayout.createSequentialGroup()
|
||||||
|
.add(0, 0, 0)
|
||||||
|
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
tabImagesLayout.setVerticalGroup(
|
tabImagesLayout.setVerticalGroup(
|
||||||
tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
.add(tabImagesLayout.createSequentialGroup()
|
.add(tabImagesLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
|
.add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
.add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(90, Short.MAX_VALUE))
|
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
|
|
||||||
tabsPanel.addTab("Images", tabImages);
|
tabsPanel.addTab("Images", tabImages);
|
||||||
|
@ -2220,7 +2267,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.add(connection_serversLayout.createSequentialGroup()
|
.add(connection_serversLayout.createSequentialGroup()
|
||||||
.add(141, 141, 141)
|
.add(141, 141, 141)
|
||||||
.add(jLabel17)))
|
.add(jLabel17)))
|
||||||
.addContainerGap(111, Short.MAX_VALUE))
|
.addContainerGap(91, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
connection_serversLayout.setVerticalGroup(
|
connection_serversLayout.setVerticalGroup(
|
||||||
connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
|
@ -2406,7 +2453,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||||
.add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
.add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||||
.add(6, 6, 6))
|
.add(6, 6, 6))
|
||||||
|
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||||
|
@ -2534,6 +2584,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY);
|
save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY);
|
save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
|
|
||||||
|
// rendering
|
||||||
|
save(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
|
save(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
|
|
||||||
// sounds
|
// sounds
|
||||||
save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY);
|
save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY);
|
save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY);
|
||||||
|
@ -2806,6 +2860,14 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
// TODO add your handling code here:
|
// TODO add your handling code here:
|
||||||
}//GEN-LAST:event_cbAutoOrderTriggerActionPerformed
|
}//GEN-LAST:event_cbAutoOrderTriggerActionPerformed
|
||||||
|
|
||||||
|
private void cbCardRenderImageFallbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderImageFallbackActionPerformed
|
||||||
|
// TODO add your handling code here:
|
||||||
|
}//GEN-LAST:event_cbCardRenderImageFallbackActionPerformed
|
||||||
|
|
||||||
|
private void cbCardRenderShowReminderTextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderShowReminderTextActionPerformed
|
||||||
|
// TODO add your handling code here:
|
||||||
|
}//GEN-LAST:event_cbCardRenderShowReminderTextActionPerformed
|
||||||
|
|
||||||
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
|
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
|
||||||
// TODO add your handling code here:
|
// TODO add your handling code here:
|
||||||
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
|
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
|
||||||
|
@ -3004,6 +3066,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10"));
|
dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10"));
|
||||||
dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en"));
|
dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en"));
|
||||||
|
|
||||||
|
// rendering settings
|
||||||
|
load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true");
|
||||||
|
load(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true");
|
||||||
|
|
||||||
//add background load precedure
|
//add background load precedure
|
||||||
prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true");
|
prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true");
|
||||||
if (prop.equals("true")) {
|
if (prop.equals("true")) {
|
||||||
|
@ -3384,6 +3450,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
private javax.swing.JCheckBox cbAllowRequestToShowHandCards;
|
private javax.swing.JCheckBox cbAllowRequestToShowHandCards;
|
||||||
private javax.swing.JCheckBox cbAskMoveToGraveOrder;
|
private javax.swing.JCheckBox cbAskMoveToGraveOrder;
|
||||||
private javax.swing.JCheckBox cbAutoOrderTrigger;
|
private javax.swing.JCheckBox cbAutoOrderTrigger;
|
||||||
|
private javax.swing.JCheckBox cbCardRenderImageFallback;
|
||||||
|
private javax.swing.JCheckBox cbCardRenderShowReminderText;
|
||||||
private javax.swing.JCheckBox cbCheckForNewImages;
|
private javax.swing.JCheckBox cbCheckForNewImages;
|
||||||
private javax.swing.JCheckBox cbConfirmEmptyManaPool;
|
private javax.swing.JCheckBox cbConfirmEmptyManaPool;
|
||||||
private javax.swing.JCheckBox cbDraftLogAutoSave;
|
private javax.swing.JCheckBox cbDraftLogAutoSave;
|
||||||
|
@ -3443,6 +3511,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
private javax.swing.JLabel jLabelOpponentsTurn;
|
private javax.swing.JLabel jLabelOpponentsTurn;
|
||||||
private javax.swing.JLabel jLabelUpkeep;
|
private javax.swing.JLabel jLabelUpkeep;
|
||||||
private javax.swing.JLabel jLabelYourTurn;
|
private javax.swing.JLabel jLabelYourTurn;
|
||||||
|
private javax.swing.JPanel jPanel1;
|
||||||
private javax.swing.JPanel jPanel10;
|
private javax.swing.JPanel jPanel10;
|
||||||
private javax.swing.JPanel jPanel11;
|
private javax.swing.JPanel jPanel11;
|
||||||
private javax.swing.JPanel jPanel12;
|
private javax.swing.JPanel jPanel12;
|
||||||
|
|
|
@ -159,7 +159,7 @@ public abstract class Animation {
|
||||||
|
|
||||||
public static void transformCard(final CardPanel panel, final MagePermanent parent, final boolean transformed) {
|
public static void transformCard(final CardPanel panel, final MagePermanent parent, final boolean transformed) {
|
||||||
|
|
||||||
new Animation(1200) {
|
new Animation(600) {
|
||||||
private boolean state = false;
|
private boolean state = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -256,7 +256,7 @@ public abstract class Animation {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (placeholder != null) {
|
if (placeholder != null) {
|
||||||
placeholder.setDisplayEnabled(true);
|
placeholder.setDisplayEnabled(true);
|
||||||
placeholder.setImage(animationPanel);
|
placeholder.transferResources(animationPanel);
|
||||||
}
|
}
|
||||||
animationPanel.setVisible(false);
|
animationPanel.setVisible(false);
|
||||||
animationPanel.repaint();
|
animationPanel.repaint();
|
||||||
|
@ -303,7 +303,7 @@ public abstract class Animation {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (placeholder != null) {
|
if (placeholder != null) {
|
||||||
placeholder.setDisplayEnabled(true);
|
placeholder.setDisplayEnabled(true);
|
||||||
placeholder.setImage(animationPanel);
|
placeholder.transferResources(animationPanel);
|
||||||
}
|
}
|
||||||
animationPanel.setVisible(false);
|
animationPanel.setVisible(false);
|
||||||
animationPanel.repaint();
|
animationPanel.repaint();
|
||||||
|
|
|
@ -0,0 +1,711 @@
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
|
import java.awt.AlphaComposite;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import mage.cards.action.ActionCallback;
|
||||||
|
import mage.client.dialog.PreferencesDialog;
|
||||||
|
import mage.client.util.ImageCaches;
|
||||||
|
import mage.client.util.ImageHelper;
|
||||||
|
import mage.components.ImagePanel;
|
||||||
|
import mage.constants.AbilityType;
|
||||||
|
import mage.utils.CardUtil;
|
||||||
|
import mage.view.CardView;
|
||||||
|
import mage.view.CounterView;
|
||||||
|
import mage.view.PermanentView;
|
||||||
|
import mage.view.StackAbilityView;
|
||||||
|
import net.java.truevfs.access.TFile;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||||
|
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||||
|
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||||
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
|
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for drawing the mage card object by using a form based JComponent approach
|
||||||
|
*
|
||||||
|
* @author arcane, nantuko, noxx, stravant
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public class CardPanelComponentImpl extends CardPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3272134219262184411L;
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CardPanelComponentImpl.class);
|
||||||
|
|
||||||
|
private static final int WIDTH_LIMIT = 90; // card width limit to create smaller counter
|
||||||
|
|
||||||
|
private static final float ROUNDED_CORNER_SIZE = 0.1f;
|
||||||
|
private static final float BLACK_BORDER_SIZE = 0.03f;
|
||||||
|
private static final int TEXT_GLOW_SIZE = 6;
|
||||||
|
private static final float TEXT_GLOW_INTENSITY = 3f;
|
||||||
|
|
||||||
|
public final ScaledImagePanel imagePanel;
|
||||||
|
public ImagePanel overlayPanel;
|
||||||
|
|
||||||
|
public JPanel iconPanel;
|
||||||
|
private JButton typeButton;
|
||||||
|
|
||||||
|
public JPanel counterPanel;
|
||||||
|
private JLabel loyaltyCounterLabel;
|
||||||
|
private JLabel plusCounterLabel;
|
||||||
|
private JLabel otherCounterLabel;
|
||||||
|
private JLabel minusCounterLabel;
|
||||||
|
private int loyaltyCounter;
|
||||||
|
private int plusCounter;
|
||||||
|
private int otherCounter;
|
||||||
|
private int minusCounter;
|
||||||
|
private int lastCardWidth;
|
||||||
|
|
||||||
|
private final GlowText titleText;
|
||||||
|
private final GlowText ptText;
|
||||||
|
|
||||||
|
private boolean hasImage = false;
|
||||||
|
|
||||||
|
private boolean displayTitleAnyway;
|
||||||
|
|
||||||
|
private final static Map<Key, BufferedImage> IMAGE_CACHE;
|
||||||
|
|
||||||
|
class Key {
|
||||||
|
|
||||||
|
final int width;
|
||||||
|
final int height;
|
||||||
|
final int cardWidth;
|
||||||
|
final int cardHeight;
|
||||||
|
final int cardXOffset;
|
||||||
|
final int cardYOffset;
|
||||||
|
final boolean hasImage;
|
||||||
|
final boolean isSelected;
|
||||||
|
final boolean isChoosable;
|
||||||
|
final boolean isPlayable;
|
||||||
|
final boolean canAttack;
|
||||||
|
|
||||||
|
public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.cardWidth = cardWidth;
|
||||||
|
this.cardHeight = cardHeight;
|
||||||
|
this.cardXOffset = cardXOffset;
|
||||||
|
this.cardYOffset = cardYOffset;
|
||||||
|
this.hasImage = hasImage;
|
||||||
|
this.isSelected = isSelected;
|
||||||
|
this.isChoosable = isChoosable;
|
||||||
|
this.isPlayable = isPlayable;
|
||||||
|
this.canAttack = canAttack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
hash = 19 * hash + this.width;
|
||||||
|
hash = 19 * hash + this.height;
|
||||||
|
hash = 19 * hash + this.cardWidth;
|
||||||
|
hash = 19 * hash + this.cardHeight;
|
||||||
|
hash = 19 * hash + this.cardXOffset;
|
||||||
|
hash = 19 * hash + this.cardYOffset;
|
||||||
|
hash = 19 * hash + (this.hasImage ? 1 : 0);
|
||||||
|
hash = 19 * hash + (this.isSelected ? 1 : 0);
|
||||||
|
hash = 19 * hash + (this.isChoosable ? 1 : 0);
|
||||||
|
hash = 19 * hash + (this.isPlayable ? 1 : 0);
|
||||||
|
hash = 19 * hash + (this.canAttack ? 1 : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Key other = (Key) obj;
|
||||||
|
if (this.width != other.width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.height != other.height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.cardWidth != other.cardWidth) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.cardHeight != other.cardHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.cardXOffset != other.cardXOffset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.cardYOffset != other.cardYOffset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.hasImage != other.hasImage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.isSelected != other.isSelected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.isChoosable != other.isChoosable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.isPlayable != other.isPlayable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.canAttack != other.canAttack) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function<Key, BufferedImage>() {
|
||||||
|
@Override
|
||||||
|
public BufferedImage apply(Key key) {
|
||||||
|
return createImage(key);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CardPanelComponentImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||||
|
// Call to super
|
||||||
|
super(newGameCard, gameId, loadImage, callback, foil, dimension);
|
||||||
|
|
||||||
|
// Counter panel
|
||||||
|
if (!newGameCard.isAbility()) {
|
||||||
|
// panel to show counters on the card
|
||||||
|
counterPanel = new JPanel();
|
||||||
|
counterPanel.setLayout(null);
|
||||||
|
counterPanel.setOpaque(false);
|
||||||
|
add(counterPanel);
|
||||||
|
|
||||||
|
plusCounterLabel = new JLabel("");
|
||||||
|
plusCounterLabel.setToolTipText("+1/+1");
|
||||||
|
counterPanel.add(plusCounterLabel);
|
||||||
|
|
||||||
|
minusCounterLabel = new JLabel("");
|
||||||
|
minusCounterLabel.setToolTipText("-1/-1");
|
||||||
|
counterPanel.add(minusCounterLabel);
|
||||||
|
|
||||||
|
loyaltyCounterLabel = new JLabel("");
|
||||||
|
loyaltyCounterLabel.setToolTipText("loyalty");
|
||||||
|
counterPanel.add(loyaltyCounterLabel);
|
||||||
|
|
||||||
|
otherCounterLabel = new JLabel("");
|
||||||
|
counterPanel.add(otherCounterLabel);
|
||||||
|
|
||||||
|
counterPanel.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ability icon
|
||||||
|
if (newGameCard.isAbility()) {
|
||||||
|
if (AbilityType.TRIGGERED.equals(newGameCard.getAbilityType())) {
|
||||||
|
setTypeIcon(ImageManagerImpl.getInstance().getTriggeredAbilityImage(), "Triggered Ability");
|
||||||
|
} else if (AbilityType.ACTIVATED.equals(newGameCard.getAbilityType())) {
|
||||||
|
setTypeIcon(ImageManagerImpl.getInstance().getActivatedAbilityImage(), "Activated Ability");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token icon
|
||||||
|
if (this.gameCard.isToken()) {
|
||||||
|
setTypeIcon(ImageManagerImpl.getInstance().getTokenIconImage(), "Token Permanent");
|
||||||
|
}
|
||||||
|
|
||||||
|
displayTitleAnyway = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_CARD_NAMES, "true").equals("true");
|
||||||
|
|
||||||
|
// Title Text
|
||||||
|
titleText = new GlowText();
|
||||||
|
setText(gameCard);
|
||||||
|
// int fontSize = (int) cardHeight / 11;
|
||||||
|
// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||||
|
titleText.setForeground(Color.white);
|
||||||
|
titleText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
|
||||||
|
titleText.setWrap(true);
|
||||||
|
add(titleText);
|
||||||
|
|
||||||
|
// PT Text
|
||||||
|
ptText = new GlowText();
|
||||||
|
if (CardUtil.isCreature(gameCard)) {
|
||||||
|
ptText.setText(gameCard.getPower() + "/" + gameCard.getToughness());
|
||||||
|
} else if (CardUtil.isPlaneswalker(gameCard)) {
|
||||||
|
ptText.setText(gameCard.getLoyalty());
|
||||||
|
}
|
||||||
|
// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||||
|
ptText.setForeground(Color.white);
|
||||||
|
ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
|
||||||
|
add(ptText);
|
||||||
|
|
||||||
|
// Sickness overlay
|
||||||
|
BufferedImage sickness = ImageManagerImpl.getInstance().getSicknessImage();
|
||||||
|
overlayPanel = new ImagePanel(sickness, ImagePanel.SCALED);
|
||||||
|
overlayPanel.setOpaque(false);
|
||||||
|
add(overlayPanel);
|
||||||
|
|
||||||
|
// Imagel panel
|
||||||
|
imagePanel = new ScaledImagePanel();
|
||||||
|
imagePanel.setBorder(BorderFactory.createLineBorder(Color.white));
|
||||||
|
add(imagePanel);
|
||||||
|
|
||||||
|
// Do we need to load?
|
||||||
|
if (loadImage) {
|
||||||
|
initialDraw();
|
||||||
|
} else {
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTypeIcon(BufferedImage bufferedImage, String toolTipText) {
|
||||||
|
iconPanel = new JPanel();
|
||||||
|
iconPanel.setLayout(null);
|
||||||
|
iconPanel.setOpaque(false);
|
||||||
|
add(iconPanel);
|
||||||
|
|
||||||
|
typeButton = new JButton("");
|
||||||
|
typeButton.setLocation(2, 2);
|
||||||
|
typeButton.setSize(25, 25);
|
||||||
|
|
||||||
|
iconPanel.setVisible(true);
|
||||||
|
typeButton.setIcon(new ImageIcon(bufferedImage));
|
||||||
|
if (toolTipText != null) {
|
||||||
|
typeButton.setToolTipText(toolTipText);
|
||||||
|
}
|
||||||
|
iconPanel.add(typeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanUp() {
|
||||||
|
super.cleanUp();
|
||||||
|
this.counterPanel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setText(CardView card) {
|
||||||
|
titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setImage(BufferedImage srcImage) {
|
||||||
|
synchronized (imagePanel) {
|
||||||
|
if (srcImage != null) {
|
||||||
|
imagePanel.setImage(srcImage);
|
||||||
|
} else {
|
||||||
|
imagePanel.clearImage();
|
||||||
|
}
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
doLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transferResources(final CardPanel panelAbstract) {
|
||||||
|
if (panelAbstract instanceof CardPanelComponentImpl) {
|
||||||
|
CardPanelComponentImpl panel = (CardPanelComponentImpl)panelAbstract;
|
||||||
|
synchronized (panel.imagePanel) {
|
||||||
|
if (panel.imagePanel.hasImage()) {
|
||||||
|
setImage(panel.imagePanel.getSrcImage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean isSelected) {
|
||||||
|
super.setSelected(isSelected);
|
||||||
|
if (isSelected) {
|
||||||
|
this.titleText.setGlowColor(Color.green);
|
||||||
|
} else {
|
||||||
|
this.titleText.setGlowColor(Color.black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintCard(Graphics2D g2d) {
|
||||||
|
float alpha = getAlpha();
|
||||||
|
if (alpha != 1.0f) {
|
||||||
|
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha);
|
||||||
|
g2d.setComposite(composite);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2d.drawImage(
|
||||||
|
IMAGE_CACHE.get(
|
||||||
|
new Key(getWidth(), getHeight(), getCardWidth(), getCardHeight(), getCardXOffset(), getCardYOffset(),
|
||||||
|
hasImage, isSelected(), isChoosable(), gameCard.isPlayable(), gameCard.isCanAttack())),
|
||||||
|
0, 0, null);
|
||||||
|
g2d.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BufferedImage createImage(Key key) {
|
||||||
|
int cardWidth = key.cardWidth;
|
||||||
|
int cardHeight = key.cardHeight;
|
||||||
|
int cardXOffset = key.cardXOffset;
|
||||||
|
int cardYOffset = key.cardYOffset;
|
||||||
|
|
||||||
|
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(key.width, key.height);
|
||||||
|
Graphics2D g2d = image.createGraphics();
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
if (!key.hasImage) {
|
||||||
|
g2d.setColor(new Color(30, 200, 200, 120));
|
||||||
|
} else {
|
||||||
|
g2d.setColor(new Color(0, 0, 0, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
|
||||||
|
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||||
|
|
||||||
|
if (key.isSelected) {
|
||||||
|
g2d.setColor(Color.green);
|
||||||
|
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||||
|
} else if (key.isChoosable) {
|
||||||
|
g2d.setColor(new Color(250, 250, 0, 230));
|
||||||
|
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||||
|
} else if (key.isPlayable) {
|
||||||
|
g2d.setColor(new Color(153, 102, 204, 200));
|
||||||
|
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||||
|
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.canAttack) {
|
||||||
|
g2d.setColor(new Color(0, 0, 255, 230));
|
||||||
|
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:uncomment
|
||||||
|
/*
|
||||||
|
if (gameCard.isAttacking()) {
|
||||||
|
g2d.setColor(new Color(200,10,10,200));
|
||||||
|
g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize);
|
||||||
|
}*/
|
||||||
|
g2d.dispose();
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintChildren(Graphics g) {
|
||||||
|
super.paintChildren(g);
|
||||||
|
|
||||||
|
if (getShowCastingCost() && !isAnimationPanel() && getCardWidth() < 200 && getCardWidth() > 60) {
|
||||||
|
String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
|
||||||
|
int width = getWidth(manaCost);
|
||||||
|
if (hasImage) {
|
||||||
|
ManaSymbols.draw(g, manaCost, getCardXOffset() + getCardWidth() - width - 5, getCardYOffset() + 5, getSymbolWidth());
|
||||||
|
} else {
|
||||||
|
ManaSymbols.draw(g, manaCost, getCardXOffset() + 8, getCardHeight() - 9, getSymbolWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getWidth(String manaCost) {
|
||||||
|
int width = 0;
|
||||||
|
manaCost = manaCost.replace("\\", "");
|
||||||
|
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
tok.nextToken();
|
||||||
|
width += getSymbolWidth();
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doLayout() {
|
||||||
|
super.doLayout();
|
||||||
|
|
||||||
|
int cardWidth = getCardWidth();
|
||||||
|
int cardHeight = getCardHeight();
|
||||||
|
int cardXOffset = getCardXOffset();
|
||||||
|
int cardYOffset = getCardYOffset();
|
||||||
|
int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE);
|
||||||
|
imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||||
|
imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||||
|
|
||||||
|
if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) {
|
||||||
|
overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||||
|
overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||||
|
} else {
|
||||||
|
overlayPanel.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconPanel != null) {
|
||||||
|
iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||||
|
iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||||
|
}
|
||||||
|
if (counterPanel != null) {
|
||||||
|
counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||||
|
counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||||
|
int size = cardWidth > WIDTH_LIMIT ? 40 : 20;
|
||||||
|
|
||||||
|
minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2);
|
||||||
|
minusCounterLabel.setSize(size, size);
|
||||||
|
|
||||||
|
plusCounterLabel.setLocation(5, counterPanel.getHeight() - size * 2);
|
||||||
|
plusCounterLabel.setSize(size, size);
|
||||||
|
|
||||||
|
loyaltyCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size);
|
||||||
|
loyaltyCounterLabel.setSize(size, size);
|
||||||
|
|
||||||
|
otherCounterLabel.setLocation(5, counterPanel.getHeight() - size);
|
||||||
|
otherCounterLabel.setSize(size, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
int fontHeight = Math.round(cardHeight * (27f / 680));
|
||||||
|
boolean showText = (!isAnimationPanel() && fontHeight < 12);
|
||||||
|
titleText.setVisible(showText);
|
||||||
|
ptText.setVisible(showText);
|
||||||
|
|
||||||
|
if (showText) {
|
||||||
|
int fontSize = (int) cardHeight / 11;
|
||||||
|
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||||
|
|
||||||
|
int titleX = Math.round(cardWidth * (20f / 480));
|
||||||
|
int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset();
|
||||||
|
titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY);
|
||||||
|
|
||||||
|
ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||||
|
Dimension ptSize = ptText.getPreferredSize();
|
||||||
|
ptText.setSize(ptSize.width, ptSize.height);
|
||||||
|
int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2;
|
||||||
|
int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height;
|
||||||
|
|
||||||
|
int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f);
|
||||||
|
|
||||||
|
ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return gameCard.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCardBounds(int x, int y, int cardWidth, int cardHeight) {
|
||||||
|
// Call to super
|
||||||
|
super.setCardBounds(x, y, cardWidth, cardHeight);
|
||||||
|
|
||||||
|
// Update image
|
||||||
|
if (imagePanel != null && imagePanel.getSrcImage() != null) {
|
||||||
|
updateImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(float alpha) {
|
||||||
|
super.setAlpha(alpha);
|
||||||
|
|
||||||
|
// Update components
|
||||||
|
if (alpha == 0) {
|
||||||
|
this.ptText.setVisible(false);
|
||||||
|
this.titleText.setVisible(false);
|
||||||
|
} else if (alpha == 1.0f) {
|
||||||
|
this.ptText.setVisible(true);
|
||||||
|
this.titleText.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Image updating code
|
||||||
|
private int updateImageStamp;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateImage() {
|
||||||
|
tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
|
||||||
|
flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0;
|
||||||
|
|
||||||
|
//final CardView gameCard = this.gameCard;
|
||||||
|
final int stamp = ++updateImageStamp;
|
||||||
|
|
||||||
|
Util.threadPool.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
final BufferedImage srcImage;
|
||||||
|
if (gameCard.isFaceDown()) {
|
||||||
|
srcImage = getFaceDownImage();
|
||||||
|
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||||
|
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||||
|
} else {
|
||||||
|
srcImage = ImageCache.getThumbnail(gameCard);
|
||||||
|
}
|
||||||
|
UI.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (stamp == updateImageStamp) {
|
||||||
|
hasImage = srcImage != null;
|
||||||
|
setText(gameCard);
|
||||||
|
setImage(srcImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Error err) {
|
||||||
|
err.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedImage getFaceDownImage() {
|
||||||
|
if (isPermanent()) {
|
||||||
|
if (((PermanentView) gameCard).isMorphed()) {
|
||||||
|
return ImageCache.getMorphImage();
|
||||||
|
} else {
|
||||||
|
return ImageCache.getManifestImage();
|
||||||
|
}
|
||||||
|
} else if (this.gameCard instanceof StackAbilityView) {
|
||||||
|
return ImageCache.getMorphImage();
|
||||||
|
} else {
|
||||||
|
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCardTitle() {
|
||||||
|
displayTitleAnyway = true;
|
||||||
|
setText(gameCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(CardView card) {
|
||||||
|
// Super
|
||||||
|
super.update(card);
|
||||||
|
|
||||||
|
// Update card text
|
||||||
|
if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) {
|
||||||
|
ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")");
|
||||||
|
} else if (CardUtil.isCreature(card)) {
|
||||||
|
ptText.setText(card.getPower() + "/" + card.getToughness());
|
||||||
|
} else if (CardUtil.isPlaneswalker(card)) {
|
||||||
|
ptText.setText(card.getLoyalty());
|
||||||
|
} else {
|
||||||
|
ptText.setText("");
|
||||||
|
}
|
||||||
|
setText(card);
|
||||||
|
|
||||||
|
// Summoning Sickness overlay
|
||||||
|
if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) {
|
||||||
|
overlayPanel.setVisible(true);
|
||||||
|
} else {
|
||||||
|
overlayPanel.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update counters panel
|
||||||
|
if (counterPanel != null) {
|
||||||
|
updateCounters(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, queue a repaint
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCounters(CardView card) {
|
||||||
|
if (card.getCounters() != null && !card.getCounters().isEmpty()) {
|
||||||
|
String name = "";
|
||||||
|
if (lastCardWidth != getCardWidth()) {
|
||||||
|
lastCardWidth = getCardWidth();
|
||||||
|
plusCounter = 0;
|
||||||
|
minusCounter = 0;
|
||||||
|
otherCounter = 0;
|
||||||
|
loyaltyCounter = 0;
|
||||||
|
}
|
||||||
|
plusCounterLabel.setVisible(false);
|
||||||
|
minusCounterLabel.setVisible(false);
|
||||||
|
loyaltyCounterLabel.setVisible(false);
|
||||||
|
otherCounterLabel.setVisible(false);
|
||||||
|
for (CounterView counterView : card.getCounters()) {
|
||||||
|
if (counterView.getCount() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (counterView.getName()) {
|
||||||
|
case "+1/+1":
|
||||||
|
if (counterView.getCount() != plusCounter) {
|
||||||
|
plusCounter = counterView.getCount();
|
||||||
|
plusCounterLabel.setIcon(getCounterImageWithAmount(plusCounter, ImageManagerImpl.getInstance().getCounterImageGreen(), getCardWidth()));
|
||||||
|
}
|
||||||
|
plusCounterLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "-1/-1":
|
||||||
|
if (counterView.getCount() != minusCounter) {
|
||||||
|
minusCounter = counterView.getCount();
|
||||||
|
minusCounterLabel.setIcon(getCounterImageWithAmount(minusCounter, ImageManagerImpl.getInstance().getCounterImageRed(), getCardWidth()));
|
||||||
|
}
|
||||||
|
minusCounterLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "loyalty":
|
||||||
|
if (counterView.getCount() != loyaltyCounter) {
|
||||||
|
loyaltyCounter = counterView.getCount();
|
||||||
|
loyaltyCounterLabel.setIcon(getCounterImageWithAmount(loyaltyCounter, ImageManagerImpl.getInstance().getCounterImageViolet(), getCardWidth()));
|
||||||
|
}
|
||||||
|
loyaltyCounterLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (name.isEmpty()) { // only first other counter is shown
|
||||||
|
name = counterView.getName();
|
||||||
|
otherCounter = counterView.getCount();
|
||||||
|
otherCounterLabel.setToolTipText(name);
|
||||||
|
otherCounterLabel.setIcon(getCounterImageWithAmount(otherCounter, ImageManagerImpl.getInstance().getCounterImageGrey(), getCardWidth()));
|
||||||
|
otherCounterLabel.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counterPanel.setVisible(true);
|
||||||
|
} else {
|
||||||
|
plusCounterLabel.setVisible(false);
|
||||||
|
minusCounterLabel.setVisible(false);
|
||||||
|
loyaltyCounterLabel.setVisible(false);
|
||||||
|
otherCounterLabel.setVisible(false);
|
||||||
|
counterPanel.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageIcon getCounterImageWithAmount(int amount, BufferedImage image, int cardWidth) {
|
||||||
|
int factor = cardWidth > WIDTH_LIMIT ? 2 : 1;
|
||||||
|
int xOffset = amount > 9 ? 2 : 5;
|
||||||
|
int fontSize = factor == 1 ? amount < 10 ? 12 : amount < 100 ? 10 : amount < 1000 ? 7 : 6
|
||||||
|
: amount < 10 ? 19 : amount < 100 ? 15 : amount < 1000 ? 12 : amount < 10000 ? 9 : 8;
|
||||||
|
BufferedImage newImage;
|
||||||
|
if (cardWidth > WIDTH_LIMIT) {
|
||||||
|
newImage = ImageManagerImpl.deepCopy(image);
|
||||||
|
} else {
|
||||||
|
newImage = ImageHelper.getResizedImage(image, 20, 20);
|
||||||
|
}
|
||||||
|
Graphics graphics = newImage.getGraphics();
|
||||||
|
graphics.setColor(Color.BLACK);
|
||||||
|
graphics.setFont(new Font("Arial Black", amount > 100 ? Font.PLAIN : Font.BOLD, fontSize));
|
||||||
|
graphics.drawString(Integer.toString(amount), xOffset * factor, 11 * factor);
|
||||||
|
return new ImageIcon(newImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image getImage() {
|
||||||
|
if (this.hasImage) {
|
||||||
|
if (gameCard.isFaceDown()) {
|
||||||
|
return getFaceDownImage();
|
||||||
|
} else {
|
||||||
|
return ImageCache.getImageOriginal(gameCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,323 @@
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.cards.action.ActionCallback;
|
||||||
|
import mage.client.util.ImageCaches;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.view.CardView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||||
|
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||||
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
|
|
||||||
|
public class CardPanelRenderImpl extends CardPanel {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CardPanelRenderImpl.class);
|
||||||
|
|
||||||
|
private static boolean cardViewEquals(CardView a, CardView b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!a.getName().equals(b.getName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getPower().equals(b.getPower())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getToughness().equals(b.getToughness())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getLoyalty().equals(b.getLoyalty())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (0 != a.getColor().compareTo(b.getColor())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getCardTypes().equals(b.getCardTypes())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getSubTypes().equals(b.getSubTypes())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getSuperTypes().equals(b.getSuperTypes())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getManaCost().equals(b.getManaCost())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getRules().equals(b.getRules())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!a.getExpansionSetCode().equals(b.getExpansionSetCode())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImageKey {
|
||||||
|
final BufferedImage artImage;
|
||||||
|
final int width;
|
||||||
|
final int height;
|
||||||
|
final boolean isChoosable;
|
||||||
|
final boolean isSelected;
|
||||||
|
final CardView view;
|
||||||
|
final int hashCode;
|
||||||
|
|
||||||
|
public ImageKey(CardView view, BufferedImage artImage, int width, int height, boolean isChoosable, boolean isSelected) {
|
||||||
|
this.view = view;
|
||||||
|
this.artImage = artImage;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.isChoosable = isChoosable;
|
||||||
|
this.isSelected = isSelected;
|
||||||
|
this.hashCode = hashCodeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int hashCodeImpl() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append((char)(artImage != null ? 1 : 0));
|
||||||
|
sb.append((char)width);
|
||||||
|
sb.append((char)height);
|
||||||
|
sb.append((char)(isSelected ? 1 : 0));
|
||||||
|
sb.append((char)(isChoosable ? 1 : 0));
|
||||||
|
sb.append((char)(this.view.isPlayable() ? 1 : 0));
|
||||||
|
sb.append((char)(this.view.isCanAttack() ? 1 : 0));
|
||||||
|
sb.append(this.view.getName());
|
||||||
|
sb.append(this.view.getPower());
|
||||||
|
sb.append(this.view.getToughness());
|
||||||
|
sb.append(this.view.getLoyalty());
|
||||||
|
sb.append(this.view.getColor().toString());
|
||||||
|
sb.append(this.view.getExpansionSetCode());
|
||||||
|
for (CardType type: this.view.getCardTypes()) {
|
||||||
|
sb.append((char)type.ordinal());
|
||||||
|
}
|
||||||
|
for (String s: this.view.getSuperTypes()) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
for (String s: this.view.getSubTypes()) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
for (String s: this.view.getManaCost()) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
for (String s: this.view.getRules()) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
return sb.toString().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
// Initial checks
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(object instanceof ImageKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final ImageKey other = (ImageKey)object;
|
||||||
|
|
||||||
|
// Compare
|
||||||
|
if ((artImage != null) != (other.artImage != null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (width != other.width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (height != other.height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isChoosable != other.isChoosable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isSelected != other.isSelected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return cardViewEquals(view, other.view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of generated images
|
||||||
|
private final static Map<ImageKey, BufferedImage> IMAGE_CACHE = new MapMaker().softValues().makeMap();
|
||||||
|
|
||||||
|
// The art image for the card, loaded in from the disk
|
||||||
|
private BufferedImage artImage;
|
||||||
|
|
||||||
|
// The rendered card image, with or without the art image loaded yet
|
||||||
|
// = null while invalid
|
||||||
|
private BufferedImage cardImage;
|
||||||
|
private CardRenderer cardRenderer;
|
||||||
|
|
||||||
|
public CardPanelRenderImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||||
|
// Call to super
|
||||||
|
super(newGameCard, gameId, loadImage, callback, foil, dimension);
|
||||||
|
|
||||||
|
// Renderer
|
||||||
|
cardRenderer = new ModernCardRenderer(gameCard, isTransformed());
|
||||||
|
|
||||||
|
// Draw the parts
|
||||||
|
initialDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transferResources(CardPanel panel) {
|
||||||
|
if (panel instanceof CardPanelRenderImpl) {
|
||||||
|
CardPanelRenderImpl impl = (CardPanelRenderImpl)panel;
|
||||||
|
|
||||||
|
// Use the art image and current rendered image from the card
|
||||||
|
artImage = impl.artImage;
|
||||||
|
cardRenderer.setArtImage(artImage);
|
||||||
|
cardImage = impl.cardImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintCard(Graphics2D g) {
|
||||||
|
// Render the card if we don't have an image ready to use
|
||||||
|
if (cardImage == null) {
|
||||||
|
// Try to get card image from cache based on our card characteristics
|
||||||
|
ImageKey key =
|
||||||
|
new ImageKey(gameCard, artImage,
|
||||||
|
getCardWidth(), getCardHeight(),
|
||||||
|
isChoosable(), isSelected());
|
||||||
|
cardImage = IMAGE_CACHE.get(key);
|
||||||
|
|
||||||
|
// No cached copy exists? Render one and cache it
|
||||||
|
if (cardImage == null) {
|
||||||
|
cardImage = renderCard();
|
||||||
|
IMAGE_CACHE.put(key, cardImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And draw the image we now have
|
||||||
|
g.drawImage(cardImage, 0, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the card to a new BufferedImage at it's current dimensions
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private BufferedImage renderCard() {
|
||||||
|
int cardWidth = getCardWidth();
|
||||||
|
int cardHeight = getCardHeight();
|
||||||
|
int cardXOffset = getCardXOffset();
|
||||||
|
int cardYOffset = getCardYOffset();
|
||||||
|
|
||||||
|
// Create image to render to
|
||||||
|
BufferedImage image =
|
||||||
|
GraphicsUtilities.createCompatibleTranslucentImage(getWidth(), getHeight());
|
||||||
|
Graphics2D g2d = image.createGraphics();
|
||||||
|
|
||||||
|
// Render with Antialialsing
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
// Draw card itself
|
||||||
|
g2d.translate(cardXOffset, cardYOffset);
|
||||||
|
cardRenderer.draw(g2d, cardWidth - cardXOffset, cardHeight - cardYOffset);
|
||||||
|
g2d.translate(-cardXOffset, -cardYOffset);
|
||||||
|
|
||||||
|
// Done
|
||||||
|
g2d.dispose();
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateImageStamp;
|
||||||
|
@Override
|
||||||
|
public void updateImage() {
|
||||||
|
// Invalidate
|
||||||
|
artImage = null;
|
||||||
|
cardImage = null;
|
||||||
|
|
||||||
|
// Stop animation
|
||||||
|
tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
|
||||||
|
flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0;
|
||||||
|
|
||||||
|
// Schedule a repaint
|
||||||
|
repaint();
|
||||||
|
|
||||||
|
// Submit a task to draw with the card art when it arrives
|
||||||
|
final int stamp = ++updateImageStamp;
|
||||||
|
Util.threadPool.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
final BufferedImage srcImage;
|
||||||
|
if (gameCard.isFaceDown()) {
|
||||||
|
// Nothing to do
|
||||||
|
srcImage = null;
|
||||||
|
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||||
|
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||||
|
} else {
|
||||||
|
srcImage = ImageCache.getThumbnail(gameCard);
|
||||||
|
}
|
||||||
|
UI.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (stamp == updateImageStamp) {
|
||||||
|
CardPanelRenderImpl.this.artImage = srcImage;
|
||||||
|
CardPanelRenderImpl.this.cardRenderer.setArtImage(srcImage);
|
||||||
|
if (srcImage != null) {
|
||||||
|
// Invalidate and repaint
|
||||||
|
CardPanelRenderImpl.this.cardImage = null;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Error err) {
|
||||||
|
err.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(CardView card) {
|
||||||
|
// Update super
|
||||||
|
super.update(card);
|
||||||
|
|
||||||
|
// Update renderer
|
||||||
|
cardRenderer = new ModernCardRenderer(gameCard, isTransformed());
|
||||||
|
|
||||||
|
// Repaint
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCardBounds(int x, int y, int cardWidth, int cardHeight) {
|
||||||
|
super.setCardBounds(x, y, cardWidth, cardHeight);
|
||||||
|
|
||||||
|
// Rerender
|
||||||
|
cardImage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image getImage() {
|
||||||
|
// Render impl never returns a card image
|
||||||
|
return artImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCardTitle() {
|
||||||
|
// Nothing to do, rendered cards always have a title
|
||||||
|
}
|
||||||
|
}
|
348
Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.Paint;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.counters.Counter;
|
||||||
|
import mage.view.CardView;
|
||||||
|
import mage.view.CounterView;
|
||||||
|
import mage.view.PermanentView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*
|
||||||
|
* Common base class for card renderers for each card frame / card type.
|
||||||
|
*
|
||||||
|
* Follows the template method pattern to implement a new renderer, implement
|
||||||
|
* the following methods (they are called in the following order):
|
||||||
|
*
|
||||||
|
* * drawBorder()
|
||||||
|
* Draws the outermost border of the card, white border or black border
|
||||||
|
*
|
||||||
|
* * drawBackground()
|
||||||
|
* Draws the background texture / color of the card
|
||||||
|
*
|
||||||
|
* * drawArt()
|
||||||
|
* Draws the card's art
|
||||||
|
*
|
||||||
|
* * drawFrame()
|
||||||
|
* Draws the card frame (over the art and background)
|
||||||
|
*
|
||||||
|
* * drawOverlays()
|
||||||
|
* Draws summoning sickness and possible other overlays
|
||||||
|
*
|
||||||
|
* * drawCounters()
|
||||||
|
* Draws counters on the card, such as +1/+1 and -1/-1 counters
|
||||||
|
*
|
||||||
|
* Predefined methods that the implementations can use:
|
||||||
|
*
|
||||||
|
* * drawRules(font, bounding box)
|
||||||
|
*
|
||||||
|
* * drawNameLine(font, bounding box)
|
||||||
|
*
|
||||||
|
* * drawTypeLine(font, bounding box)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class CardRenderer {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Common layout metrics between all cards
|
||||||
|
|
||||||
|
// The card to be rendered
|
||||||
|
protected final CardView cardView;
|
||||||
|
|
||||||
|
// Is the card transformed?
|
||||||
|
protected final boolean isTransformed;
|
||||||
|
|
||||||
|
// The card image
|
||||||
|
protected BufferedImage artImage;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Common layout metrics between all cards
|
||||||
|
|
||||||
|
// Polygons for counters
|
||||||
|
private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{
|
||||||
|
0, 5, 10, 10, 5, 0
|
||||||
|
}, new int[]{
|
||||||
|
3, 0, 3, 10, 9, 10
|
||||||
|
}, 6);
|
||||||
|
private static final Polygon MINUS_COUNTER_POLY = new Polygon(new int[]{
|
||||||
|
0, 5, 10, 10, 5, 0
|
||||||
|
}, new int[]{
|
||||||
|
0, 1, 0, 7, 10, 7
|
||||||
|
}, 6);
|
||||||
|
private static final Polygon TIME_COUNTER_POLY = new Polygon(new int[]{
|
||||||
|
0, 10, 8, 10, 0, 2
|
||||||
|
}, new int[]{
|
||||||
|
0, 0, 5, 10, 10, 5
|
||||||
|
}, 6);
|
||||||
|
private static final Polygon OTHER_COUNTER_POLY = new Polygon(new int[]{
|
||||||
|
1, 9, 9, 1
|
||||||
|
}, new int[]{
|
||||||
|
1, 1, 9, 9
|
||||||
|
}, 4);
|
||||||
|
|
||||||
|
// Paint for a card back
|
||||||
|
public static Paint BG_TEXTURE_CARDBACK = new Color(153, 102, 51);
|
||||||
|
|
||||||
|
// The size of the card
|
||||||
|
protected int cardWidth;
|
||||||
|
protected int cardHeight;
|
||||||
|
|
||||||
|
// Radius of the corners of the cards
|
||||||
|
protected static float CORNER_RADIUS_FRAC = 0.1f; //x cardWidth
|
||||||
|
protected static int CORNER_RADIUS_MIN = 3;
|
||||||
|
protected int cornerRadius;
|
||||||
|
|
||||||
|
// The inset of the actual card from the black / white border around it
|
||||||
|
protected static float BORDER_WIDTH_FRAC = 0.03f; //x cardWidth
|
||||||
|
protected static float BORDER_WIDTH_MIN = 2;
|
||||||
|
protected int borderWidth;
|
||||||
|
|
||||||
|
// The parsed text of the card
|
||||||
|
protected ArrayList<TextboxRule> textboxRules = new ArrayList<>();
|
||||||
|
protected ArrayList<TextboxRule> textboxKeywords = new ArrayList<>();
|
||||||
|
|
||||||
|
// The Construtor
|
||||||
|
// The constructor should prepare all of the things that it can
|
||||||
|
// without knowing the dimensions that the card will be rendered at.
|
||||||
|
// Then, the CardRenderer can be called on multiple times to render the
|
||||||
|
// card at various sizes (for instance, during animation)
|
||||||
|
public CardRenderer(CardView card, boolean isTransformed) {
|
||||||
|
// Set base parameters
|
||||||
|
this.cardView = card;
|
||||||
|
this.isTransformed = isTransformed;
|
||||||
|
|
||||||
|
// Translate the textbox text
|
||||||
|
for (String rule: card.getRules()) {
|
||||||
|
TextboxRule tbRule = TextboxRuleParser.parse(card, rule);
|
||||||
|
if (tbRule.type == TextboxRuleType.SIMPLE_KEYWORD) {
|
||||||
|
textboxKeywords.add(tbRule);
|
||||||
|
} else {
|
||||||
|
textboxRules.add(tbRule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout operation
|
||||||
|
// Calculate common layout metrics that will be used by several
|
||||||
|
// of the operations in the template method.
|
||||||
|
protected void layout(int cardWidth, int cardHeight) {
|
||||||
|
// Store the dimensions for the template methods to use
|
||||||
|
this.cardWidth = cardWidth;
|
||||||
|
this.cardHeight = cardHeight;
|
||||||
|
|
||||||
|
// Corner radius and border width
|
||||||
|
cornerRadius = (int)Math.max(
|
||||||
|
CORNER_RADIUS_MIN,
|
||||||
|
CORNER_RADIUS_FRAC * cardWidth);
|
||||||
|
|
||||||
|
borderWidth = (int)Math.max(
|
||||||
|
BORDER_WIDTH_MIN,
|
||||||
|
BORDER_WIDTH_FRAC * cardWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Draw Method
|
||||||
|
// The draw method takes the information caculated by the constructor
|
||||||
|
// and uses it to draw to a concrete size of card and graphics.
|
||||||
|
public void draw(Graphics2D g, int cardWidth, int cardHeight) {
|
||||||
|
// Pre template method layout, to calculate shared layout info
|
||||||
|
layout(cardWidth, cardHeight);
|
||||||
|
|
||||||
|
// Call the template methods
|
||||||
|
drawBorder(g);
|
||||||
|
drawBackground(g);
|
||||||
|
drawArt(g);
|
||||||
|
drawFrame(g);
|
||||||
|
drawOverlays(g);
|
||||||
|
drawCounters(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template methods to be implemented by sub classes
|
||||||
|
// For instance, for the Modern vs Old border card frames
|
||||||
|
protected abstract void drawBorder(Graphics2D g);
|
||||||
|
protected abstract void drawBackground(Graphics2D g);
|
||||||
|
protected abstract void drawArt(Graphics2D g);
|
||||||
|
protected abstract void drawFrame(Graphics2D g);
|
||||||
|
|
||||||
|
// Template methods that are possible to override, but unlikely to be
|
||||||
|
// overridden.
|
||||||
|
|
||||||
|
// Draw the card back
|
||||||
|
protected void drawCardBack(Graphics2D g) {
|
||||||
|
g.setPaint(BG_TEXTURE_CARDBACK);
|
||||||
|
g.fillRect(borderWidth, borderWidth,
|
||||||
|
cardWidth - 2*borderWidth, cardHeight - 2*borderWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw summoning sickness overlay, and possibly other overlays
|
||||||
|
protected void drawOverlays(Graphics2D g) {
|
||||||
|
if (cardView instanceof PermanentView) {
|
||||||
|
if (((PermanentView)cardView).hasSummoningSickness()) {
|
||||||
|
int x1 = (int)(0.2*cardWidth);
|
||||||
|
int x2 = (int)(0.8*cardWidth);
|
||||||
|
int y1 = (int)(0.2*cardHeight);
|
||||||
|
int y2 = (int)(0.8*cardHeight);
|
||||||
|
int xPoints[] = {
|
||||||
|
x1, x2, x1, x2
|
||||||
|
};
|
||||||
|
int yPoints[] = {
|
||||||
|
y1, y1, y2, y2
|
||||||
|
};
|
||||||
|
g.setColor(new Color(255, 255, 255, 200));
|
||||||
|
g.setStroke(new BasicStroke(7));
|
||||||
|
g.drawPolygon(xPoints, yPoints, 4);
|
||||||
|
g.setColor(new Color(0, 0, 0, 200));
|
||||||
|
g.setStroke(new BasicStroke(5));
|
||||||
|
g.drawPolygon(xPoints, yPoints, 4);
|
||||||
|
g.setStroke(new BasicStroke(1));
|
||||||
|
int[] xPoints2 = {
|
||||||
|
x1, x2, cardWidth/2
|
||||||
|
};
|
||||||
|
int[] yPoints2 = {
|
||||||
|
y1, y1, cardHeight/2
|
||||||
|
};
|
||||||
|
g.setColor(new Color(0, 0, 0, 100));
|
||||||
|
g.fillPolygon(xPoints2, yPoints2, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw +1/+1 and other counters
|
||||||
|
protected void drawCounters(Graphics2D g) {
|
||||||
|
int xPos = (int)(0.7*cardWidth);
|
||||||
|
int yPos = (int)(0.15*cardHeight);
|
||||||
|
if (cardView.getCounters() != null) {
|
||||||
|
for (CounterView v: cardView.getCounters()) {
|
||||||
|
// Don't render loyalty, we do that in the bottom corner
|
||||||
|
if (!v.getName().equals("loyalty")) {
|
||||||
|
Polygon p;
|
||||||
|
if (v.getName().equals("+1/+1")) {
|
||||||
|
p = PLUS_COUNTER_POLY;
|
||||||
|
} else if (v.getName().equals("-1/-1")) {
|
||||||
|
p = MINUS_COUNTER_POLY;
|
||||||
|
} else if (v.getName().equals("time")) {
|
||||||
|
p = TIME_COUNTER_POLY;
|
||||||
|
} else {
|
||||||
|
p = OTHER_COUNTER_POLY;
|
||||||
|
}
|
||||||
|
double scale = (0.1*0.18*cardWidth);
|
||||||
|
Graphics2D g2 = (Graphics2D)g.create();
|
||||||
|
g2.translate(xPos, yPos);
|
||||||
|
g2.scale(scale, scale);
|
||||||
|
g2.setColor(Color.white);
|
||||||
|
g2.fillPolygon(p);
|
||||||
|
g2.setColor(Color.black);
|
||||||
|
g2.drawPolygon(p);
|
||||||
|
g2.setFont(new Font("Arial", Font.BOLD, 7));
|
||||||
|
String cstr = "" + v.getCount();
|
||||||
|
int strW = g2.getFontMetrics().stringWidth(cstr);
|
||||||
|
g2.drawString(cstr, 5 - strW/2, 8);
|
||||||
|
g2.dispose();
|
||||||
|
yPos += ((int)(0.22*cardWidth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw an expansion symbol, right justified, in a given region
|
||||||
|
// Return the width of the drawn symbol
|
||||||
|
protected int drawExpansionSymbol(Graphics2D g, int x, int y, int w, int h) {
|
||||||
|
// Draw the expansion symbol
|
||||||
|
Image setSymbol = ManaSymbols.getSetSymbolImage(cardView.getExpansionSetCode(), cardView.getRarity().getCode());
|
||||||
|
int setSymbolWidth;
|
||||||
|
if (setSymbol == null) {
|
||||||
|
// Just draw the as a code
|
||||||
|
String code = cardView.getExpansionSetCode().toUpperCase();
|
||||||
|
FontMetrics metrics = g.getFontMetrics();
|
||||||
|
setSymbolWidth = metrics.stringWidth(code);
|
||||||
|
if (cardView.getRarity() == Rarity.COMMON) {
|
||||||
|
g.setColor(Color.white);
|
||||||
|
} else {
|
||||||
|
g.setColor(Color.black);
|
||||||
|
}
|
||||||
|
g.fillRoundRect(
|
||||||
|
x + w - setSymbolWidth - 1, y + 2,
|
||||||
|
setSymbolWidth+2, h - 5,
|
||||||
|
5, 5);
|
||||||
|
g.setColor(getRarityColor());
|
||||||
|
g.drawString(code, x + w - setSymbolWidth, y + h - 3);
|
||||||
|
} else {
|
||||||
|
// Draw the set symbol
|
||||||
|
int height = setSymbol.getHeight(null);
|
||||||
|
int scale = 1;
|
||||||
|
if (height != -1) {
|
||||||
|
while (height > h+2) {
|
||||||
|
scale *= 2;
|
||||||
|
height /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSymbolWidth = setSymbol.getWidth(null) / scale;
|
||||||
|
g.drawImage(setSymbol,
|
||||||
|
x + w - setSymbolWidth, y + (h - height)/2,
|
||||||
|
setSymbolWidth, height,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
return setSymbolWidth;
|
||||||
|
}
|
||||||
|
private Color getRarityColor() {
|
||||||
|
switch (cardView.getRarity()) {
|
||||||
|
case RARE:
|
||||||
|
return new Color(255, 191, 0);
|
||||||
|
case UNCOMMON:
|
||||||
|
return new Color(192, 192, 192);
|
||||||
|
case MYTHIC:
|
||||||
|
return new Color(213, 51, 11);
|
||||||
|
case SPECIAL:
|
||||||
|
return new Color(204, 0, 255);
|
||||||
|
case BONUS:
|
||||||
|
return new Color(129, 228, 228);
|
||||||
|
case COMMON:
|
||||||
|
default:
|
||||||
|
return Color.black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a string representing the type line
|
||||||
|
protected String getCardTypeLine() {
|
||||||
|
StringBuilder sbType = new StringBuilder();
|
||||||
|
for (String superType : cardView.getSuperTypes()) {
|
||||||
|
sbType.append(superType).append(" ");
|
||||||
|
}
|
||||||
|
for (CardType cardType : cardView.getCardTypes()) {
|
||||||
|
sbType.append(cardType.toString()).append(" ");
|
||||||
|
}
|
||||||
|
if (cardView.getSubTypes().size() > 0) {
|
||||||
|
sbType.append("- ");
|
||||||
|
for (String subType : cardView.getSubTypes()) {
|
||||||
|
sbType.append(subType).append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sbType.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the card art image (CardPanel will give it to us when it
|
||||||
|
// is loaded and ready)
|
||||||
|
public void setArtImage(Image image) {
|
||||||
|
artImage = CardRendererUtils.toBufferedImage(image);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.Paint;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*
|
||||||
|
* Various static utilities for use in the card renderer
|
||||||
|
*/
|
||||||
|
public class CardRendererUtils {
|
||||||
|
/**
|
||||||
|
* Convert an abstract image, whose underlying implementation may or may
|
||||||
|
* not be a BufferedImage into a BufferedImage by creating one and coping
|
||||||
|
* the contents if it is not, and simply up-casting if it is.
|
||||||
|
* @param img The image to convert
|
||||||
|
* @return The converted image
|
||||||
|
*/
|
||||||
|
public static BufferedImage toBufferedImage(Image img) {
|
||||||
|
// Null? No conversion to do
|
||||||
|
if (img == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already a buffered image?
|
||||||
|
if (img instanceof BufferedImage) {
|
||||||
|
return (BufferedImage) img;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a buffered image with transparency
|
||||||
|
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
// Draw the image on to the buffered image
|
||||||
|
Graphics2D bGr = bimage.createGraphics();
|
||||||
|
bGr.drawImage(img, 0, 0, null);
|
||||||
|
bGr.dispose();
|
||||||
|
|
||||||
|
// Return the buffered image
|
||||||
|
return bimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a rounded box with a 2-pixel border
|
||||||
|
// Used on various card parts.
|
||||||
|
public static void drawRoundedBox(Graphics2D g, int x, int y, int w, int h, int bevel, Paint border, Color fill) {
|
||||||
|
g.setColor(new Color(0, 0, 0, 150));
|
||||||
|
g.drawOval(x-1, y-1, bevel*2, h);
|
||||||
|
g.setPaint(border);
|
||||||
|
g.drawOval(x, y, bevel*2-1, h-1);
|
||||||
|
g.drawOval(x + w - bevel*2, y, bevel*2-1, h-1);
|
||||||
|
g.drawOval(x+1, y+1, bevel*2-3, h-3);
|
||||||
|
g.drawOval(x+1 + w - bevel*2, y+1, bevel*2-3, h-3);
|
||||||
|
g.drawRect(x + bevel, y, w - 2*bevel, h-1);
|
||||||
|
g.drawRect(x+1 + bevel, y+1, w - 2*bevel-2, h-3);
|
||||||
|
g.setColor(fill);
|
||||||
|
g.fillOval(x+2, y+2, bevel*2-4, h-4);
|
||||||
|
g.fillOval(x+2 + w - bevel*2, y+2, bevel*2-4, h-4);
|
||||||
|
g.fillRect(x + bevel, y+2, w - 2*bevel, h-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the width of a mana cost rendered with ManaSymbols.draw
|
||||||
|
public static int getManaCostWidth(String manaCost, int symbolSize) {
|
||||||
|
int width = 0;
|
||||||
|
manaCost = manaCost.replace("\\", "");
|
||||||
|
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
tok.nextToken();
|
||||||
|
width += symbolSize;
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abbreviate a piece of rules text, making substitutions to decrease its
|
||||||
|
// length. Also abbreviate reminder text.
|
||||||
|
private static Pattern abbreviationPattern;
|
||||||
|
private static Map<String, String> abbreviations = new HashMap<String, String>();
|
||||||
|
private static Pattern killReminderTextPattern;
|
||||||
|
static {
|
||||||
|
// Available abbreviations
|
||||||
|
abbreviations.put("enters the battlefield", "ETB");
|
||||||
|
abbreviations.put("less than", "<");
|
||||||
|
abbreviations.put("greater than", ">");
|
||||||
|
|
||||||
|
// Compile into regex
|
||||||
|
String patternString = "(";
|
||||||
|
Iterator<String> it = abbreviations.keySet().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
patternString += it.next();
|
||||||
|
if (it.hasNext()) {
|
||||||
|
patternString += "|";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patternString += ")";
|
||||||
|
abbreviationPattern = Pattern.compile(patternString);
|
||||||
|
|
||||||
|
// Reminder text killing
|
||||||
|
killReminderTextPattern = Pattern.compile("\\([^\\)]*\\)");
|
||||||
|
}
|
||||||
|
public static String abbreviateRule(String rule) {
|
||||||
|
StringBuffer build = new StringBuffer();
|
||||||
|
Matcher match = abbreviationPattern.matcher(rule);
|
||||||
|
while (match.find()) {
|
||||||
|
match.appendReplacement(build, abbreviations.get(match.group(1)));
|
||||||
|
}
|
||||||
|
match.appendTail(build);
|
||||||
|
return build.toString();
|
||||||
|
}
|
||||||
|
public static String killReminderText(String rule) {
|
||||||
|
return killReminderTextPattern.matcher(rule).replaceAll("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ public class ManaSymbols {
|
||||||
private static boolean smallSymbolsFound = false;
|
private static boolean smallSymbolsFound = false;
|
||||||
private static boolean mediumSymbolsFound = false;
|
private static boolean mediumSymbolsFound = false;
|
||||||
|
|
||||||
private static final Map<String, Image> setImages = new HashMap<>();
|
private static final Map<String, Map<String, Image>> setImages = new HashMap<>();
|
||||||
private static final Map<String, Dimension> setImagesExist = new HashMap<>();
|
private static final Map<String, Dimension> setImagesExist = new HashMap<>();
|
||||||
private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}");
|
private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}");
|
||||||
private static String cachedPath;
|
private static String cachedPath;
|
||||||
|
@ -57,7 +57,13 @@ public class ManaSymbols {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (String set : setCodes) {
|
for (String set : setCodes) {
|
||||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-C.jpg");
|
String[] codes = new String[]{"C", "U", "R", "M"};
|
||||||
|
|
||||||
|
Map<String, Image> rarityImages = new HashMap<>();
|
||||||
|
setImages.put(set, rarityImages);
|
||||||
|
|
||||||
|
for (String rarityCode: codes) {
|
||||||
|
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-" + rarityCode + ".jpg");
|
||||||
try {
|
try {
|
||||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||||
int width = image.getWidth(null);
|
int width = image.getWidth(null);
|
||||||
|
@ -66,16 +72,17 @@ public class ManaSymbols {
|
||||||
if (h > 0) {
|
if (h > 0) {
|
||||||
Rectangle r = new Rectangle(21, (int) (h * 21.0f / width));
|
Rectangle r = new Rectangle(21, (int) (h * 21.0f / width));
|
||||||
BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||||
setImages.put(set, resized);
|
rarityImages.put(set, resized);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setImages.put(set, image);
|
rarityImages.put(rarityCode, image);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
String[] codes = new String[]{"C", "U", "R", "M"};
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
file.mkdirs();
|
file.mkdirs();
|
||||||
}
|
}
|
||||||
|
@ -298,14 +305,27 @@ public class ManaSymbols {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Image getSetSymbolImage(String set) {
|
public static Image getSetSymbolImage(String set) {
|
||||||
return setImages.get(set);
|
return getSetSymbolImage(set, "C");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image getSetSymbolImage(String set, String rarity) {
|
||||||
|
Map<String, Image> rarityImages = setImages.get(set);
|
||||||
|
if (rarityImages != null) {
|
||||||
|
return rarityImages.get(rarity);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage getSizedManaSymbol(String symbol) {
|
public static BufferedImage getSizedManaSymbol(String symbol) {
|
||||||
if (!manaImages.containsKey(GUISizeHelper.symbolDialogSize)) {
|
return getSizedManaSymbol(symbol, GUISizeHelper.symbolDialogSize);
|
||||||
loadSymbolsImages(GUISizeHelper.symbolDialogSize);
|
|
||||||
}
|
}
|
||||||
Map<String, BufferedImage> sizedSymbols = manaImages.get(GUISizeHelper.symbolDialogSize);
|
|
||||||
|
public static BufferedImage getSizedManaSymbol(String symbol, int size) {
|
||||||
|
if (!manaImages.containsKey(size)) {
|
||||||
|
loadSymbolsImages(size);
|
||||||
|
}
|
||||||
|
Map<String, BufferedImage> sizedSymbols = manaImages.get(size);
|
||||||
return sizedSymbols.get(symbol);
|
return sizedSymbols.get(symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,934 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.GradientPaint;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.LinearGradientPaint;
|
||||||
|
import java.awt.Paint;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Shape;
|
||||||
|
import java.awt.TexturePaint;
|
||||||
|
import java.awt.font.FontRenderContext;
|
||||||
|
import java.awt.font.LineBreakMeasurer;
|
||||||
|
import java.awt.font.TextAttribute;
|
||||||
|
import java.awt.font.TextLayout;
|
||||||
|
import java.awt.font.TextMeasurer;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.text.AttributedCharacterIterator;
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.text.CharacterIterator;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.view.CardView;
|
||||||
|
import mage.view.PermanentView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.mage.card.arcane.CardRenderer;
|
||||||
|
import org.mage.card.arcane.CardRendererUtils;
|
||||||
|
import org.mage.card.arcane.ManaSymbols;
|
||||||
|
import org.mage.card.arcane.TextboxLoyaltyRule;
|
||||||
|
import org.mage.card.arcane.TextboxRule;
|
||||||
|
import org.mage.card.arcane.TextboxRuleType;
|
||||||
|
import sun.security.pkcs11.P11TlsKeyMaterialGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
private void cardRendererBasedRender(Graphics2D g) {
|
||||||
|
// Prepare for draw
|
||||||
|
g.translate(cardXOffset, cardYOffset);
|
||||||
|
int cardWidth = this.cardWidth - cardXOffset;
|
||||||
|
int cardHeight = this.cardHeight - cardYOffset;
|
||||||
|
|
||||||
|
// AA on
|
||||||
|
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
// Renderer
|
||||||
|
CardRenderer render = new ModernCardRenderer(gameCard, transformed);
|
||||||
|
Image img = imagePanel.getSrcImage();
|
||||||
|
if (img != null) {
|
||||||
|
render.setArtImage(img);
|
||||||
|
}
|
||||||
|
render.draw(g, cardWidth, cardHeight);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*
|
||||||
|
* Base rendering class for new border cards
|
||||||
|
*/
|
||||||
|
public class ModernCardRenderer extends CardRenderer {
|
||||||
|
private static Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Textures for modern frame cards
|
||||||
|
|
||||||
|
private static TexturePaint loadBackgroundTexture(String name) {
|
||||||
|
URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png");
|
||||||
|
ImageIcon icon = new ImageIcon(url);
|
||||||
|
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
|
||||||
|
return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
|
||||||
|
}
|
||||||
|
public static Paint BG_TEXTURE_WHITE = loadBackgroundTexture("white");
|
||||||
|
public static Paint BG_TEXTURE_BLUE = loadBackgroundTexture("blue");
|
||||||
|
public static Paint BG_TEXTURE_BLACK = loadBackgroundTexture("black");
|
||||||
|
public static Paint BG_TEXTURE_RED = loadBackgroundTexture("red");
|
||||||
|
public static Paint BG_TEXTURE_GREEN = loadBackgroundTexture("green");
|
||||||
|
public static Paint BG_TEXTURE_GOLD = loadBackgroundTexture("gold");
|
||||||
|
public static Paint BG_TEXTURE_ARTIFACT = loadBackgroundTexture("artifact");
|
||||||
|
public static Paint BG_TEXTURE_LAND = loadBackgroundTexture("land");
|
||||||
|
|
||||||
|
public static Color BORDER_WHITE = new Color(216, 203, 188);
|
||||||
|
public static Color BORDER_BLUE = new Color(20, 121, 175);
|
||||||
|
public static Color BORDER_BLACK = new Color(45, 45, 35);
|
||||||
|
public static Color BORDER_RED = new Color(201, 71, 58);
|
||||||
|
public static Color BORDER_GREEN = new Color(4, 136, 69);
|
||||||
|
public static Color BORDER_GOLD = new Color(255, 228, 124);
|
||||||
|
public static Color BORDER_COLORLESS = new Color(238, 242, 242);
|
||||||
|
public static Color BORDER_LAND = new Color(190, 173, 115);
|
||||||
|
|
||||||
|
public static Color BOX_WHITE = new Color(244, 245, 239);
|
||||||
|
public static Color BOX_BLUE = new Color(201, 223, 237);
|
||||||
|
public static Color BOX_BLACK = new Color(204, 194, 192);
|
||||||
|
public static Color BOX_RED = new Color(246, 208, 185);
|
||||||
|
public static Color BOX_GREEN = new Color(205, 221, 213);
|
||||||
|
public static Color BOX_GOLD = new Color(223, 195, 136);
|
||||||
|
public static Color BOX_COLORLESS = new Color(220, 228, 232);
|
||||||
|
public static Color BOX_LAND = new Color(220, 215, 213);
|
||||||
|
|
||||||
|
public static Color BOX_WHITE_NIGHT = new Color(169, 160, 145);
|
||||||
|
public static Color BOX_BLUE_NIGHT = new Color(46, 133, 176);
|
||||||
|
public static Color BOX_BLACK_NIGHT = new Color(95, 90, 89);
|
||||||
|
public static Color BOX_RED_NIGHT = new Color(188, 87, 57);
|
||||||
|
public static Color BOX_GREEN_NIGHT = new Color(31, 100, 44);
|
||||||
|
public static Color BOX_GOLD_NIGHT = new Color(171, 134, 70);
|
||||||
|
public static Color BOX_COLORLESS_NIGHT = new Color(118, 147, 158);
|
||||||
|
|
||||||
|
public static Color TEXTBOX_WHITE = new Color(252, 249, 244, 244);
|
||||||
|
public static Color TEXTBOX_BLUE = new Color(229, 238, 247, 244);
|
||||||
|
public static Color TEXTBOX_BLACK = new Color(241, 241, 240, 244);
|
||||||
|
public static Color TEXTBOX_RED = new Color(243, 224, 217, 244);
|
||||||
|
public static Color TEXTBOX_GREEN = new Color(217, 232, 223, 244);
|
||||||
|
public static Color TEXTBOX_GOLD = new Color(240, 234, 209, 244);
|
||||||
|
public static Color TEXTBOX_COLORLESS = new Color(219, 229, 233, 244);
|
||||||
|
public static Color TEXTBOX_LAND = new Color(218, 214, 212, 244);
|
||||||
|
|
||||||
|
public static Color ERROR_COLOR = new Color(255, 0, 255);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Layout metrics for modern border cards
|
||||||
|
|
||||||
|
// How far the main box, art, and name / type line are inset from the
|
||||||
|
// card border. That is, the width of background texture that shows around
|
||||||
|
// the edge of the card.
|
||||||
|
protected int contentInset;
|
||||||
|
|
||||||
|
// Helper: The total inset from card edge to rules box etc.
|
||||||
|
// = borderWidth + contentInset
|
||||||
|
protected int totalContentInset;
|
||||||
|
|
||||||
|
// Width of the content region of the card
|
||||||
|
// = cardWidth - 2 x totalContentInset
|
||||||
|
protected int contentWidth;
|
||||||
|
|
||||||
|
// How tall the name / type lines and P/T box are
|
||||||
|
protected static float BOX_HEIGHT_FRAC = 0.065f; // x cardHeight
|
||||||
|
protected static int BOX_HEIGHT_MIN = 16;
|
||||||
|
protected int boxHeight;
|
||||||
|
|
||||||
|
// How far down the card is the type line placed?
|
||||||
|
protected static float TYPE_LINE_Y_FRAC = 0.57f; // x cardHeight
|
||||||
|
protected int typeLineY;
|
||||||
|
|
||||||
|
// How large is the box text, and how far is it down the boxes
|
||||||
|
protected int boxTextHeight;
|
||||||
|
protected int boxTextOffset;
|
||||||
|
protected Font boxTextFont;
|
||||||
|
|
||||||
|
// How large is the P/T text, and how far is it down the boxes
|
||||||
|
protected int ptTextHeight;
|
||||||
|
protected int ptTextOffset;
|
||||||
|
protected Font ptTextFont;
|
||||||
|
|
||||||
|
// Processed mana cost string
|
||||||
|
protected String manaCostString;
|
||||||
|
|
||||||
|
public ModernCardRenderer(CardView card, boolean isTransformed) {
|
||||||
|
// Pass off to parent
|
||||||
|
super(card, isTransformed);
|
||||||
|
|
||||||
|
// Mana cost string
|
||||||
|
manaCostString = ManaSymbols.getStringManaCost(cardView.getManaCost());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void layout(int cardWidth, int cardHeight) {
|
||||||
|
// Pass to parent
|
||||||
|
super.layout(cardWidth, cardHeight);
|
||||||
|
|
||||||
|
// Content inset, just equal to border width
|
||||||
|
contentInset = borderWidth;
|
||||||
|
|
||||||
|
// Total content inset helper
|
||||||
|
totalContentInset = borderWidth + contentInset;
|
||||||
|
|
||||||
|
// Content width
|
||||||
|
contentWidth = cardWidth - 2*totalContentInset;
|
||||||
|
|
||||||
|
// Box height
|
||||||
|
boxHeight = (int)Math.max(
|
||||||
|
BOX_HEIGHT_MIN,
|
||||||
|
BOX_HEIGHT_FRAC * cardHeight);
|
||||||
|
|
||||||
|
// Type line at
|
||||||
|
typeLineY = (int)(TYPE_LINE_Y_FRAC * cardHeight);
|
||||||
|
|
||||||
|
// Box text height
|
||||||
|
boxTextHeight = getTextHeightForBoxHeight(boxHeight);
|
||||||
|
boxTextOffset = (boxHeight - boxTextHeight)/2;
|
||||||
|
boxTextFont = new Font("Beleren", Font.PLAIN, boxTextHeight);
|
||||||
|
|
||||||
|
// Box text height
|
||||||
|
ptTextHeight = getPTTextHeightForLineHeight(boxHeight);
|
||||||
|
ptTextOffset = (boxHeight - ptTextHeight)/2;
|
||||||
|
ptTextFont = new Font("Beleren", Font.PLAIN, ptTextHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBorder(Graphics2D g) {
|
||||||
|
// Draw border as one rounded rectangle
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.fillRoundRect(0, 0, cardWidth, cardHeight, cornerRadius, cornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBackground(Graphics2D g) {
|
||||||
|
// Draw background, in 3 parts
|
||||||
|
|
||||||
|
if (cardView.isFaceDown()) {
|
||||||
|
// Just draw a brown rectangle
|
||||||
|
drawCardBack(g);
|
||||||
|
} else {
|
||||||
|
// Set texture to paint with
|
||||||
|
g.setPaint(getBackgroundPaint(cardView.getColor(), cardView.getCardTypes()));
|
||||||
|
|
||||||
|
// Draw main part (most of card)
|
||||||
|
g.fillRoundRect(
|
||||||
|
borderWidth, borderWidth,
|
||||||
|
cardWidth - borderWidth*2, cardHeight - borderWidth*4 - cornerRadius*2,
|
||||||
|
cornerRadius - 1, cornerRadius - 1);
|
||||||
|
|
||||||
|
// Draw the M15 rounded "swoosh" at the bottom
|
||||||
|
g.fillRoundRect(
|
||||||
|
borderWidth, cardHeight - borderWidth*4 - cornerRadius*4,
|
||||||
|
cardWidth - borderWidth*2, cornerRadius*4,
|
||||||
|
cornerRadius*2, cornerRadius*2);
|
||||||
|
|
||||||
|
// Draw the cutout into the "swoosh" for the textbox to lie over
|
||||||
|
g.fillRect(
|
||||||
|
borderWidth + contentInset, cardHeight - borderWidth*5,
|
||||||
|
cardWidth - borderWidth*2 - contentInset*2, borderWidth*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawArt(Graphics2D g) {
|
||||||
|
if (artImage != null) {
|
||||||
|
int imgWidth = artImage.getWidth();
|
||||||
|
int imgHeight = artImage.getHeight();
|
||||||
|
BufferedImage subImg =
|
||||||
|
artImage.getSubimage(
|
||||||
|
(int)(.079*imgWidth), (int)(.11*imgHeight),
|
||||||
|
(int)(.84*imgWidth), (int)(.42*imgHeight));
|
||||||
|
g.drawImage(subImg,
|
||||||
|
totalContentInset+1, totalContentInset+boxHeight,
|
||||||
|
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawFrame(Graphics2D g) {
|
||||||
|
// Get the card colors to base the frame on
|
||||||
|
ObjectColor frameColors = getFrameObjectColor();
|
||||||
|
|
||||||
|
// Get the border paint
|
||||||
|
Color boxColor = getBoxColor(frameColors, cardView.getCardTypes(), isTransformed);
|
||||||
|
Paint textboxPaint = getTextboxPaint(frameColors, cardView.getCardTypes(), cardWidth);
|
||||||
|
Paint borderPaint = getBorderPaint(frameColors, cardView.getCardTypes(), cardWidth);
|
||||||
|
|
||||||
|
// Draw the main card content border
|
||||||
|
g.setPaint(borderPaint);
|
||||||
|
g.drawRect(
|
||||||
|
totalContentInset, totalContentInset,
|
||||||
|
contentWidth - 1, cardHeight - borderWidth*3 - totalContentInset - 1);
|
||||||
|
|
||||||
|
// Draw the textbox fill
|
||||||
|
g.setPaint(textboxPaint);
|
||||||
|
g.fillRect(
|
||||||
|
totalContentInset + 1, typeLineY,
|
||||||
|
contentWidth - 2, cardHeight - borderWidth*3 - typeLineY - 1);
|
||||||
|
|
||||||
|
// If it's a planeswalker, extend the textbox left border by some
|
||||||
|
if (cardView.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||||
|
g.setPaint(borderPaint);
|
||||||
|
g.fillRect(
|
||||||
|
totalContentInset, typeLineY + boxHeight,
|
||||||
|
cardWidth/16, cardHeight - typeLineY - boxHeight - borderWidth*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a shadow highlight at the right edge of the content frame
|
||||||
|
g.setColor(new Color(0, 0, 0, 100));
|
||||||
|
g.fillRect(
|
||||||
|
totalContentInset - 1, totalContentInset,
|
||||||
|
1, cardHeight - borderWidth*3 - totalContentInset - 1);
|
||||||
|
|
||||||
|
// Draw a shadow highlight separating the card art and rest of frame
|
||||||
|
g.drawRect(
|
||||||
|
totalContentInset + 1, totalContentInset + boxHeight,
|
||||||
|
contentWidth - 3, typeLineY - totalContentInset - boxHeight - 1);
|
||||||
|
|
||||||
|
// Draw the name line box
|
||||||
|
CardRendererUtils.drawRoundedBox(g,
|
||||||
|
borderWidth, totalContentInset,
|
||||||
|
cardWidth - 2*borderWidth, boxHeight,
|
||||||
|
contentInset,
|
||||||
|
borderPaint, boxColor);
|
||||||
|
|
||||||
|
// Draw the type line box
|
||||||
|
CardRendererUtils.drawRoundedBox(g,
|
||||||
|
borderWidth, typeLineY,
|
||||||
|
cardWidth - 2*borderWidth, boxHeight,
|
||||||
|
contentInset,
|
||||||
|
borderPaint, boxColor);
|
||||||
|
|
||||||
|
// Draw a small separator between the type line and box, and shadow
|
||||||
|
// at the left of the texbox, and above the name line
|
||||||
|
g.setColor(new Color(0, 0, 0, 150));
|
||||||
|
g.fillRect(
|
||||||
|
totalContentInset - 1, totalContentInset - 1,
|
||||||
|
contentWidth + 1, 1);
|
||||||
|
g.fillRect(
|
||||||
|
totalContentInset + 1, typeLineY + boxHeight,
|
||||||
|
contentWidth - 2, 1);
|
||||||
|
g.fillRect(
|
||||||
|
cardWidth - totalContentInset - 1, typeLineY + boxHeight,
|
||||||
|
1, cardHeight - borderWidth*3 - typeLineY - boxHeight);
|
||||||
|
|
||||||
|
// Draw the transform circle
|
||||||
|
int nameOffset = drawTransformationCircle(g, borderPaint);
|
||||||
|
|
||||||
|
// Draw the name line
|
||||||
|
drawNameLine(g,
|
||||||
|
totalContentInset + nameOffset, totalContentInset,
|
||||||
|
contentWidth - nameOffset, boxHeight);
|
||||||
|
|
||||||
|
// Draw the type line
|
||||||
|
drawTypeLine(g,
|
||||||
|
totalContentInset, typeLineY,
|
||||||
|
contentWidth, boxHeight);
|
||||||
|
|
||||||
|
// Draw the textbox rules
|
||||||
|
drawRulesText(g,
|
||||||
|
totalContentInset + 2, typeLineY + boxHeight + 2,
|
||||||
|
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth*3);
|
||||||
|
|
||||||
|
// Draw the bottom right stuff
|
||||||
|
drawBottomRight(g, borderPaint, boxColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the name line
|
||||||
|
protected void drawNameLine(Graphics2D g, int x, int y, int w, int h) {
|
||||||
|
// Width of the mana symbols
|
||||||
|
int manaCostWidth = CardRendererUtils.getManaCostWidth(manaCostString, boxTextHeight);
|
||||||
|
|
||||||
|
// Available width for name. Add a little bit of slop so that one character
|
||||||
|
// can partially go underneath the mana cost
|
||||||
|
int availableWidth = w - manaCostWidth + 2;
|
||||||
|
|
||||||
|
// Draw the name
|
||||||
|
AttributedString str = new AttributedString(cardView.getName());
|
||||||
|
str.addAttribute(TextAttribute.FONT, boxTextFont);
|
||||||
|
TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext());
|
||||||
|
TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth));
|
||||||
|
g.setColor(getBoxTextColor());
|
||||||
|
layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1);
|
||||||
|
|
||||||
|
// Draw the mana symbols
|
||||||
|
ManaSymbols.draw(g, manaCostString, x + w - manaCostWidth, y + boxTextOffset, boxTextHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the type line (color indicator, types, and expansion symbol)
|
||||||
|
protected void drawTypeLine(Graphics2D g, int x, int y, int w, int h) {
|
||||||
|
// Draw expansion symbol
|
||||||
|
int expansionSymbolWidth = drawExpansionSymbol(g, x, y, w, h);
|
||||||
|
|
||||||
|
// Draw type line text
|
||||||
|
int availableWidth = w - expansionSymbolWidth + 1;
|
||||||
|
String types = getCardTypeLine();
|
||||||
|
g.setFont(boxTextFont);
|
||||||
|
|
||||||
|
// Replace "Legendary" in type line if there's not enough space
|
||||||
|
if (g.getFontMetrics().stringWidth(types) > availableWidth) {
|
||||||
|
types = types.replace("Legendary", "L.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AttributedString str = new AttributedString(types);
|
||||||
|
str.addAttribute(TextAttribute.FONT, boxTextFont);
|
||||||
|
TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext());
|
||||||
|
TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth));
|
||||||
|
g.setColor(getBoxTextColor());
|
||||||
|
layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the P/T and/or Loyalty boxes
|
||||||
|
protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) {
|
||||||
|
// Where to start drawing the things
|
||||||
|
int curY = cardHeight - (int)(0.03f*cardHeight);
|
||||||
|
|
||||||
|
// Width of the boxes
|
||||||
|
int partWidth = (int)Math.max(30, 0.20f*cardWidth);
|
||||||
|
|
||||||
|
// Is it a creature?
|
||||||
|
if (cardView.getCardTypes().contains(CardType.CREATURE)) {
|
||||||
|
int x = cardWidth - borderWidth - partWidth;
|
||||||
|
|
||||||
|
// Draw PT box
|
||||||
|
CardRendererUtils.drawRoundedBox(g,
|
||||||
|
x, curY - boxHeight,
|
||||||
|
partWidth, boxHeight,
|
||||||
|
contentInset,
|
||||||
|
borderPaint,
|
||||||
|
fill);
|
||||||
|
|
||||||
|
// Draw shadow line top
|
||||||
|
g.setColor(new Color(0, 0, 0, 150));
|
||||||
|
g.fillRect(
|
||||||
|
x + contentInset, curY - boxHeight - 1,
|
||||||
|
partWidth - 2*contentInset, 1);
|
||||||
|
|
||||||
|
// Draw text
|
||||||
|
g.setColor(getBoxTextColor());
|
||||||
|
g.setFont(ptTextFont);
|
||||||
|
String ptText = cardView.getPower() + "/" + cardView.getToughness();
|
||||||
|
int ptTextWidth = g.getFontMetrics().stringWidth(ptText);
|
||||||
|
g.drawString(ptText,
|
||||||
|
x + (partWidth - ptTextWidth)/2, curY - ptTextOffset - 1);
|
||||||
|
|
||||||
|
// Does it have damage on it?
|
||||||
|
if ((cardView instanceof PermanentView) && ((PermanentView)cardView).getDamage() > 0) {
|
||||||
|
// Show marked damage
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
curY -= boxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a walker?
|
||||||
|
if (cardView.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||||
|
// Draw the PW loyalty box
|
||||||
|
int w = partWidth;
|
||||||
|
int h = partWidth/2;
|
||||||
|
int x = cardWidth - partWidth - borderWidth;
|
||||||
|
int y = curY - h;
|
||||||
|
|
||||||
|
Polygon symbol = new Polygon(
|
||||||
|
new int[]{
|
||||||
|
x + w/2,
|
||||||
|
(int)(x + w*0.9),
|
||||||
|
x + w,
|
||||||
|
(int)(x + w*0.6),
|
||||||
|
x + w/2,
|
||||||
|
(int)(x + w*0.4),
|
||||||
|
x,
|
||||||
|
(int)(x + w*0.1),
|
||||||
|
},
|
||||||
|
new int[]{
|
||||||
|
y + h,
|
||||||
|
(int)(y + 0.8*h),
|
||||||
|
y,
|
||||||
|
(int)(y - 0.2*h),
|
||||||
|
y,
|
||||||
|
(int)(y - 0.2*h),
|
||||||
|
y,
|
||||||
|
(int)(y + 0.8*h),
|
||||||
|
},
|
||||||
|
8);
|
||||||
|
|
||||||
|
// Draw + stroke
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.fillPolygon(symbol);
|
||||||
|
g.setColor(new Color(200, 200, 200));
|
||||||
|
g.setStroke(new BasicStroke(2));
|
||||||
|
g.drawPolygon(symbol);
|
||||||
|
g.setStroke(new BasicStroke(1));
|
||||||
|
|
||||||
|
// Loyalty number
|
||||||
|
String loyalty;
|
||||||
|
if (cardView instanceof PermanentView) {
|
||||||
|
loyalty = cardView.getLoyalty();
|
||||||
|
} else {
|
||||||
|
loyalty = cardView.getStartingLoyalty();
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setFont(ptTextFont);
|
||||||
|
g.setColor(Color.white);
|
||||||
|
int loyaltyWidth = g.getFontMetrics().stringWidth(loyalty);
|
||||||
|
g.drawString(loyalty, x + (w - loyaltyWidth)/2, y + ptTextHeight + (h - ptTextHeight)/2);
|
||||||
|
|
||||||
|
// Advance
|
||||||
|
curY -= (int)(1.2*y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the card's textbox in a given rect
|
||||||
|
protected boolean loyaltyAbilityColorToggle = false;
|
||||||
|
protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) {
|
||||||
|
// Initial font size to try to render at
|
||||||
|
Font font = new Font("Arial", Font.PLAIN, 12);
|
||||||
|
Font fontItalic = new Font("Arial", Font.ITALIC, 12);
|
||||||
|
|
||||||
|
// Handle the keyword rules
|
||||||
|
boolean hasKeywords = !textboxKeywords.isEmpty();
|
||||||
|
String keywordRulesString = getKeywordRulesString();
|
||||||
|
AttributedString keywordRulesAttributed = new AttributedString(keywordRulesString);
|
||||||
|
if (hasKeywords) {
|
||||||
|
keywordRulesAttributed.addAttribute(TextAttribute.FONT, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total height
|
||||||
|
List<AttributedString> attributedRules = new ArrayList<>();
|
||||||
|
boolean useSmallFont = false;
|
||||||
|
int remaining = h;
|
||||||
|
{
|
||||||
|
if (hasKeywords) {
|
||||||
|
remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false);
|
||||||
|
}
|
||||||
|
for (TextboxRule rule: textboxRules) {
|
||||||
|
AttributedString attributed = rule.generateAttributedString(font, fontItalic);
|
||||||
|
attributedRules.add(attributed);
|
||||||
|
remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false);
|
||||||
|
if (remaining < 0) {
|
||||||
|
useSmallFont = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there wasn't enough room, try using a smaller font
|
||||||
|
if (useSmallFont) {
|
||||||
|
font = new Font("Arial", Font.PLAIN, 9);
|
||||||
|
fontItalic = new Font("Arial", Font.ITALIC, 9);
|
||||||
|
if (hasKeywords) {
|
||||||
|
keywordRulesAttributed = new AttributedString(keywordRulesString);
|
||||||
|
keywordRulesAttributed.addAttribute(TextAttribute.FONT, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear out the attributed rules and reatribute them with the new font size
|
||||||
|
attributedRules.clear();
|
||||||
|
for (TextboxRule rule: textboxRules) {
|
||||||
|
AttributedString attributed = rule.generateAttributedString(font, fontItalic);
|
||||||
|
attributedRules.add(attributed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have room for additional spacing between the parts of text?
|
||||||
|
// If so, calculate the spacing based on how much space was left over
|
||||||
|
int spacing;
|
||||||
|
if (useSmallFont) {
|
||||||
|
spacing = 0;
|
||||||
|
} else {
|
||||||
|
spacing = (int)(remaining / (hasKeywords ? (textboxRules.size() + 2) : (textboxRules.size() + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the actual draw
|
||||||
|
loyaltyAbilityColorToggle = false;
|
||||||
|
g.setColor(Color.black);
|
||||||
|
int curY = y + spacing;
|
||||||
|
if (hasKeywords) {
|
||||||
|
int adv = drawSingleRule(g, keywordRulesAttributed, null, x, y, w, h, true);
|
||||||
|
curY += adv + spacing;
|
||||||
|
h -= adv;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < textboxRules.size(); ++i) {
|
||||||
|
TextboxRule rule = textboxRules.get(i);
|
||||||
|
AttributedString attributedRule = attributedRules.get(i);
|
||||||
|
int adv = drawSingleRule(g, attributedRule, rule, x, curY, w, h, true);
|
||||||
|
curY += adv + spacing;
|
||||||
|
h -= adv;
|
||||||
|
if (h < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first line of the textbox, the keyword string
|
||||||
|
private String getKeywordRulesString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < textboxKeywords.size(); ++i) {
|
||||||
|
builder.append(textboxKeywords.get(i).text);
|
||||||
|
if (i != textboxKeywords.size() - 1) {
|
||||||
|
builder.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a single rule and returns the amount vertically advanced by, but
|
||||||
|
// only if doDraw is true. If doDraw is false, just returns the vertical
|
||||||
|
// advance if the rule were to be drawn.
|
||||||
|
private int drawSingleRule(Graphics2D g, AttributedString text, TextboxRule rule, int x, int y, int w, int h, boolean doDraw) {
|
||||||
|
// Inset, in case we are a leveler or loyalty ability
|
||||||
|
int inset = 0;
|
||||||
|
if (rule != null && rule.type == TextboxRuleType.LOYALTY) {
|
||||||
|
inset = cardWidth/12;
|
||||||
|
}
|
||||||
|
int availWidth = w - inset;
|
||||||
|
|
||||||
|
FontRenderContext frc = g.getFontRenderContext();
|
||||||
|
AttributedCharacterIterator textIter = text.getIterator();
|
||||||
|
LineBreakMeasurer measure = new LineBreakMeasurer(textIter, frc);
|
||||||
|
float yPos = y;
|
||||||
|
float remain = h;
|
||||||
|
AttributedCharacterIterator newLineCheck = text.getIterator();
|
||||||
|
while (measure.getPosition() < textIter.getEndIndex()) {
|
||||||
|
// Advance iterator to next line break
|
||||||
|
char ch = newLineCheck.setIndex(measure.getPosition());
|
||||||
|
while ((ch = newLineCheck.next()) != CharacterIterator.DONE) {
|
||||||
|
if (ch == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the text layout
|
||||||
|
TextLayout layout = measure.nextLayout(availWidth, newLineCheck.getIndex(), false);
|
||||||
|
float ascent = layout.getAscent();
|
||||||
|
yPos += ascent;
|
||||||
|
remain -= ascent;
|
||||||
|
if (remain < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (doDraw) {
|
||||||
|
g.setColor(Color.black);
|
||||||
|
layout.draw(g, x + inset, yPos);
|
||||||
|
}
|
||||||
|
yPos += layout.getDescent() + layout.getLeading() - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance
|
||||||
|
int advance = ((int)Math.ceil(yPos)) - y;
|
||||||
|
|
||||||
|
// Is it a loyalty ability?
|
||||||
|
if (rule != null && rule.type == TextboxRuleType.LOYALTY) {
|
||||||
|
TextboxLoyaltyRule loyaltyRule = (TextboxLoyaltyRule)rule;
|
||||||
|
Polygon symbol;
|
||||||
|
int symbolWidth = (x + inset) - borderWidth - 4;
|
||||||
|
int symbolHeight = (int)(0.7f*symbolWidth);
|
||||||
|
if (symbolHeight > advance) {
|
||||||
|
advance = symbolHeight;
|
||||||
|
}
|
||||||
|
int symbolX = x - borderWidth;
|
||||||
|
int symbolY = y + (advance - symbolHeight)/2;
|
||||||
|
if (doDraw) {
|
||||||
|
if (loyaltyRule.loyaltyChange < 0 || loyaltyRule.loyaltyChange == TextboxLoyaltyRule.MINUS_X) {
|
||||||
|
symbol = new Polygon(
|
||||||
|
new int[]{
|
||||||
|
symbolX,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX + symbolWidth/2,
|
||||||
|
symbolX,
|
||||||
|
},
|
||||||
|
new int[]{
|
||||||
|
symbolY,
|
||||||
|
symbolY,
|
||||||
|
symbolY + symbolHeight - 3,
|
||||||
|
symbolY + symbolHeight + 3,
|
||||||
|
symbolY + symbolHeight - 3,
|
||||||
|
},
|
||||||
|
5);
|
||||||
|
} else if (loyaltyRule.loyaltyChange > 0) {
|
||||||
|
symbol = new Polygon(
|
||||||
|
new int[]{
|
||||||
|
symbolX,
|
||||||
|
symbolX + symbolWidth/2,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX,
|
||||||
|
},
|
||||||
|
new int[]{
|
||||||
|
symbolY + 3,
|
||||||
|
symbolY - 3,
|
||||||
|
symbolY + 3,
|
||||||
|
symbolY + symbolHeight,
|
||||||
|
symbolY + symbolHeight,
|
||||||
|
},
|
||||||
|
5);
|
||||||
|
} else {
|
||||||
|
symbol = new Polygon(
|
||||||
|
new int[]{
|
||||||
|
symbolX,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX + symbolWidth,
|
||||||
|
symbolX,
|
||||||
|
},
|
||||||
|
new int[]{
|
||||||
|
symbolY,
|
||||||
|
symbolY,
|
||||||
|
symbolY + symbolHeight,
|
||||||
|
symbolY + symbolHeight,
|
||||||
|
},
|
||||||
|
4);
|
||||||
|
}
|
||||||
|
g.setColor(new Color(0, 0, 0, 128));
|
||||||
|
g.fillRect(x+2, y+advance+1, w-2, 1);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.fillPolygon(symbol);
|
||||||
|
g.setColor(new Color(200, 200, 200));
|
||||||
|
g.setStroke(new BasicStroke(2));
|
||||||
|
g.drawPolygon(symbol);
|
||||||
|
g.setStroke(new BasicStroke(1));
|
||||||
|
g.setColor(Color.white);
|
||||||
|
g.setFont(boxTextFont);
|
||||||
|
String loyaltyString = loyaltyRule.getChangeString();
|
||||||
|
int textWidth = g.getFontMetrics().stringWidth(loyaltyString);
|
||||||
|
g.drawString(loyaltyString,
|
||||||
|
symbolX + (symbolWidth - textWidth)/2,
|
||||||
|
symbolY + symbolHeight - (symbolHeight - boxTextHeight)/2);
|
||||||
|
|
||||||
|
advance += 3;
|
||||||
|
loyaltyAbilityColorToggle = !loyaltyAbilityColorToggle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the transformation circle if there is one, and return the
|
||||||
|
// horizontal width taken up into the content space by it.
|
||||||
|
protected boolean isNightCard() {
|
||||||
|
return isTransformed;
|
||||||
|
}
|
||||||
|
protected boolean isTransformCard() {
|
||||||
|
return cardView.canTransform() || isTransformed;
|
||||||
|
}
|
||||||
|
protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) {
|
||||||
|
int transformCircleOffset = 0;
|
||||||
|
if (isTransformCard()) {
|
||||||
|
transformCircleOffset = boxHeight - contentInset;
|
||||||
|
g.setPaint(borderPaint);
|
||||||
|
g.drawOval(borderWidth, totalContentInset, boxHeight - 1, boxHeight - 1);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.fillOval(borderWidth+1, totalContentInset+1, boxHeight-2, boxHeight-2);
|
||||||
|
g.setColor(Color.white);
|
||||||
|
if (isNightCard()) {
|
||||||
|
g.fillArc(borderWidth+3, totalContentInset+3, boxHeight-6, boxHeight-6, 90, 270);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.fillArc(borderWidth+3+3, totalContentInset+3, boxHeight-6-3, boxHeight-6, 90, 270);
|
||||||
|
} else {
|
||||||
|
g.fillOval(borderWidth+3, totalContentInset+3, boxHeight-6, boxHeight-6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transformCircleOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the text height for a given box height
|
||||||
|
protected static int getTextHeightForBoxHeight(int h) {
|
||||||
|
if (h < 15) {
|
||||||
|
return h-3;
|
||||||
|
} else {
|
||||||
|
return (int)Math.ceil(.6*h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int getPTTextHeightForLineHeight(int h) {
|
||||||
|
return h - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the color of the name / type line text
|
||||||
|
protected Color getBoxTextColor() {
|
||||||
|
if (isNightCard()) {
|
||||||
|
return Color.white;
|
||||||
|
} else {
|
||||||
|
return Color.black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the colors to base the frame on
|
||||||
|
protected ObjectColor getFrameObjectColor() {
|
||||||
|
// TODO: Take into account devoid, land frame colors, etc
|
||||||
|
return cardView.getColor().union(cardView.getFrameColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which background paint to use from a set of colors
|
||||||
|
// and the current card.
|
||||||
|
protected static Paint getBackgroundPaint(ObjectColor colors, Collection<CardType> types) {
|
||||||
|
if (types.contains(CardType.LAND)) {
|
||||||
|
return BG_TEXTURE_LAND;
|
||||||
|
} else if (types.contains(CardType.ARTIFACT)) {
|
||||||
|
return BG_TEXTURE_ARTIFACT;
|
||||||
|
} else if (colors.isMulticolored()) {
|
||||||
|
return BG_TEXTURE_GOLD;
|
||||||
|
} else if (colors.isWhite()) {
|
||||||
|
return BG_TEXTURE_WHITE;
|
||||||
|
} else if (colors.isBlue()) {
|
||||||
|
return BG_TEXTURE_BLUE;
|
||||||
|
} else if (colors.isBlack()) {
|
||||||
|
return BG_TEXTURE_BLACK;
|
||||||
|
} else if (colors.isRed()) {
|
||||||
|
return BG_TEXTURE_RED;
|
||||||
|
} else if (colors.isGreen()) {
|
||||||
|
return BG_TEXTURE_GREEN;
|
||||||
|
} else {
|
||||||
|
// Colorless
|
||||||
|
return new Color(71, 86, 101);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the box color for the given colors
|
||||||
|
protected static Color getBoxColor(ObjectColor colors, Collection<CardType> types, boolean isNightCard) {
|
||||||
|
if (colors.getColorCount() == 2 && types.contains(CardType.LAND)) {
|
||||||
|
// Special case for two color lands. Boxes should be normal land colored
|
||||||
|
// rather than multicolor. Three or greater color lands use a multi-color
|
||||||
|
// box as normal.
|
||||||
|
return BOX_LAND;
|
||||||
|
} else if (colors.isMulticolored()) {
|
||||||
|
return isNightCard ? BOX_GOLD_NIGHT : BOX_GOLD;
|
||||||
|
} else if (colors.isColorless()) {
|
||||||
|
if (types.contains(CardType.LAND)) {
|
||||||
|
return BOX_LAND;
|
||||||
|
} else {
|
||||||
|
return isNightCard ? BOX_COLORLESS_NIGHT : BOX_COLORLESS;
|
||||||
|
}
|
||||||
|
} else if (colors.isWhite()) {
|
||||||
|
return isNightCard ? BOX_WHITE_NIGHT : BOX_WHITE;
|
||||||
|
} else if (colors.isBlue()) {
|
||||||
|
return isNightCard ? BOX_BLUE_NIGHT : BOX_BLUE;
|
||||||
|
} else if (colors.isBlack()) {
|
||||||
|
return isNightCard ? BOX_BLACK_NIGHT : BOX_BLACK;
|
||||||
|
} else if (colors.isRed()) {
|
||||||
|
return isNightCard ? BOX_RED_NIGHT : BOX_RED;
|
||||||
|
} else if (colors.isGreen()) {
|
||||||
|
return isNightCard ? BOX_GREEN_NIGHT : BOX_GREEN;
|
||||||
|
} else {
|
||||||
|
return ERROR_COLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the border color for a single color
|
||||||
|
protected static Color getBorderColor(ObjectColor color) {
|
||||||
|
if (color.isWhite()) {
|
||||||
|
return BORDER_WHITE;
|
||||||
|
} else if (color.isBlue()) {
|
||||||
|
return BORDER_BLUE;
|
||||||
|
} else if (color.isBlack()) {
|
||||||
|
return BORDER_BLACK;
|
||||||
|
} else if (color.isRed()) {
|
||||||
|
return BORDER_RED;
|
||||||
|
} else if (color.isGreen()) {
|
||||||
|
return BORDER_GREEN;
|
||||||
|
} else {
|
||||||
|
return ERROR_COLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the border paint to use, based on an ObjectColors
|
||||||
|
protected static Paint getBorderPaint(ObjectColor colors, Collection<CardType> types, int width) {
|
||||||
|
if (colors.isMulticolored()) {
|
||||||
|
if (colors.getColorCount() == 2) {
|
||||||
|
List<ObjectColor> twoColors = colors.getColors();
|
||||||
|
|
||||||
|
// Two-color frames look better if we use a whiter white
|
||||||
|
// than the normal white frame color for them, as the normal
|
||||||
|
// white border color is very close to the gold background
|
||||||
|
// color.
|
||||||
|
Color color1, color2;
|
||||||
|
if (twoColors.get(0).isWhite()) {
|
||||||
|
color1 = new Color(240, 240, 240);
|
||||||
|
} else {
|
||||||
|
color1 = getBorderColor(twoColors.get(0));
|
||||||
|
}
|
||||||
|
if (twoColors.get(1).isWhite()) {
|
||||||
|
color2 = new Color(240, 240, 240);
|
||||||
|
} else {
|
||||||
|
color2 = getBorderColor(twoColors.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case for two colors, gradient paint
|
||||||
|
return new LinearGradientPaint(
|
||||||
|
0, 0, width, 0,
|
||||||
|
new float[]{0.4f, 0.6f},
|
||||||
|
new Color[]{color1, color2});
|
||||||
|
} else {
|
||||||
|
return BORDER_GOLD;
|
||||||
|
}
|
||||||
|
} else if (colors.isColorless()) {
|
||||||
|
if (types.contains(CardType.LAND)) {
|
||||||
|
return BORDER_LAND;
|
||||||
|
} else {
|
||||||
|
return BORDER_COLORLESS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getBorderColor(colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the textbox color for a single color
|
||||||
|
protected static Color getTextboxColor(ObjectColor color) {
|
||||||
|
if (color.isWhite()) {
|
||||||
|
return TEXTBOX_WHITE;
|
||||||
|
} else if (color.isBlue()) {
|
||||||
|
return TEXTBOX_BLUE;
|
||||||
|
} else if (color.isBlack()) {
|
||||||
|
return TEXTBOX_BLACK;
|
||||||
|
} else if (color.isRed()) {
|
||||||
|
return TEXTBOX_RED;
|
||||||
|
} else if (color.isGreen()) {
|
||||||
|
return TEXTBOX_GREEN;
|
||||||
|
} else {
|
||||||
|
return ERROR_COLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the border paint to use, based on an ObjectColors
|
||||||
|
protected static Paint getTextboxPaint(ObjectColor colors, Collection<CardType> types, int width) {
|
||||||
|
if (colors.isMulticolored()) {
|
||||||
|
if (colors.getColorCount() == 2) {
|
||||||
|
List<ObjectColor> twoColors = colors.getColors();
|
||||||
|
|
||||||
|
// Special case for two colors, gradient paint
|
||||||
|
return new LinearGradientPaint(
|
||||||
|
0, 0, width, 0,
|
||||||
|
new float[]{0.4f, 0.6f},
|
||||||
|
new Color[]{
|
||||||
|
getTextboxColor(twoColors.get(0)),
|
||||||
|
getTextboxColor(twoColors.get(1))
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return TEXTBOX_GOLD;
|
||||||
|
}
|
||||||
|
} else if (colors.isColorless()) {
|
||||||
|
if (types.contains(CardType.LAND)) {
|
||||||
|
return TEXTBOX_LAND;
|
||||||
|
} else {
|
||||||
|
return TEXTBOX_COLORLESS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getTextboxColor(colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*/
|
||||||
|
public class TextboxKeywordRule extends TextboxRule {
|
||||||
|
public TextboxKeywordRule(String text, List<AttributeRegion> regions) {
|
||||||
|
super(text, regions, TextboxRuleType.SIMPLE_KEYWORD);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author StravantUser
|
||||||
|
*
|
||||||
|
* Level rule associated with leveler cards
|
||||||
|
*/
|
||||||
|
public class TextboxLevelRule extends TextboxRule {
|
||||||
|
// The levels that this rule applies to
|
||||||
|
public int levelFrom;
|
||||||
|
public int levelTo;
|
||||||
|
|
||||||
|
public static int AND_HIGHER = 100;
|
||||||
|
|
||||||
|
public TextboxLevelRule(String text, List<AttributeRegion> regions, int levelFrom, int levelTo) {
|
||||||
|
super(text, regions, TextboxRuleType.LEVEL);
|
||||||
|
this.levelFrom = levelFrom;
|
||||||
|
this.levelTo = levelTo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author StravantUser
|
||||||
|
*/
|
||||||
|
public class TextboxLoyaltyRule extends TextboxRule {
|
||||||
|
public int loyaltyChange;
|
||||||
|
|
||||||
|
public static int MINUS_X = 100;
|
||||||
|
|
||||||
|
public String getChangeString() {
|
||||||
|
if (loyaltyChange == MINUS_X) {
|
||||||
|
return "-X";
|
||||||
|
} else if (loyaltyChange > 0) {
|
||||||
|
return "+" + loyaltyChange;
|
||||||
|
} else {
|
||||||
|
return "" + loyaltyChange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextboxLoyaltyRule(String text, List<AttributeRegion> regions, int loyaltyChange) {
|
||||||
|
super(text, regions, TextboxRuleType.LOYALTY);
|
||||||
|
this.loyaltyChange = loyaltyChange;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.font.GraphicAttribute;
|
||||||
|
import java.awt.font.ImageGraphicAttribute;
|
||||||
|
import java.awt.font.TextAttribute;
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*
|
||||||
|
* Class describing parsed & translated rules in the text box of a card,
|
||||||
|
* ready to be rendered.
|
||||||
|
*/
|
||||||
|
public class TextboxRule {
|
||||||
|
// An attributed region in the text, which can be applied to an
|
||||||
|
// attributed string.
|
||||||
|
public interface AttributeRegion {
|
||||||
|
public void applyToAttributedString(AttributedString str, Font normal, Font italic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A region of italics, or bold text in a
|
||||||
|
public static class ItalicRegion implements AttributeRegion {
|
||||||
|
ItalicRegion(int start, int end) {
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
private final int start;
|
||||||
|
private final int end;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
|
||||||
|
if (end > start+1) {
|
||||||
|
str.addAttribute(TextAttribute.FONT, italic, start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A special symbol embedded at some point in a string
|
||||||
|
public static class EmbeddedSymbol implements AttributeRegion {
|
||||||
|
EmbeddedSymbol(String symbol, int location) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
private final String symbol;
|
||||||
|
private final int location;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
|
||||||
|
Image symbolImage = ManaSymbols.getSizedManaSymbol(symbol, normal.getSize());
|
||||||
|
if (symbolImage != null) {
|
||||||
|
ImageGraphicAttribute imgAttr =
|
||||||
|
new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT);
|
||||||
|
str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String text;
|
||||||
|
public TextboxRuleType type;
|
||||||
|
|
||||||
|
private List<AttributeRegion> regions;
|
||||||
|
|
||||||
|
protected TextboxRule(String text, List<AttributeRegion> regions, TextboxRuleType type) {
|
||||||
|
this.text = text;
|
||||||
|
this.type = type;
|
||||||
|
this.regions = regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextboxRule(String text, List<AttributeRegion> regions) {
|
||||||
|
this(text, regions, TextboxRuleType.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributedString generateAttributedString(Font normal, Font italic) {
|
||||||
|
// Build the final attributed text using the regions
|
||||||
|
// Do it in reverse order for proper handling of regions where
|
||||||
|
// there are multiple attributes stacked (EG: bold + italic)
|
||||||
|
AttributedString attributedRule = new AttributedString(text);
|
||||||
|
if (text.length() != 0) {
|
||||||
|
attributedRule.addAttribute(TextAttribute.FONT, normal);
|
||||||
|
for (int i = regions.size()-1; i >= 0; --i) {
|
||||||
|
regions.get(i).applyToAttributedString(attributedRule, normal, italic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attributedRule;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.font.GraphicAttribute;
|
||||||
|
import java.awt.font.ImageGraphicAttribute;
|
||||||
|
import java.awt.font.TextAttribute;
|
||||||
|
import java.text.AttributedString;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import mage.view.CardView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author StravantUser
|
||||||
|
*/
|
||||||
|
public class TextboxRuleParser {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||||
|
|
||||||
|
private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)");
|
||||||
|
private static final Pattern LoyaltyAbilityPattern = Pattern.compile("^(\\+|\\-)(\\d+|X): ");
|
||||||
|
private static final Pattern SimpleKeywordPattern = Pattern.compile("^(\\w+( \\w+)?)\\s*(\\([^\\)]*\\))?\\s*$");
|
||||||
|
|
||||||
|
// Parse a given rule (given as a string) into a TextboxRule, replacing
|
||||||
|
// symbol annotations, italics, etc, parsing out information such as
|
||||||
|
// if the ability is a loyalty ability, and returning an TextboxRule
|
||||||
|
// representing that information, which can be used to render the rule in
|
||||||
|
// the textbox of a card.
|
||||||
|
public static TextboxRule parse(CardView source, String rule) {
|
||||||
|
// List of regions to apply
|
||||||
|
ArrayList<TextboxRule.AttributeRegion> regions = new ArrayList<>();
|
||||||
|
|
||||||
|
// Leveler / loyalty
|
||||||
|
boolean isLeveler = false;
|
||||||
|
int levelFrom = 0;
|
||||||
|
int levelTo = 0;
|
||||||
|
|
||||||
|
boolean isLoyalty = false;
|
||||||
|
int loyaltyChange = 0;
|
||||||
|
|
||||||
|
// Parse the attributedString contents
|
||||||
|
int index = 0;
|
||||||
|
int outputIndex = 0;
|
||||||
|
|
||||||
|
// Is it a simple keyword ability?
|
||||||
|
{
|
||||||
|
Matcher simpleKeywordMatch = SimpleKeywordPattern.matcher(rule);
|
||||||
|
if (simpleKeywordMatch.find()) {
|
||||||
|
return new TextboxKeywordRule(simpleKeywordMatch.group(1), regions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's a loyalty ability. Must be right at the start of the rule
|
||||||
|
{
|
||||||
|
Matcher loyaltyMatch = LoyaltyAbilityPattern.matcher(rule);
|
||||||
|
if (loyaltyMatch.find()) {
|
||||||
|
// Get the loyalty change
|
||||||
|
if (loyaltyMatch.group(2).equals("X")) {
|
||||||
|
loyaltyChange = TextboxLoyaltyRule.MINUS_X;
|
||||||
|
} else {
|
||||||
|
loyaltyChange = Integer.parseInt(loyaltyMatch.group(2));
|
||||||
|
if (loyaltyMatch.group(1).equals("-")) {
|
||||||
|
loyaltyChange = -loyaltyChange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isLoyalty = true;
|
||||||
|
|
||||||
|
// Go past the match
|
||||||
|
index = loyaltyMatch.group().length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Deque<Integer> openingStack = new ArrayDeque<>();
|
||||||
|
StringBuilder build = new StringBuilder();
|
||||||
|
while (index < rule.length()) {
|
||||||
|
int initialIndex = index;
|
||||||
|
char ch = rule.charAt(index);
|
||||||
|
if (ch == '{') {
|
||||||
|
// Handling for `{this}`
|
||||||
|
int closeIndex = rule.indexOf('}', index);
|
||||||
|
if (closeIndex == -1) {
|
||||||
|
// Malformed input, nothing to do
|
||||||
|
++index;
|
||||||
|
++outputIndex;
|
||||||
|
build.append(ch);
|
||||||
|
} else {
|
||||||
|
String contents = rule.substring(index+1, closeIndex);
|
||||||
|
if (contents.equals("this") || contents.equals("source")) {
|
||||||
|
// Replace {this} with the card's name
|
||||||
|
String cardName = source.getName();
|
||||||
|
build.append(cardName);
|
||||||
|
index += contents.length() + 2;
|
||||||
|
outputIndex += cardName.length();
|
||||||
|
} else {
|
||||||
|
Image symbol = ManaSymbols.getSizedManaSymbol(contents, 10);
|
||||||
|
if (symbol != null) {
|
||||||
|
// Mana or other inline symbol
|
||||||
|
build.append('#');
|
||||||
|
regions.add(new TextboxRule.EmbeddedSymbol(contents, outputIndex));
|
||||||
|
++outputIndex;
|
||||||
|
index = closeIndex+1;
|
||||||
|
} else {
|
||||||
|
// Bad entry
|
||||||
|
build.append('{');
|
||||||
|
build.append(contents);
|
||||||
|
build.append('}');
|
||||||
|
index = closeIndex+1;
|
||||||
|
outputIndex += (contents.length() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (ch == '&') {
|
||||||
|
// Handling for `—`
|
||||||
|
if (rule.startsWith("—", index)) {
|
||||||
|
build.append('—');
|
||||||
|
index += 7;
|
||||||
|
++outputIndex;
|
||||||
|
} else if (rule.startsWith("&bull", index)) {
|
||||||
|
build.append('•');
|
||||||
|
index += 5;
|
||||||
|
++outputIndex;
|
||||||
|
} else {
|
||||||
|
LOGGER.error("Bad &...; sequence `" + rule.substring(index+1, index+10) + "` in rule.");
|
||||||
|
build.append('&');
|
||||||
|
++index;
|
||||||
|
++outputIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if (ch == '<') {
|
||||||
|
// Handling for `<i>` and `<br/>`
|
||||||
|
int closeIndex = rule.indexOf('>', index);
|
||||||
|
if (closeIndex != -1) {
|
||||||
|
// Is a tag
|
||||||
|
String tag = rule.substring(index+1, closeIndex);
|
||||||
|
if (tag.charAt(tag.length()-1) == '/') {
|
||||||
|
// Pure closing tag (like <br/>)
|
||||||
|
if (tag.equals("br/")) {
|
||||||
|
build.append('\n');
|
||||||
|
++outputIndex;
|
||||||
|
} else {
|
||||||
|
// Unknown
|
||||||
|
build.append('<').append(tag).append('>');
|
||||||
|
outputIndex += (tag.length() + 2);
|
||||||
|
}
|
||||||
|
} else if (tag.charAt(0) == '/') {
|
||||||
|
// Opening index for the tag
|
||||||
|
int openingIndex;
|
||||||
|
if (openingStack.isEmpty()) {
|
||||||
|
// Malformed input, just make an empty interval
|
||||||
|
openingIndex = outputIndex;
|
||||||
|
} else {
|
||||||
|
openingIndex = openingStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// What tag is it?
|
||||||
|
if (tag.equals("/i")) {
|
||||||
|
// Italics
|
||||||
|
regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex));
|
||||||
|
} else if (tag.equals("/b")) {
|
||||||
|
// Bold, see if it's a level ability
|
||||||
|
String content = build.substring(openingIndex);
|
||||||
|
|
||||||
|
Matcher levelMatch = LevelAbilityPattern.matcher(content);
|
||||||
|
if (levelMatch.find()) {
|
||||||
|
try {
|
||||||
|
levelFrom = Integer.parseInt(levelMatch.group(1));
|
||||||
|
if (!levelMatch.group(2).equals("")) {
|
||||||
|
levelTo = Integer.parseInt(levelMatch.group(2));
|
||||||
|
}
|
||||||
|
if (!levelMatch.group(3).equals("")) {
|
||||||
|
levelTo = TextboxLevelRule.AND_HIGHER;
|
||||||
|
}
|
||||||
|
isLeveler = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Bad leveler levels in rule `" + rule + "`.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unknown
|
||||||
|
build.append('<').append(tag).append('>');
|
||||||
|
outputIndex += (tag.length() + 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Is it a <br> tag special case? [Why can't it have a closing `/`... =( ]
|
||||||
|
if (tag.equals("br")) {
|
||||||
|
build.append('\n');
|
||||||
|
++outputIndex;
|
||||||
|
} else {
|
||||||
|
// Opening tag
|
||||||
|
openingStack.push(outputIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip characters
|
||||||
|
index = closeIndex+1;
|
||||||
|
} else {
|
||||||
|
// Malformed tag
|
||||||
|
build.append('<');
|
||||||
|
++outputIndex;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Normal character
|
||||||
|
++index;
|
||||||
|
++outputIndex;
|
||||||
|
build.append(ch);
|
||||||
|
}
|
||||||
|
if (outputIndex != build.length()) {
|
||||||
|
// Somehow our parsing code output symbols but didn't update the output index correspondingly
|
||||||
|
LOGGER.error("The human is dead; mismatch! Failed on rule: `" + rule + "` due to not updating outputIndex properly.");
|
||||||
|
|
||||||
|
// Bail out
|
||||||
|
build = new StringBuilder(rule);
|
||||||
|
regions.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (index == initialIndex) {
|
||||||
|
// Somehow our parsing failed to consume the
|
||||||
|
LOGGER.error("Failed on rule `" + rule + "` due to not consuming a character.");
|
||||||
|
|
||||||
|
// Bail out
|
||||||
|
build = new StringBuilder(rule);
|
||||||
|
regions.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build and return the rule
|
||||||
|
rule = build.toString();
|
||||||
|
if (isLoyalty) {
|
||||||
|
return new TextboxLoyaltyRule(rule, regions, loyaltyChange);
|
||||||
|
} else if (isLeveler) {
|
||||||
|
return new TextboxLevelRule(rule, regions, levelFrom, levelTo);
|
||||||
|
} else {
|
||||||
|
return new TextboxRule(rule, regions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.mage.card.arcane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*/
|
||||||
|
public enum TextboxRuleType {
|
||||||
|
/* Normal abilities, just rendered as lines of text with embedded symbols
|
||||||
|
* replaced to the relevant images. */
|
||||||
|
NORMAL,
|
||||||
|
|
||||||
|
/* Keyword ability. To be displayed in the comma separated list at the
|
||||||
|
* very top of the rules box */
|
||||||
|
SIMPLE_KEYWORD,
|
||||||
|
|
||||||
|
/* Loyalty abilities on planeswalkers */
|
||||||
|
LOYALTY,
|
||||||
|
|
||||||
|
/* Levelup creature - static ability at a given level */
|
||||||
|
LEVEL
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import javax.swing.JDialog;
|
||||||
import javax.swing.JLayeredPane;
|
import javax.swing.JLayeredPane;
|
||||||
import mage.cards.MagePermanent;
|
import mage.cards.MagePermanent;
|
||||||
import mage.cards.action.ActionCallback;
|
import mage.cards.action.ActionCallback;
|
||||||
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.client.util.GUISizeHelper;
|
import mage.client.util.GUISizeHelper;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.interfaces.plugin.CardPlugin;
|
import mage.interfaces.plugin.CardPlugin;
|
||||||
|
@ -31,6 +32,7 @@ import net.xeoh.plugins.base.annotations.meta.Author;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.mage.card.arcane.Animation;
|
import org.mage.card.arcane.Animation;
|
||||||
import org.mage.card.arcane.CardPanel;
|
import org.mage.card.arcane.CardPanel;
|
||||||
|
import org.mage.card.arcane.CardPanelComponentImpl;
|
||||||
import org.mage.card.arcane.ManaSymbols;
|
import org.mage.card.arcane.ManaSymbols;
|
||||||
import org.mage.plugins.card.dl.DownloadGui;
|
import org.mage.plugins.card.dl.DownloadGui;
|
||||||
import org.mage.plugins.card.dl.DownloadJob;
|
import org.mage.plugins.card.dl.DownloadJob;
|
||||||
|
@ -41,6 +43,7 @@ import org.mage.plugins.card.dl.sources.GathererSets;
|
||||||
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
||||||
import org.mage.plugins.card.images.ImageCache;
|
import org.mage.plugins.card.images.ImageCache;
|
||||||
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
||||||
|
import org.mage.card.arcane.CardPanelRenderImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CardPlugin} implementation.
|
* {@link CardPlugin} implementation.
|
||||||
|
@ -106,9 +109,22 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
|
cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary card rendering shim. Split card rendering isn't implemented yet, so
|
||||||
|
* use old component based rendering for the split cards.
|
||||||
|
*/
|
||||||
|
private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension) {
|
||||||
|
String fallback = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false");
|
||||||
|
if (view.isSplitCard() || fallback.equals("true")) {
|
||||||
|
return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
|
||||||
|
} else {
|
||||||
|
return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
||||||
CardPanel cardPanel = new CardPanel(permanent, gameId, loadImage, callback, false, dimension);
|
CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension);
|
||||||
boolean implemented = !permanent.getRarity().equals(Rarity.NA);
|
boolean implemented = !permanent.getRarity().equals(Rarity.NA);
|
||||||
cardPanel.setShowCastingCost(implemented);
|
cardPanel.setShowCastingCost(implemented);
|
||||||
return cardPanel;
|
return cardPanel;
|
||||||
|
@ -116,7 +132,7 @@ public class CardPluginImpl implements CardPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
|
||||||
CardPanel cardPanel = new CardPanel(cardView, gameId, loadImage, callback, false, dimension);
|
CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension);
|
||||||
boolean implemented = cardView.getRarity() != null && !cardView.getRarity().equals(Rarity.NA);
|
boolean implemented = cardView.getRarity() != null && !cardView.getRarity().equals(Rarity.NA);
|
||||||
cardPanel.setShowCastingCost(implemented);
|
cardPanel.setShowCastingCost(implemented);
|
||||||
return cardPanel;
|
return cardPanel;
|
||||||
|
|
After Width: | Height: | Size: 411 KiB |
After Width: | Height: | Size: 450 KiB |
After Width: | Height: | Size: 453 KiB |
After Width: | Height: | Size: 506 KiB |
After Width: | Height: | Size: 517 KiB |
After Width: | Height: | Size: 457 KiB |
After Width: | Height: | Size: 534 KiB |
After Width: | Height: | Size: 144 KiB |
28
Mage.Common/src/mage/cards/CardBorder.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
package mage.cards;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author stravant@gmail.com
|
||||||
|
*
|
||||||
|
* Enum listing the possible card faces for a card
|
||||||
|
*
|
||||||
|
* Because of Time Spiral block's shifted cards it is
|
||||||
|
* not sufficient to just look at a card's edition to
|
||||||
|
* determine what the card face should be.
|
||||||
|
*/
|
||||||
|
public enum CardBorder {
|
||||||
|
/* Old border card frames. ALPHA -> 8th ED */
|
||||||
|
OLD,
|
||||||
|
|
||||||
|
/* Future Sight frames. FUT futureshifted */
|
||||||
|
FUT,
|
||||||
|
|
||||||
|
/* Planar Chaos frames. PLC planeshifted */
|
||||||
|
PLC,
|
||||||
|
|
||||||
|
/* Modern card frames. 8th ED -> M15 */
|
||||||
|
MOD,
|
||||||
|
|
||||||
|
/* New border cards, M15 -> current */
|
||||||
|
M15
|
||||||
|
}
|
|
@ -32,8 +32,10 @@ import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
|
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
|
||||||
import mage.abilities.costs.mana.ManaCosts;
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.SplitCard;
|
import mage.cards.SplitCard;
|
||||||
|
@ -68,10 +70,12 @@ public class CardView extends SimpleCardView {
|
||||||
protected String power;
|
protected String power;
|
||||||
protected String toughness;
|
protected String toughness;
|
||||||
protected String loyalty;
|
protected String loyalty;
|
||||||
|
protected String startingLoyalty;
|
||||||
protected List<CardType> cardTypes;
|
protected List<CardType> cardTypes;
|
||||||
protected List<String> subTypes;
|
protected List<String> subTypes;
|
||||||
protected List<String> superTypes;
|
protected List<String> superTypes;
|
||||||
protected ObjectColor color;
|
protected ObjectColor color;
|
||||||
|
protected ObjectColor frameColor;
|
||||||
protected List<String> manaCost;
|
protected List<String> manaCost;
|
||||||
protected int convertedManaCost;
|
protected int convertedManaCost;
|
||||||
protected Rarity rarity;
|
protected Rarity rarity;
|
||||||
|
@ -329,6 +333,12 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Frame color
|
||||||
|
this.frameColor = card.getFrameColor(game);
|
||||||
|
|
||||||
|
// Get starting loyalty
|
||||||
|
this.startingLoyalty = "" + card.getStartingLoyalty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView(MageObject object) {
|
public CardView(MageObject object) {
|
||||||
|
@ -373,6 +383,10 @@ public class CardView extends SimpleCardView {
|
||||||
this.expansionSetCode = stackAbility.getExpansionSetCode();
|
this.expansionSetCode = stackAbility.getExpansionSetCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Frame color
|
||||||
|
this.frameColor = object.getFrameColor(null);
|
||||||
|
// Starting loyalty. Must be extracted from an ability
|
||||||
|
this.startingLoyalty = "" + object.getStartingLoyalty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CardView() {
|
protected CardView() {
|
||||||
|
@ -407,10 +421,12 @@ public class CardView extends SimpleCardView {
|
||||||
this.power = "";
|
this.power = "";
|
||||||
this.toughness = "";
|
this.toughness = "";
|
||||||
this.loyalty = "";
|
this.loyalty = "";
|
||||||
|
this.startingLoyalty = "";
|
||||||
this.cardTypes = new ArrayList<>();
|
this.cardTypes = new ArrayList<>();
|
||||||
this.subTypes = new ArrayList<>();
|
this.subTypes = new ArrayList<>();
|
||||||
this.superTypes = new ArrayList<>();
|
this.superTypes = new ArrayList<>();
|
||||||
this.color = new ObjectColor();
|
this.color = new ObjectColor();
|
||||||
|
this.frameColor = new ObjectColor();
|
||||||
this.manaCost = new ArrayList<>();
|
this.manaCost = new ArrayList<>();
|
||||||
this.convertedManaCost = 0;
|
this.convertedManaCost = 0;
|
||||||
|
|
||||||
|
@ -451,10 +467,12 @@ public class CardView extends SimpleCardView {
|
||||||
this.power = token.getPower().toString();
|
this.power = token.getPower().toString();
|
||||||
this.toughness = token.getToughness().toString();
|
this.toughness = token.getToughness().toString();
|
||||||
this.loyalty = "";
|
this.loyalty = "";
|
||||||
|
this.startingLoyalty = "";
|
||||||
this.cardTypes = token.getCardType();
|
this.cardTypes = token.getCardType();
|
||||||
this.subTypes = token.getSubtype();
|
this.subTypes = token.getSubtype();
|
||||||
this.superTypes = token.getSupertype();
|
this.superTypes = token.getSupertype();
|
||||||
this.color = token.getColor(null);
|
this.color = token.getColor(null);
|
||||||
|
this.frameColor = token.getFrameColor(null);
|
||||||
this.manaCost = token.getManaCost().getSymbols();
|
this.manaCost = token.getManaCost().getSymbols();
|
||||||
this.rarity = Rarity.NA;
|
this.rarity = Rarity.NA;
|
||||||
this.type = token.getTokenType();
|
this.type = token.getTokenType();
|
||||||
|
@ -518,6 +536,10 @@ public class CardView extends SimpleCardView {
|
||||||
return loyalty;
|
return loyalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getStartingLoyalty() {
|
||||||
|
return startingLoyalty;
|
||||||
|
}
|
||||||
|
|
||||||
public List<CardType> getCardTypes() {
|
public List<CardType> getCardTypes() {
|
||||||
return cardTypes;
|
return cardTypes;
|
||||||
}
|
}
|
||||||
|
@ -534,6 +556,10 @@ public class CardView extends SimpleCardView {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObjectColor getFrameColor() {
|
||||||
|
return frameColor;
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getManaCost() {
|
public List<String> getManaCost() {
|
||||||
return manaCost;
|
return manaCost;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
package mage.sets.onslaught;
|
package mage.sets.onslaught;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -42,6 +43,7 @@ public class BloodstainedMire extends CardImpl {
|
||||||
public BloodstainedMire(UUID ownerId) {
|
public BloodstainedMire(UUID ownerId) {
|
||||||
super(ownerId, 313, "Bloodstained Mire", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
super(ownerId, 313, "Bloodstained Mire", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||||
this.expansionSetCode = "ONS";
|
this.expansionSetCode = "ONS";
|
||||||
|
this.frameColor = new ObjectColor("RB");
|
||||||
|
|
||||||
// {tap}, Pay 1 life, Sacrifice Bloodstained Mire: Search your library for a Swamp or Mountain card and put it onto the battlefield. Then shuffle your library.
|
// {tap}, Pay 1 life, Sacrifice Bloodstained Mire: Search your library for a Swamp or Mountain card and put it onto the battlefield. Then shuffle your library.
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[]{"Swamp", "Mountain"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[]{"Swamp", "Mountain"}));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
package mage.sets.onslaught;
|
package mage.sets.onslaught;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -42,6 +43,7 @@ public class FloodedStrand extends CardImpl {
|
||||||
public FloodedStrand(UUID ownerId) {
|
public FloodedStrand(UUID ownerId) {
|
||||||
super(ownerId, 316, "Flooded Strand", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
super(ownerId, 316, "Flooded Strand", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||||
this.expansionSetCode = "ONS";
|
this.expansionSetCode = "ONS";
|
||||||
|
this.frameColor = new ObjectColor("UW");
|
||||||
|
|
||||||
// {tap}, Pay 1 life, Sacrifice Flooded Strand: Search your library for a Plains or Island card and put it onto the battlefield. Then shuffle your library.
|
// {tap}, Pay 1 life, Sacrifice Flooded Strand: Search your library for a Plains or Island card and put it onto the battlefield. Then shuffle your library.
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[]{"Plains", "Island"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[]{"Plains", "Island"}));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
package mage.sets.onslaught;
|
package mage.sets.onslaught;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -42,6 +43,7 @@ public class PollutedDelta extends CardImpl {
|
||||||
public PollutedDelta(UUID ownerId) {
|
public PollutedDelta(UUID ownerId) {
|
||||||
super(ownerId, 321, "Polluted Delta", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
super(ownerId, 321, "Polluted Delta", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||||
this.expansionSetCode = "ONS";
|
this.expansionSetCode = "ONS";
|
||||||
|
this.frameColor = new ObjectColor("UB");
|
||||||
|
|
||||||
// {tap}, Pay 1 life, Sacrifice Polluted Delta: Search your library for an Island or Swamp card and put it onto the battlefield. Then shuffle your library.
|
// {tap}, Pay 1 life, Sacrifice Polluted Delta: Search your library for an Island or Swamp card and put it onto the battlefield. Then shuffle your library.
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[]{"Island", "Swamp"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[]{"Island", "Swamp"}));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
package mage.sets.onslaught;
|
package mage.sets.onslaught;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -42,6 +43,7 @@ public class WindsweptHeath extends CardImpl {
|
||||||
public WindsweptHeath(UUID ownerId) {
|
public WindsweptHeath(UUID ownerId) {
|
||||||
super(ownerId, 328, "Windswept Heath", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
super(ownerId, 328, "Windswept Heath", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||||
this.expansionSetCode = "ONS";
|
this.expansionSetCode = "ONS";
|
||||||
|
this.frameColor = new ObjectColor("GW");
|
||||||
|
|
||||||
// {tap}, Pay 1 life, Sacrifice Windswept Heath: Search your library for a Forest or Plains card and put it onto the battlefield. Then shuffle your library.
|
// {tap}, Pay 1 life, Sacrifice Windswept Heath: Search your library for a Forest or Plains card and put it onto the battlefield. Then shuffle your library.
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[]{"Forest", "Plains"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[]{"Forest", "Plains"}));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
package mage.sets.onslaught;
|
package mage.sets.onslaught;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -42,6 +43,7 @@ public class WoodedFoothills extends CardImpl {
|
||||||
public WoodedFoothills(UUID ownerId) {
|
public WoodedFoothills(UUID ownerId) {
|
||||||
super(ownerId, 330, "Wooded Foothills", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
super(ownerId, 330, "Wooded Foothills", Rarity.RARE, new CardType[]{CardType.LAND}, "");
|
||||||
this.expansionSetCode = "ONS";
|
this.expansionSetCode = "ONS";
|
||||||
|
this.frameColor = new ObjectColor("RG");
|
||||||
|
|
||||||
// {tap}, Pay 1 life, Sacrifice Wooded Foothills: Search your library for a Mountain or Forest card and put it onto the battlefield. Then shuffle your library.
|
// {tap}, Pay 1 life, Sacrifice Wooded Foothills: Search your library for a Mountain or Forest card and put it onto the battlefield. Then shuffle your library.
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[]{"Mountain", "Forest"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[]{"Mountain", "Forest"}));
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.sets.zendikar;
|
package mage.sets.zendikar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -43,6 +44,7 @@ public class AridMesa extends CardImpl {
|
||||||
public AridMesa(UUID ownerId) {
|
public AridMesa(UUID ownerId) {
|
||||||
super(ownerId, 211, "Arid Mesa", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
super(ownerId, 211, "Arid Mesa", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
|
this.frameColor = new ObjectColor("WR");
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[] {"Mountain", "Plains"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[] {"Mountain", "Plains"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.sets.zendikar;
|
package mage.sets.zendikar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -43,6 +44,7 @@ public class MarshFlats extends CardImpl {
|
||||||
public MarshFlats(UUID ownerId) {
|
public MarshFlats(UUID ownerId) {
|
||||||
super(ownerId, 219, "Marsh Flats", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
super(ownerId, 219, "Marsh Flats", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
|
this.frameColor = new ObjectColor("WB");
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[] {"Swamp", "Plains"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[] {"Swamp", "Plains"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.sets.zendikar;
|
package mage.sets.zendikar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -43,6 +44,7 @@ public class MistyRainforest extends CardImpl {
|
||||||
public MistyRainforest(UUID ownerId) {
|
public MistyRainforest(UUID ownerId) {
|
||||||
super(ownerId, 220, "Misty Rainforest", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
super(ownerId, 220, "Misty Rainforest", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
|
this.frameColor = new ObjectColor("UG");
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Island"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Island"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.sets.zendikar;
|
package mage.sets.zendikar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -43,6 +44,7 @@ public class ScaldingTarn extends CardImpl {
|
||||||
public ScaldingTarn(UUID ownerId) {
|
public ScaldingTarn(UUID ownerId) {
|
||||||
super(ownerId, 223, "Scalding Tarn", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
super(ownerId, 223, "Scalding Tarn", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
|
this.frameColor = new ObjectColor("UR");
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[] {"Island", "Mountain"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[] {"Island", "Mountain"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.sets.zendikar;
|
package mage.sets.zendikar;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.abilities.common.FetchLandActivatedAbility;
|
import mage.abilities.common.FetchLandActivatedAbility;
|
||||||
|
@ -43,6 +44,7 @@ public class VerdantCatacombs extends CardImpl {
|
||||||
public VerdantCatacombs(UUID ownerId) {
|
public VerdantCatacombs(UUID ownerId) {
|
||||||
super(ownerId, 229, "Verdant Catacombs", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
super(ownerId, 229, "Verdant Catacombs", Rarity.RARE, new CardType[]{CardType.LAND}, null);
|
||||||
this.expansionSetCode = "ZEN";
|
this.expansionSetCode = "ZEN";
|
||||||
|
this.frameColor = new ObjectColor("BG");
|
||||||
this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Swamp"}));
|
this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Swamp"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2127
Mage.Tests/replay_pid4548.log
Normal file
|
@ -36,6 +36,8 @@ public interface MageObject extends MageItem, Serializable {
|
||||||
|
|
||||||
ObjectColor getColor(Game game);
|
ObjectColor getColor(Game game);
|
||||||
|
|
||||||
|
ObjectColor getFrameColor(Game game);
|
||||||
|
|
||||||
ManaCosts<ManaCost> getManaCost();
|
ManaCosts<ManaCost> getManaCost();
|
||||||
|
|
||||||
int getConvertedManaCost();
|
int getConvertedManaCost();
|
||||||
|
@ -44,6 +46,10 @@ public interface MageObject extends MageItem, Serializable {
|
||||||
|
|
||||||
MageInt getToughness();
|
MageInt getToughness();
|
||||||
|
|
||||||
|
int getStartingLoyalty();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void adjustCosts(Ability ability, Game game);
|
void adjustCosts(Ability ability, Game game);
|
||||||
|
|
||||||
void adjustTargets(Ability ability, Game game);
|
void adjustTargets(Ability ability, Game game);
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.util.UUID;
|
||||||
import mage.abilities.Abilities;
|
import mage.abilities.Abilities;
|
||||||
import mage.abilities.AbilitiesImpl;
|
import mage.abilities.AbilitiesImpl;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCosts;
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
@ -49,6 +50,7 @@ public abstract class MageObjectImpl implements MageObject {
|
||||||
protected String name;
|
protected String name;
|
||||||
protected ManaCosts<ManaCost> manaCost;
|
protected ManaCosts<ManaCost> manaCost;
|
||||||
protected ObjectColor color;
|
protected ObjectColor color;
|
||||||
|
protected ObjectColor frameColor;
|
||||||
protected List<CardType> cardType = new ArrayList<>();
|
protected List<CardType> cardType = new ArrayList<>();
|
||||||
protected List<String> subtype = new ArrayList<>();
|
protected List<String> subtype = new ArrayList<>();
|
||||||
protected List<String> supertype = new ArrayList<>();
|
protected List<String> supertype = new ArrayList<>();
|
||||||
|
@ -67,6 +69,7 @@ public abstract class MageObjectImpl implements MageObject {
|
||||||
power = new MageInt(0);
|
power = new MageInt(0);
|
||||||
toughness = new MageInt(0);
|
toughness = new MageInt(0);
|
||||||
color = new ObjectColor();
|
color = new ObjectColor();
|
||||||
|
frameColor = new ObjectColor();
|
||||||
manaCost = new ManaCostsImpl<>("");
|
manaCost = new ManaCostsImpl<>("");
|
||||||
abilities = new AbilitiesImpl<>();
|
abilities = new AbilitiesImpl<>();
|
||||||
}
|
}
|
||||||
|
@ -77,6 +80,7 @@ public abstract class MageObjectImpl implements MageObject {
|
||||||
manaCost = object.manaCost.copy();
|
manaCost = object.manaCost.copy();
|
||||||
text = object.text;
|
text = object.text;
|
||||||
color = object.color.copy();
|
color = object.color.copy();
|
||||||
|
frameColor = object.frameColor.copy();
|
||||||
power = object.power.copy();
|
power = object.power.copy();
|
||||||
toughness = object.toughness.copy();
|
toughness = object.toughness.copy();
|
||||||
abilities = object.abilities.copy();
|
abilities = object.abilities.copy();
|
||||||
|
@ -155,11 +159,26 @@ public abstract class MageObjectImpl implements MageObject {
|
||||||
return toughness;
|
return toughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
for (Ability ab: getAbilities()) {
|
||||||
|
if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) {
|
||||||
|
return ((PlanswalkerEntersWithLoyalityCountersAbility)ab).getStartingLoyalty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectColor getColor(Game game) {
|
public ObjectColor getColor(Game game) {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectColor getFrameColor(Game game) {
|
||||||
|
return frameColor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManaCosts<ManaCost> getManaCost() {
|
public ManaCosts<ManaCost> getManaCost() {
|
||||||
return manaCost;
|
return manaCost;
|
||||||
|
|
|
@ -82,6 +82,22 @@ public class ObjectColor implements Serializable, Copyable<ObjectColor>, Compara
|
||||||
green = color.green;
|
green = color.green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new color which contains all of the colors of this ObjectColor
|
||||||
|
* in addition to all of the colors of the other ObjectColor.
|
||||||
|
* @param other The other ObjectColor to union with
|
||||||
|
* @return A new color which is the union of this and other
|
||||||
|
*/
|
||||||
|
public ObjectColor union(ObjectColor other) {
|
||||||
|
ObjectColor newColor = new ObjectColor();
|
||||||
|
newColor.white = white | other.white;
|
||||||
|
newColor.blue = blue | other.blue;
|
||||||
|
newColor.black = black | other.black;
|
||||||
|
newColor.red = red | other.red;
|
||||||
|
newColor.green = green | other.green;
|
||||||
|
return newColor;
|
||||||
|
}
|
||||||
|
|
||||||
public int getColorCount() {
|
public int getColorCount() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (white) {
|
if (white) {
|
||||||
|
|
|
@ -14,13 +14,21 @@ import mage.counters.CounterType;
|
||||||
*/
|
*/
|
||||||
public class PlanswalkerEntersWithLoyalityCountersAbility extends EntersBattlefieldAbility {
|
public class PlanswalkerEntersWithLoyalityCountersAbility extends EntersBattlefieldAbility {
|
||||||
|
|
||||||
public PlanswalkerEntersWithLoyalityCountersAbility(int loyality) {
|
private final int startingLoyalty;
|
||||||
super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyality)));
|
|
||||||
|
public PlanswalkerEntersWithLoyalityCountersAbility(int loyalty) {
|
||||||
|
super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyalty)));
|
||||||
|
startingLoyalty = loyalty;
|
||||||
setRuleVisible(false);
|
setRuleVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlanswalkerEntersWithLoyalityCountersAbility(final PlanswalkerEntersWithLoyalityCountersAbility ability) {
|
public PlanswalkerEntersWithLoyalityCountersAbility(final PlanswalkerEntersWithLoyalityCountersAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
|
startingLoyalty = ability.startingLoyalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return startingLoyalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.cards.basiclands;
|
package mage.cards.basiclands;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.mana.GreenManaAbility;
|
import mage.abilities.mana.GreenManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +44,7 @@ public abstract class Forest extends BasicLand {
|
||||||
|
|
||||||
public Forest(UUID ownerId, String cardNumber) {
|
public Forest(UUID ownerId, String cardNumber) {
|
||||||
super(ownerId, cardNumber, "Forest", new GreenManaAbility());
|
super(ownerId, cardNumber, "Forest", new GreenManaAbility());
|
||||||
|
this.frameColor = ObjectColor.GREEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Forest(final Forest land) {
|
public Forest(final Forest land) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.cards.basiclands;
|
package mage.cards.basiclands;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.mana.BlueManaAbility;
|
import mage.abilities.mana.BlueManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +44,7 @@ public abstract class Island extends BasicLand {
|
||||||
|
|
||||||
public Island(UUID ownerId, String cardNumber) {
|
public Island(UUID ownerId, String cardNumber) {
|
||||||
super(ownerId, cardNumber, "Island", new BlueManaAbility());
|
super(ownerId, cardNumber, "Island", new BlueManaAbility());
|
||||||
|
this.frameColor = ObjectColor.BLUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Island(Island land) {
|
public Island(Island land) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.cards.basiclands;
|
package mage.cards.basiclands;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.mana.RedManaAbility;
|
import mage.abilities.mana.RedManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +44,7 @@ public abstract class Mountain extends BasicLand {
|
||||||
|
|
||||||
public Mountain(UUID ownerId, String cardNumber) {
|
public Mountain(UUID ownerId, String cardNumber) {
|
||||||
super(ownerId, cardNumber, "Mountain", new RedManaAbility());
|
super(ownerId, cardNumber, "Mountain", new RedManaAbility());
|
||||||
|
this.frameColor = ObjectColor.RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mountain(Mountain land) {
|
public Mountain(Mountain land) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.cards.basiclands;
|
package mage.cards.basiclands;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.mana.WhiteManaAbility;
|
import mage.abilities.mana.WhiteManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +44,7 @@ public abstract class Plains extends BasicLand {
|
||||||
|
|
||||||
public Plains(UUID ownerId, String cardNumber) {
|
public Plains(UUID ownerId, String cardNumber) {
|
||||||
super(ownerId, cardNumber, "Plains", new WhiteManaAbility());
|
super(ownerId, cardNumber, "Plains", new WhiteManaAbility());
|
||||||
|
this.frameColor = ObjectColor.WHITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plains(Plains land) {
|
public Plains(Plains land) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
package mage.cards.basiclands;
|
package mage.cards.basiclands;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import mage.ObjectColor;
|
||||||
import mage.abilities.mana.BlackManaAbility;
|
import mage.abilities.mana.BlackManaAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +44,7 @@ public abstract class Swamp extends BasicLand {
|
||||||
|
|
||||||
public Swamp(UUID ownerId, String cardNumber) {
|
public Swamp(UUID ownerId, String cardNumber) {
|
||||||
super(ownerId, cardNumber, "Swamp", new BlackManaAbility());
|
super(ownerId, cardNumber, "Swamp", new BlackManaAbility());
|
||||||
|
this.frameColor = ObjectColor.BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Swamp(Swamp land) {
|
public Swamp(Swamp land) {
|
||||||
|
|
|
@ -7,11 +7,18 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.repository.CardInfo;
|
import mage.cards.repository.CardInfo;
|
||||||
import mage.cards.repository.CardRepository;
|
import mage.cards.repository.CardRepository;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author North
|
* @author North
|
||||||
*/
|
*/
|
||||||
public class MockCard extends CardImpl {
|
public class MockCard extends CardImpl {
|
||||||
|
// Needs to be here, as it is normally calculated from the
|
||||||
|
// PlaneswalkerEntersWithLoyaltyAbility of the card... but the MockCard
|
||||||
|
// only has MockAbilities.
|
||||||
|
private int startingLoyalty;
|
||||||
|
|
||||||
public MockCard(CardInfo card) {
|
public MockCard(CardInfo card) {
|
||||||
super(null, card.getName());
|
super(null, card.getName());
|
||||||
this.cardNumber = card.getCardNumber();
|
this.cardNumber = card.getCardNumber();
|
||||||
|
@ -28,6 +35,9 @@ public class MockCard extends CardImpl {
|
||||||
this.manaCost = new ManaCostsImpl(join(card.getManaCosts()));
|
this.manaCost = new ManaCostsImpl(join(card.getManaCosts()));
|
||||||
|
|
||||||
this.color = card.getColor();
|
this.color = card.getColor();
|
||||||
|
|
||||||
|
this.frameColor = card.getFrameColor();
|
||||||
|
|
||||||
this.splitCard = card.isSplitCard();
|
this.splitCard = card.isSplitCard();
|
||||||
this.flipCard = card.isFlipCard();
|
this.flipCard = card.isFlipCard();
|
||||||
|
|
||||||
|
@ -37,8 +47,20 @@ public class MockCard extends CardImpl {
|
||||||
this.secondSideCard = new MockCard(CardRepository.instance.findCard(card.getSecondSideName()));
|
this.secondSideCard = new MockCard(CardRepository.instance.findCard(card.getSecondSideName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.flipCardName = card.getFlipCardName();
|
if (this.cardType.contains(CardType.PLANESWALKER)) {
|
||||||
|
String startingLoyaltyString = card.getStartingLoyalty();
|
||||||
|
if (startingLoyaltyString.isEmpty()) {
|
||||||
|
Logger.getLogger(MockCard.class).warn("Planeswalker `" + this.name + "` has empty starting loyalty.");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.startingLoyalty = Integer.parseInt(startingLoyaltyString);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Logger.getLogger(MockCard.class).warn("Planeswalker `" + this.name + "` starting loyalty in bad format: `" + startingLoyaltyString + "`.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.flipCardName = card.getFlipCardName();
|
||||||
for(String ruleText: card.getRules()) {
|
for(String ruleText: card.getRules()) {
|
||||||
this.addAbility(textAbilityFromString(ruleText));
|
this.addAbility(textAbilityFromString(ruleText));
|
||||||
}
|
}
|
||||||
|
@ -48,6 +70,11 @@ public class MockCard extends CardImpl {
|
||||||
super(card);
|
super(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return startingLoyalty;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MockCard copy() {
|
public MockCard copy() {
|
||||||
return new MockCard(this);
|
return new MockCard(this);
|
||||||
|
|
|
@ -39,7 +39,10 @@ import java.util.List;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
|
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
|
||||||
|
import mage.abilities.effects.PlaneswalkerRedirectionEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.mock.MockCard;
|
import mage.cards.mock.MockCard;
|
||||||
|
@ -70,6 +73,8 @@ public class CardInfo {
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
protected String toughness;
|
protected String toughness;
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
|
protected String startingLoyalty;
|
||||||
|
@DatabaseField
|
||||||
protected int convertedManaCost;
|
protected int convertedManaCost;
|
||||||
@DatabaseField(dataType = DataType.ENUM_STRING)
|
@DatabaseField(dataType = DataType.ENUM_STRING)
|
||||||
protected Rarity rarity;
|
protected Rarity rarity;
|
||||||
|
@ -94,6 +99,8 @@ public class CardInfo {
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
protected boolean white;
|
protected boolean white;
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
|
protected String frameColor;
|
||||||
|
@DatabaseField
|
||||||
protected boolean splitCard;
|
protected boolean splitCard;
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
protected boolean splitCardHalf;
|
protected boolean splitCardHalf;
|
||||||
|
@ -132,6 +139,7 @@ public class CardInfo {
|
||||||
this.secondSideName = secondSide.getName();
|
this.secondSideName = secondSide.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.frameColor = card.getFrameColor(null).toString();
|
||||||
this.blue = card.getColor(null).isBlue();
|
this.blue = card.getColor(null).isBlue();
|
||||||
this.black = card.getColor(null).isBlack();
|
this.black = card.getColor(null).isBlack();
|
||||||
this.green = card.getColor(null).isGreen();
|
this.green = card.getColor(null).isGreen();
|
||||||
|
@ -173,6 +181,21 @@ public class CardInfo {
|
||||||
this.splitCardHalf = true;
|
this.splitCardHalf = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Starting loyalty
|
||||||
|
if (card.getCardType().contains(CardType.PLANESWALKER)) {
|
||||||
|
for (Ability ab: card.getAbilities()) {
|
||||||
|
if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) {
|
||||||
|
this.startingLoyalty = "" + ((PlanswalkerEntersWithLoyalityCountersAbility) ab).getStartingLoyalty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.startingLoyalty == null) {
|
||||||
|
Logger.getLogger(CardInfo.class).warn("Planeswalker `" + card.getName() + "` missing starting loyalty");
|
||||||
|
this.startingLoyalty = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.startingLoyalty = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Card getCard() {
|
public Card getCard() {
|
||||||
|
@ -201,6 +224,10 @@ public class CardInfo {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObjectColor getFrameColor() {
|
||||||
|
return new ObjectColor(frameColor);
|
||||||
|
}
|
||||||
|
|
||||||
private String joinList(List<String> items) {
|
private String joinList(List<String> items) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (Object item : items) {
|
for (Object item : items) {
|
||||||
|
@ -287,6 +314,10 @@ public class CardInfo {
|
||||||
return toughness;
|
return toughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getStartingLoyalty() {
|
||||||
|
return startingLoyalty;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSetCode() {
|
public String getSetCode() {
|
||||||
return setCode;
|
return setCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,11 @@ public class Commander implements CommandObject {
|
||||||
return card.getColor(game);
|
return card.getColor(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectColor getFrameColor(Game game) {
|
||||||
|
return card.getFrameColor(game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManaCosts<ManaCost> getManaCost() {
|
public ManaCosts<ManaCost> getManaCost() {
|
||||||
return card.getManaCost();
|
return card.getManaCost();
|
||||||
|
@ -165,6 +170,11 @@ public class Commander implements CommandObject {
|
||||||
return card.getToughness();
|
return card.getToughness();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return card.getStartingLoyalty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void adjustCosts(Ability ability, Game game) {
|
public void adjustCosts(Ability ability, Game game) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,11 @@ public class Emblem implements CommandObject {
|
||||||
return emptyColor;
|
return emptyColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectColor getFrameColor(Game game) {
|
||||||
|
return emptyColor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManaCosts<ManaCost> getManaCost() {
|
public ManaCosts<ManaCost> getManaCost() {
|
||||||
return emptyCost;
|
return emptyCost;
|
||||||
|
@ -174,6 +179,11 @@ public class Emblem implements CommandObject {
|
||||||
return MageInt.EmptyMageInt;
|
return MageInt.EmptyMageInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void adjustCosts(Ability ability, Game game) {
|
public void adjustCosts(Ability ability, Game game) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
|
|
||||||
private final Card card;
|
private final Card card;
|
||||||
private final ObjectColor color;
|
private final ObjectColor color;
|
||||||
|
private final ObjectColor frameColor;
|
||||||
private final SpellAbility ability;
|
private final SpellAbility ability;
|
||||||
private final Zone fromZone;
|
private final Zone fromZone;
|
||||||
private final UUID id;
|
private final UUID id;
|
||||||
|
@ -87,6 +88,7 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) {
|
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) {
|
||||||
this.card = card;
|
this.card = card;
|
||||||
this.color = card.getColor(null).copy();
|
this.color = card.getColor(null).copy();
|
||||||
|
this.frameColor = card.getFrameColor(null).copy();
|
||||||
id = ability.getId();
|
id = ability.getId();
|
||||||
this.ability = ability;
|
this.ability = ability;
|
||||||
this.ability.setControllerId(controllerId);
|
this.ability.setControllerId(controllerId);
|
||||||
|
@ -127,6 +129,7 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
this.copiedSpell = spell.copiedSpell;
|
this.copiedSpell = spell.copiedSpell;
|
||||||
this.faceDown = spell.faceDown;
|
this.faceDown = spell.faceDown;
|
||||||
this.color = spell.color.copy();
|
this.color = spell.color.copy();
|
||||||
|
this.frameColor = spell.color.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean activate(Game game, boolean noMana) {
|
public boolean activate(Game game, boolean noMana) {
|
||||||
|
@ -483,6 +486,11 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectColor getFrameColor(Game game) {
|
||||||
|
return frameColor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManaCosts<ManaCost> getManaCost() {
|
public ManaCosts<ManaCost> getManaCost() {
|
||||||
return card.getManaCost();
|
return card.getManaCost();
|
||||||
|
@ -519,6 +527,11 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
return card.getToughness();
|
return card.getToughness();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return card.getStartingLoyalty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID getId() {
|
public UUID getId() {
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -193,6 +193,11 @@ public class StackAbility extends StackObjImpl implements Ability {
|
||||||
return emptyColor;
|
return emptyColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectColor getFrameColor(Game game) {
|
||||||
|
return ability.getSourceObject(game).getFrameColor(game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManaCosts<ManaCost> getManaCost() {
|
public ManaCosts<ManaCost> getManaCost() {
|
||||||
return emptyCost;
|
return emptyCost;
|
||||||
|
@ -208,6 +213,11 @@ public class StackAbility extends StackObjImpl implements Ability {
|
||||||
return MageInt.EmptyMageInt;
|
return MageInt.EmptyMageInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStartingLoyalty() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Zone getZone() {
|
public Zone getZone() {
|
||||||
return this.ability.getZone();
|
return this.ability.getZone();
|
||||||
|
|