Merge pull request #6 from magefree/master

pulling upstream
This commit is contained in:
brodee 2019-01-01 13:34:04 -08:00 committed by GitHub
commit 6f4c404727
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
690 changed files with 9247 additions and 4138 deletions

View file

@ -47,7 +47,7 @@ import net.java.truevfs.access.TConfig;
import net.java.truevfs.kernel.spec.FsAccessOption; import net.java.truevfs.kernel.spec.FsAccessOption;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.ManaSymbols;
import org.mage.plugins.card.images.DownloadPictures; import org.mage.plugins.card.images.DownloadPicturesService;
import org.mage.plugins.card.info.CardInfoPaneImpl; import org.mage.plugins.card.info.CardInfoPaneImpl;
import org.mage.plugins.card.utils.impl.ImageManagerImpl; import org.mage.plugins.card.utils.impl.ImageManagerImpl;
@ -1010,7 +1010,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}//GEN-LAST:event_btnImagesActionPerformed }//GEN-LAST:event_btnImagesActionPerformed
public void downloadImages() { public void downloadImages() {
DownloadPictures.startDownload(); DownloadPicturesService.startDownload();
} }
public void exitApp() { public void exitApp() {
@ -1380,7 +1380,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
Plugins.instance.downloadSymbols(); Plugins.instance.downloadSymbols();
break; break;
case CLIENT_DOWNLOAD_CARD_IMAGES: case CLIENT_DOWNLOAD_CARD_IMAGES:
DownloadPictures.startDownload(); DownloadPicturesService.startDownload();
break; break;
case CLIENT_DISCONNECT: case CLIENT_DISCONNECT:
if (SessionHandler.isConnected()) { if (SessionHandler.isConnected()) {

View file

@ -1,9 +1,8 @@
package mage.client.components.ability; package mage.client.components.ability;
import mage.client.SessionHandler; import mage.client.SessionHandler;
import mage.client.dialog.MageDialog;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.client.util.SettingsManager;
import mage.client.util.gui.GuiDisplayUtil;
import mage.remote.Session; import mage.remote.Session;
import mage.view.AbilityPickerView; import mage.view.AbilityPickerView;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -17,8 +16,8 @@ import org.mage.card.arcane.UI;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.util.*;
import java.util.List; import java.util.List;
import java.util.*;
/** /**
* Dialog for choosing abilities. * Dialog for choosing abilities.
@ -112,10 +111,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
this.selected = false; // back to false - waiting for selection this.selected = false; // back to false - waiting for selection
setVisible(true); setVisible(true);
Point centered = SettingsManager.instance.getComponentPosition(DIALOG_WIDTH, DIALOG_HEIGHT); MageDialog.makeWindowCentered(this, DIALOG_WIDTH, DIALOG_HEIGHT);
this.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
//startModal(); //startModal();
} }
@ -188,28 +184,28 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
GroupLayout.TRAILING, GroupLayout.TRAILING,
layout.createSequentialGroup().addContainerGap().add( layout.createSequentialGroup().addContainerGap().add(
layout.createParallelGroup(GroupLayout.TRAILING).add(GroupLayout.LEADING, jScrollPane2, GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE).add(GroupLayout.LEADING, layout.createParallelGroup(GroupLayout.TRAILING).add(GroupLayout.LEADING, jScrollPane2, GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE).add(GroupLayout.LEADING,
layout.createSequentialGroup().add(jLabel1).addPreferredGap(LayoutStyle.RELATED, 175, Short.MAX_VALUE).add(1, 1, 1)).add( layout.createSequentialGroup().add(jLabel1).addPreferredGap(LayoutStyle.RELATED, 175, Short.MAX_VALUE).add(1, 1, 1)).add(
GroupLayout.LEADING, GroupLayout.LEADING,
layout.createSequentialGroup().add(layout.createParallelGroup(GroupLayout.LEADING) layout.createSequentialGroup().add(layout.createParallelGroup(GroupLayout.LEADING)
) )
.addPreferredGap(LayoutStyle.RELATED) .addPreferredGap(LayoutStyle.RELATED)
.add( .add(
layout.createParallelGroup(GroupLayout.TRAILING) layout.createParallelGroup(GroupLayout.TRAILING)
.add( .add(
GroupLayout.LEADING, layout.createParallelGroup(GroupLayout.LEADING))))).add(10, 10, 10))); GroupLayout.LEADING, layout.createParallelGroup(GroupLayout.LEADING))))).add(10, 10, 10)));
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.LEADING).add( layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.LEADING).add(
layout.createSequentialGroup().add( layout.createSequentialGroup().add(
layout.createParallelGroup(GroupLayout.LEADING).add( layout.createParallelGroup(GroupLayout.LEADING).add(
layout.createSequentialGroup().add(jLabel1, GroupLayout.PREFERRED_SIZE, 36, GroupLayout.PREFERRED_SIZE) layout.createSequentialGroup().add(jLabel1, GroupLayout.PREFERRED_SIZE, 36, GroupLayout.PREFERRED_SIZE)
.add(5, 5, 5) .add(5, 5, 5)
.add( .add(
layout.createParallelGroup(GroupLayout.BASELINE) layout.createParallelGroup(GroupLayout.BASELINE)
) )
).add(layout.createSequentialGroup().add(8, 8, 8))) ).add(layout.createSequentialGroup().add(8, 8, 8)))
.addPreferredGap(LayoutStyle.RELATED).add(layout.createParallelGroup(GroupLayout.BASELINE)).addPreferredGap(LayoutStyle.RELATED).add( .addPreferredGap(LayoutStyle.RELATED).add(layout.createParallelGroup(GroupLayout.BASELINE)).addPreferredGap(LayoutStyle.RELATED).add(
layout.createParallelGroup(GroupLayout.BASELINE)).addPreferredGap(LayoutStyle.RELATED).add(layout.createParallelGroup(GroupLayout.LEADING)).addPreferredGap( layout.createParallelGroup(GroupLayout.BASELINE)).addPreferredGap(LayoutStyle.RELATED).add(layout.createParallelGroup(GroupLayout.LEADING)).addPreferredGap(
LayoutStyle.RELATED).add(jScrollPane2, GroupLayout.PREFERRED_SIZE, 180, GroupLayout.PREFERRED_SIZE).addContainerGap(23, Short.MAX_VALUE))); LayoutStyle.RELATED).add(jScrollPane2, GroupLayout.PREFERRED_SIZE, 180, GroupLayout.PREFERRED_SIZE).addContainerGap(23, Short.MAX_VALUE)));
} }
@Override @Override

View file

@ -41,7 +41,7 @@ import mage.view.PlaneView;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.ManaSymbols;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import static org.mage.plugins.card.images.DownloadPictures.getTokenCardUrls; import static org.mage.plugins.card.images.DownloadPicturesService.getTokenCardUrls;
/** /**
* Mage book with cards and page flipping. * Mage book with cards and page flipping.

View file

@ -34,6 +34,8 @@ import javax.swing.DefaultComboBoxModel;
import javax.swing.JLayeredPane; import javax.swing.JLayeredPane;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import mage.cards.repository.CardRepository;
import mage.choices.Choice; import mage.choices.Choice;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
import mage.client.MageFrame; import mage.client.MageFrame;
@ -454,7 +456,8 @@ public class ConnectDialog extends MageDialog {
connection.setPort(Integer.valueOf(this.txtPort.getText().trim())); connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
connection.setUsername(this.txtUserName.getText().trim()); connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim()); connection.setPassword(this.txtPassword.getText().trim());
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); boolean redownloadDatabase = CardRepository.instance.findCard("Island") == null;
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected() || redownloadDatabase);
String allMAC = ""; String allMAC = "";
try { try {
allMAC = connection.getMAC(); allMAC = connection.getMAC();

View file

@ -0,0 +1,560 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<Properties>
<Property name="title" type="java.lang.String" value="Downloading images"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 400]"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,73,0,0,2,65"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelGlobal">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="North"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
<SubComponents>
<Component class="javax.swing.Box$Filler" name="fillerGlobal1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 5]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="labelGlobal">
<Properties>
<Property name="text" type="java.lang.String" value="Initializing image download..."/>
<Property name="alignmentX" type="float" value="0.5"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="buttonStop">
<Properties>
<Property name="text" type="java.lang.String" value="Cancel"/>
<Property name="alignmentX" type="float" value="0.5"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[65, 30]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonStopActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.Box$Filler" name="fillerglobal2">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 5]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JTabbedPane" name="tabsList">
<Properties>
<Property name="tabLayoutPolicy" type="int" value="1"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="tabMain">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Standard download">
<Property name="tabTitle" type="java.lang.String" value="Standard download"/>
<Property name="tabIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/buttons/card_panel.png"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelInfo">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
<SubComponents>
<Component class="javax.swing.Box$Filler" name="fillerInfo1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 5]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="labelInfo">
<Properties>
<Property name="text" type="java.lang.String" value="Missing stats: 12345 card images / 789 token images"/>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder bottom="0" left="7" right="0" top="0"/>
</Border>
</Property>
</Properties>
</Component>
<Component class="javax.swing.Box$Filler" name="fillerInfo2">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 5]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelSource">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[65536, 55]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[352, 55]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[593, 55]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="0"/>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelSourceLeft">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[430, 30]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
<Property name="alignment" type="int" value="3"/>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="labelSource">
<Properties>
<Property name="text" type="java.lang.String" value="Images source to download:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="comboSource">
<Properties>
<Property name="maximumRowCount" type="int" value="15"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[400, 25]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelSourceRight">
<Properties>
<Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 100]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
<Property name="alignment" type="int" value="3"/>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="labelLanguage">
<Properties>
<Property name="text" type="java.lang.String" value="Language:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="comboLanguage">
<Properties>
<Property name="maximumRowCount" type="int" value="15"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[90, 25]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelMode">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32869, 55]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[322, 55]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 55]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelModeInner">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[430, 43]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
<Property name="alignment" type="int" value="0"/>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="labelMode">
<Properties>
<Property name="text" type="java.lang.String" value="Sets to download:"/>
<Property name="alignmentY" type="float" value="0.0"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="panelModeSelect">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="0"/>
</Layout>
<SubComponents>
<Component class="javax.swing.JComboBox" name="comboSets">
<Properties>
<Property name="maximumRowCount" type="int" value="15"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[373, 25]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.Box$Filler" name="fillerMode1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalStrut"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="buttonSearchSet">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/buttons/search_24.png"/>
</Property>
<Property name="toolTipText" type="java.lang.String" value="Fast search your flag"/>
<Property name="alignmentX" type="float" value="1.0"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[25, 25]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonSearchSetActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelRedownload">
<Properties>
<Property name="alignmentX" type="float" value="0.0"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[130, 100]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="checkboxRedownload">
<Properties>
<Property name="text" type="java.lang.String" value="&lt;html&gt;Re-download selected images"/>
<Property name="verticalAlignment" type="int" value="3"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.Box$Filler" name="filler1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 5]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 3]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Last"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="javax.swing.Box$Filler" name="fillerMain1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 10]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 10]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 10]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
<Container class="javax.swing.JPanel" name="panelProgress">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32777, 30]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[20, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[564, 30]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="0"/>
</Layout>
<SubComponents>
<Component class="javax.swing.Box$Filler" name="fillerProgress1">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalStrut"/>
</AuxValues>
</Component>
<Component class="javax.swing.JProgressBar" name="progress">
<Properties>
<Property name="value" type="int" value="75"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 25]"/>
</Property>
<Property name="string" type="java.lang.String" value="123 of 12313 (120 cards/546 tokens) image downloads finished! Please wait! [123 Mb]"/>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
</Component>
<Component class="javax.swing.Box$Filler" name="fillerProgress2">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 32767]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 0]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalStrut"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.Box$Filler" name="fillerMain2">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 32767]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.Glue"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="tabCustom">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Custom download">
<Property name="tabTitle" type="java.lang.String" value="Custom download"/>
<Property name="tabIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/buttons/list_panel.png"/>
</Property>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelCommands">
<Properties>
<Property name="alignmentX" type="float" value="0.0"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="South"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
<Property name="alignment" type="int" value="4"/>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="buttonOK">
<Properties>
<Property name="text" type="java.lang.String" value="Start download"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[120, 30]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_AddingCodePost" type="java.lang.String" value="getRootPane().setDefaultButton(buttonOK);"/>
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="DownloadImagesDialog_buttonOK"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="buttonCancel">
<Properties>
<Property name="text" type="java.lang.String" value="Cancel"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[80, 30]"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View file

@ -0,0 +1,470 @@
package mage.client.dialog;
import mage.client.MageFrame;
import mage.client.util.gui.FastSearchUtil;
import mage.client.util.gui.MageDialogState;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
/**
* @author JayDi85
*/
public class DownloadImagesDialog extends MageDialog {
public static final int RET_CANCEL = 0;
public static final int RET_OK = 1;
private Dimension sizeModeMessageOnly;
private Dimension sizeModeMessageAndControls;
private Map<Component, Boolean> actionsControlStates = new HashMap<>();
/**
* Creates new form DownloadImagesDialog
*/
public DownloadImagesDialog() {
initComponents();
this.setModal(true);
// fix for panelInfo (it's resets aligmentX after netbeans designer opened)
panelInfo.setAlignmentX(CENTER_ALIGNMENT);
// save default sizes
//
this.sizeModeMessageAndControls = new Dimension(580, 330); // dialog -> properties -> designer size
//
this.sizeModeMessageOnly = new Dimension(this.sizeModeMessageAndControls.getSize());
sizeModeMessageOnly.height = 25 * 4;
sizeModeMessageOnly.width = sizeModeMessageOnly.width / 2;
// Close the dialog when Esc is pressed
String cancelName = "cancel";
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
ActionMap actionMap = getRootPane().getActionMap();
actionMap.put(cancelName, new AbstractAction() {
public void actionPerformed(ActionEvent e) {
doClose(RET_CANCEL);
}
});
}
public void setWindowSize(int width, int heigth) {
this.setSize(new Dimension(width, heigth));
}
public void showDialog() {
showDialog(null);
}
public void showDialog(MageDialogState mageDialogState) {
showDownloadControls(false); // call to change window size
// window settings
if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
} else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
}
if (mageDialogState != null) {
mageDialogState.setStateToDialog(this);
} else {
this.makeWindowCentered();
}
this.setVisible(true);
}
public void setGlobalInfo(String info) {
this.labelGlobal.setText(info);
}
public void setCurrentInfo(String info) {
this.labelInfo.setText(info);
}
public JComboBox getSourcesCombo() {
return this.comboSource;
}
public JComboBox getLaunguagesCombo() {
return this.comboLanguage;
}
public JComboBox getSetsCombo() {
return this.comboSets;
}
public JButton getStartButton() {
return this.buttonOK;
}
public JButton getCancelButton() {
return this.buttonCancel;
}
public JButton getStopButton() {
return this.buttonStop;
}
public JProgressBar getProgressBar() {
return this.progress;
}
public JCheckBox getRedownloadCheckbox() {
return this.checkboxRedownload;
}
public void showLanguagesSupport(boolean haveSupport) {
labelLanguage.setEnabled(haveSupport);
comboLanguage.setEnabled(haveSupport);
}
private void enableActionControl(boolean enable, Component comp) {
if (enable) {
// restore last enable state
comp.setEnabled(actionsControlStates.getOrDefault(comp, true));
} else {
// save enable state and disable it
actionsControlStates.putIfAbsent(comp, comp.isEnabled());
comp.setEnabled(false);
}
}
public void enableActionControls(boolean enable) {
// restrict user actions while downloading/processing (all buttons, comboboxes and edits)
enableActionControl(enable, tabsList);
enableActionControl(enable, comboSource);
enableActionControl(enable, comboSets);
enableActionControl(enable, buttonSearchSet);
enableActionControl(enable, comboLanguage);
enableActionControl(enable, checkboxRedownload);
}
private void setTabTitle(int tabIndex, String title, String iconResourceName) {
// tab caption with left sided icon
// https://stackoverflow.com/questions/1782224/jtabbedpane-icon-on-left-side-of-tabs
JLabel lbl = new JLabel(title);
Icon icon = new ImageIcon(getClass().getResource(iconResourceName));
lbl.setIcon(icon);
lbl.setIconTextGap(5);
lbl.setHorizontalTextPosition(SwingConstants.RIGHT);
tabsList.setTabComponentAt(tabIndex, lbl);
}
public void showDownloadControls(boolean needToShow) {
// 2 modes:
// - only message;
// - message + download controls and buttons
this.panelGlobal.setVisible(true);
this.buttonStop.setVisible(!needToShow); // stop button only for loading mode
this.tabsList.setVisible(needToShow);
this.panelCommands.setVisible(needToShow);
// auto-size form
if (needToShow) {
this.setWindowSize(this.sizeModeMessageAndControls.width, this.sizeModeMessageAndControls.height);
} else {
this.setWindowSize(this.sizeModeMessageOnly.width, this.sizeModeMessageOnly.height);
}
this.makeWindowCentered();
//this.setLocationRelativeTo(null); // center screen //FIX
// icons on tabs left side
setTabTitle(0, "Standard download", "/buttons/card_panel.png");
setTabTitle(1, "Custom download", "/buttons/list_panel.png");
// TODO: add manual mode as tab
this.tabsList.getTabComponentAt(1).setEnabled(false);
this.tabsList.setEnabledAt(1, false);
}
/**
* @return the return status of this dialog - one of RET_OK or RET_CANCEL
*/
public int getReturnStatus() {
return returnStatus;
}
/**
* 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
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
panelGlobal = new javax.swing.JPanel();
fillerGlobal1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
labelGlobal = new javax.swing.JLabel();
buttonStop = new javax.swing.JButton();
fillerglobal2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
tabsList = new javax.swing.JTabbedPane();
tabMain = new javax.swing.JPanel();
panelInfo = new javax.swing.JPanel();
fillerInfo1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
labelInfo = new javax.swing.JLabel();
fillerInfo2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
panelSource = new javax.swing.JPanel();
panelSourceLeft = new javax.swing.JPanel();
labelSource = new javax.swing.JLabel();
comboSource = new javax.swing.JComboBox<>();
panelSourceRight = new javax.swing.JPanel();
labelLanguage = new javax.swing.JLabel();
comboLanguage = new javax.swing.JComboBox<>();
panelMode = new javax.swing.JPanel();
panelModeInner = new javax.swing.JPanel();
labelMode = new javax.swing.JLabel();
panelModeSelect = new javax.swing.JPanel();
comboSets = new javax.swing.JComboBox<>();
fillerMode1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
buttonSearchSet = new javax.swing.JButton();
panelRedownload = new javax.swing.JPanel();
checkboxRedownload = new javax.swing.JCheckBox();
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 3), new java.awt.Dimension(32767, 5));
fillerMain1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
panelProgress = new javax.swing.JPanel();
fillerProgress1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
progress = new javax.swing.JProgressBar();
fillerProgress2 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767));
fillerMain2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 32767));
tabCustom = new javax.swing.JPanel();
panelCommands = new javax.swing.JPanel();
buttonOK = new javax.swing.JButton();
buttonCancel = new javax.swing.JButton();
setTitle("Downloading images");
setPreferredSize(new java.awt.Dimension(600, 400));
getContentPane().setLayout(new java.awt.BorderLayout());
panelGlobal.setLayout(new javax.swing.BoxLayout(panelGlobal, javax.swing.BoxLayout.Y_AXIS));
panelGlobal.add(fillerGlobal1);
labelGlobal.setText("Initializing image download...");
labelGlobal.setAlignmentX(0.5F);
panelGlobal.add(labelGlobal);
buttonStop.setText("Cancel");
buttonStop.setAlignmentX(0.5F);
buttonStop.setPreferredSize(new java.awt.Dimension(65, 30));
buttonStop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonStopActionPerformed(evt);
}
});
panelGlobal.add(buttonStop);
panelGlobal.add(fillerglobal2);
getContentPane().add(panelGlobal, java.awt.BorderLayout.NORTH);
tabsList.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT);
tabMain.setLayout(new javax.swing.BoxLayout(tabMain, javax.swing.BoxLayout.Y_AXIS));
panelInfo.setLayout(new javax.swing.BoxLayout(panelInfo, javax.swing.BoxLayout.Y_AXIS));
panelInfo.add(fillerInfo1);
labelInfo.setText("Missing stats: 12345 card images / 789 token images");
labelInfo.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 7, 0, 0));
panelInfo.add(labelInfo);
panelInfo.add(fillerInfo2);
tabMain.add(panelInfo);
panelSource.setMaximumSize(new java.awt.Dimension(65536, 55));
panelSource.setMinimumSize(new java.awt.Dimension(352, 55));
panelSource.setPreferredSize(new java.awt.Dimension(593, 55));
panelSource.setLayout(new javax.swing.BoxLayout(panelSource, javax.swing.BoxLayout.X_AXIS));
panelSourceLeft.setMinimumSize(new java.awt.Dimension(430, 30));
panelSourceLeft.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEADING));
labelSource.setText("Images source to download:");
panelSourceLeft.add(labelSource);
comboSource.setMaximumRowCount(15);
comboSource.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
comboSource.setMinimumSize(new java.awt.Dimension(300, 20));
comboSource.setPreferredSize(new java.awt.Dimension(400, 25));
panelSourceLeft.add(comboSource);
panelSource.add(panelSourceLeft);
panelSourceRight.setAlignmentX(0.0F);
panelSourceRight.setMaximumSize(new java.awt.Dimension(130, 32767));
panelSourceRight.setMinimumSize(new java.awt.Dimension(130, 30));
panelSourceRight.setPreferredSize(new java.awt.Dimension(130, 100));
panelSourceRight.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEADING));
labelLanguage.setText("Language:");
panelSourceRight.add(labelLanguage);
comboLanguage.setMaximumRowCount(15);
comboLanguage.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
comboLanguage.setPreferredSize(new java.awt.Dimension(90, 25));
panelSourceRight.add(comboLanguage);
panelSource.add(panelSourceRight);
tabMain.add(panelSource);
panelMode.setMaximumSize(new java.awt.Dimension(32869, 55));
panelMode.setMinimumSize(new java.awt.Dimension(322, 55));
panelMode.setPreferredSize(new java.awt.Dimension(100, 55));
panelMode.setLayout(new javax.swing.BoxLayout(panelMode, javax.swing.BoxLayout.LINE_AXIS));
panelModeInner.setMinimumSize(new java.awt.Dimension(430, 43));
panelModeInner.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
labelMode.setText("Sets to download:");
labelMode.setAlignmentY(0.0F);
panelModeInner.add(labelMode);
panelModeSelect.setLayout(new javax.swing.BoxLayout(panelModeSelect, javax.swing.BoxLayout.X_AXIS));
comboSets.setMaximumRowCount(15);
comboSets.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
comboSets.setPreferredSize(new java.awt.Dimension(373, 25));
panelModeSelect.add(comboSets);
panelModeSelect.add(fillerMode1);
buttonSearchSet.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png"))); // NOI18N
buttonSearchSet.setToolTipText("Fast search your flag");
buttonSearchSet.setAlignmentX(1.0F);
buttonSearchSet.setPreferredSize(new java.awt.Dimension(25, 25));
buttonSearchSet.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonSearchSetActionPerformed(evt);
}
});
panelModeSelect.add(buttonSearchSet);
panelModeInner.add(panelModeSelect);
panelMode.add(panelModeInner);
panelRedownload.setAlignmentX(0.0F);
panelRedownload.setMaximumSize(new java.awt.Dimension(130, 32767));
panelRedownload.setMinimumSize(new java.awt.Dimension(130, 30));
panelRedownload.setPreferredSize(new java.awt.Dimension(130, 100));
panelRedownload.setLayout(new java.awt.BorderLayout());
checkboxRedownload.setText("<html>Re-download selected images");
checkboxRedownload.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
panelRedownload.add(checkboxRedownload, java.awt.BorderLayout.CENTER);
panelRedownload.add(filler1, java.awt.BorderLayout.PAGE_END);
panelMode.add(panelRedownload);
tabMain.add(panelMode);
tabMain.add(fillerMain1);
panelProgress.setMaximumSize(new java.awt.Dimension(32777, 30));
panelProgress.setMinimumSize(new java.awt.Dimension(20, 30));
panelProgress.setPreferredSize(new java.awt.Dimension(564, 30));
panelProgress.setLayout(new javax.swing.BoxLayout(panelProgress, javax.swing.BoxLayout.X_AXIS));
panelProgress.add(fillerProgress1);
progress.setValue(75);
progress.setMaximumSize(new java.awt.Dimension(32767, 25));
progress.setString("123 of 12313 (120 cards/546 tokens) image downloads finished! Please wait! [123 Mb]");
progress.setStringPainted(true);
panelProgress.add(progress);
panelProgress.add(fillerProgress2);
tabMain.add(panelProgress);
tabMain.add(fillerMain2);
tabsList.addTab("Standard download", new javax.swing.ImageIcon(getClass().getResource("/buttons/card_panel.png")), tabMain); // NOI18N
tabCustom.setLayout(new javax.swing.BoxLayout(tabCustom, javax.swing.BoxLayout.Y_AXIS));
tabsList.addTab("Custom download", new javax.swing.ImageIcon(getClass().getResource("/buttons/list_panel.png")), tabCustom); // NOI18N
getContentPane().add(tabsList, java.awt.BorderLayout.CENTER);
panelCommands.setAlignmentX(0.0F);
panelCommands.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.TRAILING));
buttonOK.setText("Start download");
buttonOK.setPreferredSize(new java.awt.Dimension(120, 30));
panelCommands.add(buttonOK);
getRootPane().setDefaultButton(buttonOK);
buttonCancel.setText("Cancel");
buttonCancel.setPreferredSize(new java.awt.Dimension(80, 30));
panelCommands.add(buttonCancel);
getContentPane().add(panelCommands, java.awt.BorderLayout.SOUTH);
pack();
}// </editor-fold>//GEN-END:initComponents
/**
* Closes the dialog
*/
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
doClose(RET_CANCEL);
}//GEN-LAST:event_closeDialog
private void buttonSearchSetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSearchSetActionPerformed
FastSearchUtil.showFastSearchForStringComboBox(comboSets, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE, 400, 500);
}//GEN-LAST:event_buttonSearchSetActionPerformed
private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_buttonStopActionPerformed
private void doClose(int retStatus) {
returnStatus = retStatus;
setVisible(false);
dispose();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonOK;
private javax.swing.JButton buttonSearchSet;
private javax.swing.JButton buttonStop;
private javax.swing.JCheckBox checkboxRedownload;
private javax.swing.JComboBox<String> comboLanguage;
private javax.swing.JComboBox<String> comboSets;
private javax.swing.JComboBox<String> comboSource;
private javax.swing.Box.Filler filler1;
private javax.swing.Box.Filler fillerGlobal1;
private javax.swing.Box.Filler fillerInfo1;
private javax.swing.Box.Filler fillerInfo2;
private javax.swing.Box.Filler fillerMain1;
private javax.swing.Box.Filler fillerMain2;
private javax.swing.Box.Filler fillerMode1;
private javax.swing.Box.Filler fillerProgress1;
private javax.swing.Box.Filler fillerProgress2;
private javax.swing.Box.Filler fillerglobal2;
private javax.swing.JLabel labelGlobal;
private javax.swing.JLabel labelInfo;
private javax.swing.JLabel labelLanguage;
private javax.swing.JLabel labelMode;
private javax.swing.JLabel labelSource;
private javax.swing.JPanel panelCommands;
private javax.swing.JPanel panelGlobal;
private javax.swing.JPanel panelInfo;
private javax.swing.JPanel panelMode;
private javax.swing.JPanel panelModeInner;
private javax.swing.JPanel panelModeSelect;
private javax.swing.JPanel panelProgress;
private javax.swing.JPanel panelRedownload;
private javax.swing.JPanel panelSource;
private javax.swing.JPanel panelSourceLeft;
private javax.swing.JPanel panelSourceRight;
private javax.swing.JProgressBar progress;
private javax.swing.JPanel tabCustom;
private javax.swing.JPanel tabMain;
private javax.swing.JTabbedPane tabsList;
// End of variables declaration//GEN-END:variables
private int returnStatus = RET_CANCEL;
}

View file

@ -1,31 +1,19 @@
/*
* MageDialog.java
*
* Created on 15-Dec-2009, 10:28:27 PM
*/
package mage.client.dialog; package mage.client.dialog;
import java.awt.AWTEvent; import mage.client.MageFrame;
import java.awt.ActiveEvent; import mage.client.util.SettingsManager;
import java.awt.Component; import mage.client.util.gui.GuiDisplayUtil;
import java.awt.EventQueue; import org.apache.log4j.Logger;
import java.awt.KeyboardFocusManager;
import java.awt.MenuComponent; import javax.swing.*;
import java.awt.TrayIcon; import java.awt.*;
import java.awt.event.InvocationEvent; import java.awt.event.InvocationEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.PropertyVetoException; import java.beans.PropertyVetoException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.*;
import mage.client.MageFrame;
import org.apache.log4j.Logger;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class MageDialog extends javax.swing.JInternalFrame { public class MageDialog extends javax.swing.JInternalFrame {
@ -75,7 +63,7 @@ public class MageDialog extends javax.swing.JInternalFrame {
this.toFront(); this.toFront();
if (modal){ if (modal) {
startModal(); startModal();
} }
} }
@ -105,6 +93,7 @@ public class MageDialog extends javax.swing.JInternalFrame {
} }
private synchronized void startModal() { private synchronized void startModal() {
// modal loop -- all mouse events must be ignored by other windows
try { try {
if (SwingUtilities.isEventDispatchThread()) { if (SwingUtilities.isEventDispatchThread()) {
EventQueue theQueue = getToolkit().getSystemEventQueue(); EventQueue theQueue = getToolkit().getSystemEventQueue();
@ -115,18 +104,46 @@ public class MageDialog extends javax.swing.JInternalFrame {
// https://github.com/magefree/mage/issues/584 - Let's hope this will fix the Linux window problem // https://github.com/magefree/mage/issues/584 - Let's hope this will fix the Linux window problem
if (event.getSource() != null && event.getSource() instanceof TrayIcon && !(event instanceof InvocationEvent)) { if (event.getSource() != null && event.getSource() instanceof TrayIcon && !(event instanceof InvocationEvent)) {
return; dispatch = false;
//return; // JayDi85: users can move mouse over try icon to disable modal mode (it's a bug but can be used in the future)
} }
// ignore mouse events outside from panel, only drag and move allowed -- as example:
// combobox's popup will be selectable outside
// cards and button hints will be works
Component popupComponent = null;
MouseEvent popupEvent = null;
if (event instanceof MouseEvent && event.getSource() instanceof Component) { if (event instanceof MouseEvent && event.getSource() instanceof Component) {
MouseEvent e = (MouseEvent) event; MouseEvent e = (MouseEvent) event;
MouseEvent m = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this); MouseEvent m = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this);
if (!this.contains(m.getPoint()) && e.getID() != MouseEvent.MOUSE_DRAGGED) {
dispatch = false; // disable all outer events (except some actions)
if (!this.contains(m.getPoint())) {
boolean allowedEvent = false;
// need any mouse move (for hints)
if (e.getID() == MouseEvent.MOUSE_DRAGGED || e.getID() == MouseEvent.MOUSE_MOVED) {
allowedEvent = true;
}
// need popup clicks and mouse wheel (for out of bound actions)
if (!allowedEvent) {
popupComponent = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY()); // show root component (popups creates at root)
if (popupComponent != null && popupComponent.getClass().getName().contains("BasicComboPopup")) {
popupEvent = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, popupComponent);
allowedEvent = true;
}
}
dispatch = allowedEvent;
} }
} }
if (dispatch) { if (dispatch) {
if (event instanceof ActiveEvent) { if (popupEvent != null) {
// process outer popup events, it's must be FIRST check
popupComponent.dispatchEvent(popupEvent);
} else if (event instanceof ActiveEvent) {
((ActiveEvent) event).dispatch(); ((ActiveEvent) event).dispatch();
} else if (source instanceof Component) { } else if (source instanceof Component) {
((Component) source).dispatchEvent(event); ((Component) source).dispatchEvent(event);
@ -174,14 +191,21 @@ public class MageDialog extends javax.swing.JInternalFrame {
java.util.logging.Logger.getLogger(MageDialog.class.getName()).log(Level.SEVERE, "setClosed(false) failed", ex); java.util.logging.Logger.getLogger(MageDialog.class.getName()).log(Level.SEVERE, "setClosed(false) failed", ex);
} }
MageFrame.getDesktop().remove(this); MageFrame.getDesktop().remove(this);
}
public void makeWindowCentered() {
makeWindowCentered(this, getWidth(), getHeight());
}
public static void makeWindowCentered(Component component, int width, int height) {
Point centered = SettingsManager.instance.getComponentPosition(width, height);
component.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, component);
} }
/** /**
* Used to set a tooltip text on icon and titel bar * Used to set a tooltip text on icon and titel bar
* *
* used in {@link ExileZoneDialog} and {@link ShowCardsDialog}
*
* @param text * @param text
*/ */
public void setTitelBarToolTip(final String text) { public void setTitelBarToolTip(final String text) {
@ -209,12 +233,12 @@ public class MageDialog extends javax.swing.JInternalFrame {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 394, Short.MAX_VALUE) .addGap(0, 394, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 274, Short.MAX_VALUE) .addGap(0, 274, Short.MAX_VALUE)
); );
pack(); pack();

View file

@ -1,37 +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 mage.client.dialog; package mage.client.dialog;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.DefaultListModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.KeyStroke;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import mage.choices.Choice; import mage.choices.Choice;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.util.SettingsManager;
import mage.client.util.gui.GuiDisplayUtil;
import mage.client.util.gui.MageDialogState; import mage.client.util.gui.MageDialogState;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/** /**
*
* @author JayDi85 * @author JayDi85
* @author Salco * @author Salco
*/ */
@ -42,28 +22,29 @@ public class PickCheckBoxDialog extends MageDialog {
ArrayList<KeyValueItem> allItems = new ArrayList<>(); ArrayList<KeyValueItem> allItems = new ArrayList<>();
DefaultListModel<KeyValueItem> dataModel = new DefaultListModel(); DefaultListModel<KeyValueItem> dataModel = new DefaultListModel();
CheckBoxList.CheckBoxListModel m_dataModel; CheckBoxList.CheckBoxListModel m_dataModel;
CheckBoxList tList; CheckBoxList tList;
final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>"; final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
private void setFocus(CheckBoxList obj){ private void setFocus(CheckBoxList obj) {
if (!(obj instanceof java.awt.Component)) { if (!(obj instanceof java.awt.Component)) {
throw new IllegalArgumentException("Must be a java.awt.Component!"); throw new IllegalArgumentException("Must be a java.awt.Component!");
} }
this.scrollList.setViewportView((java.awt.Component)obj); this.scrollList.setViewportView((java.awt.Component) obj);
}
private javax.swing.JList get_a_Jlist_from_ScrollListView(){
return ((javax.swing.JList)this.scrollList.getViewport().getView());
} }
private void restoreData(Object dataFrom){ private javax.swing.JList get_a_Jlist_from_ScrollListView() {
return ((javax.swing.JList) this.scrollList.getViewport().getView());
}
private void restoreData(Object dataFrom) {
this.allItems.forEach((item) -> { this.allItems.forEach((item) -> {
((CheckBoxList.CheckBoxListModel)dataFrom).addElement(item.getObjectValue()); ((CheckBoxList.CheckBoxListModel) dataFrom).addElement(item.getObjectValue());
}); });
} }
public void showDialog(Choice choice) { public void showDialog(Choice choice) {
showDialog(choice, null, null, null); showDialog(choice, null, null, null);
} }
@ -75,47 +56,45 @@ public class PickCheckBoxDialog extends MageDialog {
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) { public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) {
showDialog(choice, objectId, mageDialogState, null); showDialog(choice, objectId, mageDialogState, null);
} }
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) { public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) {
this.choice = choice; this.choice = choice;
KeyValueItem tempKeyValue; KeyValueItem tempKeyValue;
int indexInTList; int indexInTList;
setLabelText(this.labelMessage, choice.getMessage()); setLabelText(this.labelMessage, choice.getMessage());
setLabelText(this.labelSubMessage, choice.getSubMessage()); setLabelText(this.labelSubMessage, choice.getSubMessage());
btCancel.setEnabled(!choice.isRequired()); btCancel.setEnabled(!choice.isRequired());
// 2 modes: string or key-values // 2 modes: string or key-values
// sore data in allItems for inremental filtering // sore data in allItems for inremental filtering
// http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/ // http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/
this.allItems.clear(); this.allItems.clear();
if (choice.isKeyChoice()){ if (choice.isKeyChoice()) {
for (Map.Entry<String, String> entry: choice.getKeyChoices().entrySet()) { for (Map.Entry<String, String> entry : choice.getKeyChoices().entrySet()) {
if(tList != null){ if (tList != null) {
indexInTList = m_dataModel.indexOf(entry.getKey()); indexInTList = m_dataModel.indexOf(entry.getKey());
tempKeyValue=new KeyValueItem(entry.getKey(), entry.getValue(),(CheckBoxList.CheckBoxListItem) this.tList.getModel().getElementAt(indexInTList)); tempKeyValue = new KeyValueItem(entry.getKey(), entry.getValue(), (CheckBoxList.CheckBoxListItem) this.tList.getModel().getElementAt(indexInTList));
} } else {
else{ tempKeyValue = new KeyValueItem(entry.getKey(), entry.getValue());
tempKeyValue=new KeyValueItem(entry.getKey(), entry.getValue());
} }
this.allItems.add(tempKeyValue); this.allItems.add(tempKeyValue);
} }
} else { } else {
for (String value: choice.getChoices()){ for (String value : choice.getChoices()) {
if(tList != null){ if (tList != null) {
indexInTList = m_dataModel.indexOf(value); indexInTList = m_dataModel.indexOf(value);
tempKeyValue=new KeyValueItem(value, value,(CheckBoxList.CheckBoxListItem) tList.getModel().getElementAt(indexInTList)); tempKeyValue = new KeyValueItem(value, value, (CheckBoxList.CheckBoxListItem) tList.getModel().getElementAt(indexInTList));
} } else {
else{ tempKeyValue = new KeyValueItem(value, value);
tempKeyValue=new KeyValueItem(value, value);
} }
this.allItems.add(tempKeyValue); this.allItems.add(tempKeyValue);
} }
} }
// sorting // sorting
if(choice.isSortEnabled()){ if (choice.isSortEnabled()) {
Collections.sort(this.allItems, new Comparator<KeyValueItem>() { Collections.sort(this.allItems, new Comparator<KeyValueItem>() {
@Override @Override
public int compare(KeyValueItem o1, KeyValueItem o2) { public int compare(KeyValueItem o1, KeyValueItem o2) {
@ -125,38 +104,37 @@ public class PickCheckBoxDialog extends MageDialog {
} }
}); });
} }
// search // search
if(choice.isSearchEnabled()) if (choice.isSearchEnabled()) {
{
panelSearch.setVisible(true); panelSearch.setVisible(true);
this.editSearch.setText(choice.getSearchText()); this.editSearch.setText(choice.getSearchText());
}else{ } else {
panelSearch.setVisible(false); panelSearch.setVisible(false);
this.editSearch.setText(""); this.editSearch.setText("");
} }
// listeners for inremental filtering // listeners for inremental filtering
editSearch.getDocument().addDocumentListener(new DocumentListener() { editSearch.getDocument().addDocumentListener(new DocumentListener() {
@Override @Override
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
@Override @Override
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
@Override @Override
public void changedUpdate(DocumentEvent e) { public void changedUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
}); });
// listeners for select up and down without edit focus lost // listeners for select up and down without edit focus lost
editSearch.addKeyListener(new KeyListener() { editSearch.addKeyListener(new KeyListener() {
@Override @Override
@ -165,10 +143,10 @@ public class PickCheckBoxDialog extends MageDialog {
} }
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){ if (e.getKeyCode() == KeyEvent.VK_UP) {
doPrevSelect(); doPrevSelect();
}else if(e.getKeyCode() == KeyEvent.VK_DOWN){ } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
doNextSelect(); doNextSelect();
} }
} }
@ -178,19 +156,19 @@ public class PickCheckBoxDialog extends MageDialog {
//System.out.println("released"); //System.out.println("released");
} }
}); });
// listeners double click choose // listeners double click choose
listChoices.addMouseListener(new MouseAdapter() { listChoices.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2){ if (e.getClickCount() == 2) {
doChoose(); doChoose();
} }
} }
}); });
// listeners for ESC close // listeners for ESC close
if(!choice.isRequired()){ if (!choice.isRequired()) {
String cancelName = "cancel"; String cancelName = "cancel";
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
@ -201,107 +179,106 @@ public class PickCheckBoxDialog extends MageDialog {
} }
}); });
} }
// window settings // window settings
if (this.isModal()){ if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
}else{ } else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
} }
if (mageDialogState != null) { if (mageDialogState != null) {
mageDialogState.setStateToDialog(this); mageDialogState.setStateToDialog(this);
} else { } else {
Point centered = SettingsManager.instance.getComponentPosition(getWidth(), getHeight()); this.makeWindowCentered();
this.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
} }
// final load // final load
loadData(); loadData();
// start selection // start selection
if((startSelectionValue != null)){ if ((startSelectionValue != null)) {
javax.swing.JList currentlistChoices;// = new javax.swing.JList(); javax.swing.JList currentlistChoices;// = new javax.swing.JList();
currentlistChoices=this.get_a_Jlist_from_ScrollListView(); currentlistChoices = this.get_a_Jlist_from_ScrollListView();
/*currentlistChoices = this.listChoices;*/ /*currentlistChoices = this.listChoices;*/
int selectIndex = -1; int selectIndex = -1;
for(int i = 0; i < this.listChoices.getModel().getSize(); i++){ for (int i = 0; i < this.listChoices.getModel().getSize(); i++) {
//KeyValueItem listItem = (KeyValueItem)currentlistChoices.getModel().getElementAt(i); //KeyValueItem listItem = (KeyValueItem)currentlistChoices.getModel().getElementAt(i);
String elementOfList = currentlistChoices.getModel().getElementAt(i).toString(); String elementOfList = currentlistChoices.getModel().getElementAt(i).toString();
if (elementOfList.equals(startSelectionValue)){ if (elementOfList.equals(startSelectionValue)) {
selectIndex = i; selectIndex = i;
break; break;
} }
} }
if(selectIndex >= 0){ if (selectIndex >= 0) {
// currentlistChoices=this.get_a_Jlist_from_ScrollListView(); // currentlistChoices=this.get_a_Jlist_from_ScrollListView();
/*currentlistChoices = this.listChoices;*/ /*currentlistChoices = this.listChoices;*/
currentlistChoices.setSelectedIndex(selectIndex); currentlistChoices.setSelectedIndex(selectIndex);
currentlistChoices.ensureIndexIsVisible(selectIndex); currentlistChoices.ensureIndexIsVisible(selectIndex);
} }
} }
this.setVisible(true); this.setVisible(true);
} }
public void setWindowSize(int width, int heigth){ public void setWindowSize(int width, int heigth) {
this.setSize(new Dimension(width, heigth)); this.setSize(new Dimension(width, heigth));
} }
private void loadData(){ private void loadData() {
// load data to datamodel after filter or on startup // load data to datamodel after filter or on startup
String filter = choice.getSearchText(); String filter = choice.getSearchText();
if (filter == null){ filter = ""; } if (filter == null) {
filter = "";
}
filter = filter.toLowerCase(); filter = filter.toLowerCase();
this.dataModel.clear(); this.dataModel.clear();
this.m_dataModel.clear(); this.m_dataModel.clear();
for(KeyValueItem item: this.allItems){ for (KeyValueItem item : this.allItems) {
if(!choice.isSearchEnabled() || item.Value.toLowerCase().contains(filter)){ if (!choice.isSearchEnabled() || item.Value.toLowerCase().contains(filter)) {
this.dataModel.addElement(item); this.dataModel.addElement(item);
this.m_dataModel.addElement(item.getObjectValue()); this.m_dataModel.addElement(item.getObjectValue());
} }
} }
} }
private void setLabelText(JLabel label, String text){ private void setLabelText(JLabel label, String text) {
if ((text != null) && !text.equals("")){ if ((text != null) && !text.equals("")) {
label.setText(String.format(HTML_TEMPLATE, text)); label.setText(String.format(HTML_TEMPLATE, text));
label.setVisible(true); label.setVisible(true);
}else{ } else {
label.setText(""); label.setText("");
label.setVisible(false); label.setVisible(false);
}
}
private void doNextSelect(){
int newSel = this.listChoices.getSelectedIndex() + 1;
int maxSel = this.listChoices.getModel().getSize() - 1;
if(newSel <= maxSel){
this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel);
} }
} }
private void doPrevSelect(){ private void doNextSelect() {
int newSel = this.listChoices.getSelectedIndex() - 1; int newSel = this.listChoices.getSelectedIndex() + 1;
if(newSel >= 0){ int maxSel = this.listChoices.getModel().getSize() - 1;
if (newSel <= maxSel) {
this.listChoices.setSelectedIndex(newSel); this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel); this.listChoices.ensureIndexIsVisible(newSel);
} }
} }
private void doChoose(){ private void doPrevSelect() {
if((tList != null)||(setChoice())){ int newSel = this.listChoices.getSelectedIndex() - 1;
if (newSel >= 0) {
this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel);
}
}
private void doChoose() {
if ((tList != null) || (setChoice())) {
this.m_dataModel.clear(); this.m_dataModel.clear();
restoreData(this.m_dataModel); restoreData(this.m_dataModel);
this.hideDialog(); this.hideDialog();
} }
} }
private void doCancel(){ private void doCancel() {
this.listChoices.clearSelection(); this.listChoices.clearSelection();
this.choice.clearChoice(); this.choice.clearChoice();
hideDialog(); hideDialog();
@ -309,91 +286,93 @@ public class PickCheckBoxDialog extends MageDialog {
/** /**
* Creates new form PickChoiceDialog * Creates new form PickChoiceDialog
* @param list *
* @param list
*/ */
public PickCheckBoxDialog(CheckBoxList list) { public PickCheckBoxDialog(CheckBoxList list) {
initComponents(); initComponents();
tList=list; tList = list;
this.listChoices.setModel(dataModel); this.listChoices.setModel(dataModel);
this.setModal(true); this.setModal(true);
if(tList != null) if (tList != null) {
{
this.listChoices.setVisible(false); this.listChoices.setVisible(false);
m_dataModel= ( CheckBoxList.CheckBoxListModel )tList.getModel(); m_dataModel = (CheckBoxList.CheckBoxListModel) tList.getModel();
tList.setSelectionForeground(Color.BLUE); tList.setSelectionForeground(Color.BLUE);
if(this.tList instanceof javax.swing.JList){ if (this.tList instanceof javax.swing.JList) {
setFocus(tList); setFocus(tList);
} }
} }
} }
/** /**
* Creates new form PickChoiceDialog * Creates new form PickChoiceDialog
*/ */
public PickCheckBoxDialog() { public PickCheckBoxDialog() {
this(null); this(null);
} }
public boolean setChoice() { public boolean setChoice() {
KeyValueItem item = (KeyValueItem)this.listChoices.getSelectedValue(); KeyValueItem item = (KeyValueItem) this.listChoices.getSelectedValue();
// auto select one item (after incemental filtering) // auto select one item (after incemental filtering)
if((item == null) && (this.listChoices.getModel().getSize() == 1)){ if ((item == null) && (this.listChoices.getModel().getSize() == 1)) {
this.listChoices.setSelectedIndex(0); this.listChoices.setSelectedIndex(0);
item = (KeyValueItem)this.listChoices.getSelectedValue(); item = (KeyValueItem) this.listChoices.getSelectedValue();
} }
if(item != null){ if (item != null) {
if(choice.isKeyChoice()){ if (choice.isKeyChoice()) {
choice.setChoiceByKey(item.getKey()); choice.setChoiceByKey(item.getKey());
}else{ } else {
choice.setChoice(item.getKey()); choice.setChoice(item.getKey());
} }
return true; return true;
}else{ } else {
choice.clearChoice(); choice.clearChoice();
return false; return false;
} }
} }
class KeyValueItem class KeyValueItem {
{
private final String Key; private final String Key;
private final String Value; private final String Value;
private final CheckBoxList.CheckBoxListItem objectValue; private final CheckBoxList.CheckBoxListItem objectValue;
public KeyValueItem(String value) { public KeyValueItem(String value) {
this(value,null,null); this(value, null, null);
}
public KeyValueItem(String value, String label) {
this(value,label,null);
} }
public KeyValueItem(String value, String label,CheckBoxList.CheckBoxListItem object) {
public KeyValueItem(String value, String label) {
this(value, label, null);
}
public KeyValueItem(String value, String label, CheckBoxList.CheckBoxListItem object) {
this.Key = value; this.Key = value;
this.Value = label; this.Value = label;
this.objectValue = object; this.objectValue = object;
} }
public String getKey() { public String getKey() {
return this.Key; return this.Key;
} }
public String getValue() { public String getValue() {
return this.Value; return this.Value;
} }
public Object getObjectValue(){ public Object getObjectValue() {
return (CheckBoxList.CheckBoxListItem)this.objectValue; return (CheckBoxList.CheckBoxListItem) this.objectValue;
} }
@Override @Override
public String toString() { public String toString() {
return this.Value; return this.Value;
} }
} }
/** /**
@ -428,20 +407,20 @@ public class PickCheckBoxDialog extends MageDialog {
javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader); javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader);
panelHeader.setLayout(panelHeaderLayout); panelHeader.setLayout(panelHeaderLayout);
panelHeaderLayout.setHorizontalGroup( panelHeaderLayout.setHorizontalGroup(
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelHeaderLayout.createSequentialGroup() .addGroup(panelHeaderLayout.createSequentialGroup()
.addGroup(panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addComponent(labelMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING)) .addComponent(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING))
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelHeaderLayout.setVerticalGroup( panelHeaderLayout.setVerticalGroup(
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelHeaderLayout.createSequentialGroup() .addGroup(panelHeaderLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addComponent(labelMessage) .addComponent(labelMessage)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelSubMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE)) .addComponent(labelSubMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))
); );
labelSearch.setText("Search:"); labelSearch.setText("Search:");
@ -451,28 +430,34 @@ public class PickCheckBoxDialog extends MageDialog {
javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch); javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch);
panelSearch.setLayout(panelSearchLayout); panelSearch.setLayout(panelSearchLayout);
panelSearchLayout.setHorizontalGroup( panelSearchLayout.setHorizontalGroup(
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSearchLayout.createSequentialGroup() .addGroup(panelSearchLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(labelSearch) .addComponent(labelSearch)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editSearch) .addComponent(editSearch)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelSearchLayout.setVerticalGroup( panelSearchLayout.setVerticalGroup(
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSearchLayout.createSequentialGroup() .addGroup(panelSearchLayout.createSequentialGroup()
.addGap(3, 3, 3) .addGap(3, 3, 3)
.addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSearch) .addComponent(labelSearch)
.addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3)) .addGap(3, 3, 3))
); );
listChoices.setModel(new javax.swing.AbstractListModel() { listChoices.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "item1", "item2", "item3" }; String[] strings = {"item1", "item2", "item3"};
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; } public int getSize() {
return strings.length;
}
public Object getElementAt(int i) {
return strings[i];
}
}); });
scrollList.setViewportView(listChoices); scrollList.setViewportView(listChoices);
@ -501,25 +486,25 @@ public class PickCheckBoxDialog extends MageDialog {
javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands); javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands);
panelCommands.setLayout(panelCommandsLayout); panelCommands.setLayout(panelCommandsLayout);
panelCommandsLayout.setHorizontalGroup( panelCommandsLayout.setHorizontalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btClear, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btClear, 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(btOK) .addComponent(btOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
panelCommandsLayout.setVerticalGroup( panelCommandsLayout.setVerticalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btCancel) .addComponent(btCancel)
.addComponent(btOK) .addComponent(btOK)
.addComponent(btClear, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(btClear, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap()) .addContainerGap())
); );
getRootPane().setDefaultButton(btOK); getRootPane().setDefaultButton(btOK);
@ -528,28 +513,28 @@ public class PickCheckBoxDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(panelHeader, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelHeader, 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(panelSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelSearch, 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(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) .addComponent(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
pack(); pack();

View file

@ -1,36 +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 mage.client.dialog; package mage.client.dialog;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.DefaultListModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.KeyStroke;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import mage.choices.Choice; import mage.choices.Choice;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.util.SettingsManager;
import mage.client.util.gui.GuiDisplayUtil;
import mage.client.util.gui.MageDialogState; import mage.client.util.gui.MageDialogState;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/** /**
*
* @author JayDi85 * @author JayDi85
*/ */
@ -39,7 +20,7 @@ public class PickChoiceDialog extends MageDialog {
Choice choice; Choice choice;
ArrayList<KeyValueItem> allItems = new ArrayList<>(); ArrayList<KeyValueItem> allItems = new ArrayList<>();
DefaultListModel<KeyValueItem> dataModel = new DefaultListModel(); DefaultListModel<KeyValueItem> dataModel = new DefaultListModel();
final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>"; final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
public void showDialog(Choice choice) { public void showDialog(Choice choice) {
@ -53,31 +34,31 @@ public class PickChoiceDialog extends MageDialog {
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) { public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) {
showDialog(choice, objectId, mageDialogState, null); showDialog(choice, objectId, mageDialogState, null);
} }
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) { public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) {
this.choice = choice; this.choice = choice;
setLabelText(this.labelMessage, choice.getMessage()); setLabelText(this.labelMessage, choice.getMessage());
setLabelText(this.labelSubMessage, choice.getSubMessage()); setLabelText(this.labelSubMessage, choice.getSubMessage());
btCancel.setEnabled(!choice.isRequired()); btCancel.setEnabled(!choice.isRequired());
// 2 modes: string or key-values // 2 modes: string or key-values
// sore data in allItems for inremental filtering // sore data in allItems for inremental filtering
// http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/ // http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/
this.allItems.clear(); this.allItems.clear();
if (choice.isKeyChoice()){ if (choice.isKeyChoice()) {
for (Map.Entry<String, String> entry: choice.getKeyChoices().entrySet()) { for (Map.Entry<String, String> entry : choice.getKeyChoices().entrySet()) {
this.allItems.add(new KeyValueItem(entry.getKey(), entry.getValue())); this.allItems.add(new KeyValueItem(entry.getKey(), entry.getValue()));
} }
} else { } else {
for (String value: choice.getChoices()){ for (String value : choice.getChoices()) {
this.allItems.add(new KeyValueItem(value, value)); this.allItems.add(new KeyValueItem(value, value));
} }
} }
// sorting // sorting
if(choice.isSortEnabled()){ if (choice.isSortEnabled()) {
Collections.sort(this.allItems, new Comparator<KeyValueItem>() { Collections.sort(this.allItems, new Comparator<KeyValueItem>() {
@Override @Override
public int compare(KeyValueItem o1, KeyValueItem o2) { public int compare(KeyValueItem o1, KeyValueItem o2) {
@ -87,38 +68,37 @@ public class PickChoiceDialog extends MageDialog {
} }
}); });
} }
// search // search
if(choice.isSearchEnabled()) if (choice.isSearchEnabled()) {
{
panelSearch.setVisible(true); panelSearch.setVisible(true);
this.editSearch.setText(choice.getSearchText()); this.editSearch.setText(choice.getSearchText());
}else{ } else {
panelSearch.setVisible(false); panelSearch.setVisible(false);
this.editSearch.setText(""); this.editSearch.setText("");
} }
// listeners for inremental filtering // listeners for inremental filtering
editSearch.getDocument().addDocumentListener(new DocumentListener() { editSearch.getDocument().addDocumentListener(new DocumentListener() {
@Override @Override
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
@Override @Override
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
@Override @Override
public void changedUpdate(DocumentEvent e) { public void changedUpdate(DocumentEvent e) {
choice.setSearchText(editSearch.getText()); choice.setSearchText(editSearch.getText());
loadData(); loadData();
} }
}); });
// listeners for select up and down without edit focus lost // listeners for select up and down without edit focus lost
editSearch.addKeyListener(new KeyListener() { editSearch.addKeyListener(new KeyListener() {
@Override @Override
@ -127,10 +107,10 @@ public class PickChoiceDialog extends MageDialog {
} }
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){ if (e.getKeyCode() == KeyEvent.VK_UP) {
doPrevSelect(); doPrevSelect();
}else if(e.getKeyCode() == KeyEvent.VK_DOWN){ } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
doNextSelect(); doNextSelect();
} }
} }
@ -140,19 +120,19 @@ public class PickChoiceDialog extends MageDialog {
//System.out.println("released"); //System.out.println("released");
} }
}); });
// listeners double click choose // listeners double click choose
listChoices.addMouseListener(new MouseAdapter() { listChoices.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2){ if (e.getClickCount() == 2) {
doChoose(); doChoose();
} }
} }
}); });
// listeners for ESC close // listeners for ESC close
if(!choice.isRequired()){ if (!choice.isRequired()) {
String cancelName = "cancel"; String cancelName = "cancel";
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
@ -163,37 +143,35 @@ public class PickChoiceDialog extends MageDialog {
} }
}); });
} }
// window settings // window settings
if (this.isModal()){ if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
}else{ } else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
} }
if (mageDialogState != null) { if (mageDialogState != null) {
mageDialogState.setStateToDialog(this); mageDialogState.setStateToDialog(this);
} else { } else {
Point centered = SettingsManager.instance.getComponentPosition(getWidth(), getHeight()); this.makeWindowCentered();
this.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
} }
// final load // final load
loadData(); loadData();
// start selection // start selection
if((startSelectionValue != null)){ if ((startSelectionValue != null)) {
int selectIndex = -1; int selectIndex = -1;
for(int i = 0; i < this.listChoices.getModel().getSize(); i++){ for (int i = 0; i < this.listChoices.getModel().getSize(); i++) {
KeyValueItem listItem = (KeyValueItem)this.listChoices.getModel().getElementAt(i); KeyValueItem listItem = (KeyValueItem) this.listChoices.getModel().getElementAt(i);
if (listItem.Key.equals(startSelectionValue)){ if (listItem.Key.equals(startSelectionValue)) {
selectIndex = i; selectIndex = i;
break; break;
} }
} }
if(selectIndex >= 0){ if (selectIndex >= 0) {
this.listChoices.setSelectedIndex(selectIndex); this.listChoices.setSelectedIndex(selectIndex);
this.listChoices.ensureIndexIsVisible(selectIndex); this.listChoices.ensureIndexIsVisible(selectIndex);
} }
@ -201,59 +179,61 @@ public class PickChoiceDialog extends MageDialog {
this.setVisible(true); this.setVisible(true);
} }
public void setWindowSize(int width, int heigth){ public void setWindowSize(int width, int height) {
this.setSize(new Dimension(width, heigth)); this.setSize(new Dimension(width, height));
} }
private void loadData(){ private void loadData() {
// load data to datamodel after filter or on startup // load data to datamodel after filter or on startup
String filter = choice.getSearchText(); String filter = choice.getSearchText();
if (filter == null){ filter = ""; } if (filter == null) {
filter = "";
}
filter = filter.toLowerCase(Locale.ENGLISH); filter = filter.toLowerCase(Locale.ENGLISH);
this.dataModel.clear(); this.dataModel.clear();
for(KeyValueItem item: this.allItems){ for (KeyValueItem item : this.allItems) {
if(!choice.isSearchEnabled() || item.Value.toLowerCase(Locale.ENGLISH).contains(filter)){ if (!choice.isSearchEnabled() || item.Value.toLowerCase(Locale.ENGLISH).contains(filter)) {
this.dataModel.addElement(item); this.dataModel.addElement(item);
} }
} }
} }
private void setLabelText(JLabel label, String text){ private void setLabelText(JLabel label, String text) {
if ((text != null) && !text.equals("")){ if ((text != null) && !text.equals("")) {
label.setText(String.format(HTML_TEMPLATE, text)); label.setText(String.format(HTML_TEMPLATE, text));
label.setVisible(true); label.setVisible(true);
}else{ } else {
label.setText(""); label.setText("");
label.setVisible(false); label.setVisible(false);
}
}
private void doNextSelect(){
int newSel = this.listChoices.getSelectedIndex() + 1;
int maxSel = this.listChoices.getModel().getSize() - 1;
if(newSel <= maxSel){
this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel);
} }
} }
private void doPrevSelect(){ private void doNextSelect() {
int newSel = this.listChoices.getSelectedIndex() - 1; int newSel = this.listChoices.getSelectedIndex() + 1;
if(newSel >= 0){ int maxSel = this.listChoices.getModel().getSize() - 1;
if (newSel <= maxSel) {
this.listChoices.setSelectedIndex(newSel); this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel); this.listChoices.ensureIndexIsVisible(newSel);
} }
} }
private void doChoose(){ private void doPrevSelect() {
if(setChoice()){ int newSel = this.listChoices.getSelectedIndex() - 1;
if (newSel >= 0) {
this.listChoices.setSelectedIndex(newSel);
this.listChoices.ensureIndexIsVisible(newSel);
}
}
private void doChoose() {
if (setChoice()) {
this.hideDialog(); this.hideDialog();
} }
} }
private void doCancel(){ private void doCancel() {
this.listChoices.clearSelection(); this.listChoices.clearSelection();
this.choice.clearChoice(); this.choice.clearChoice();
hideDialog(); hideDialog();
@ -267,34 +247,33 @@ public class PickChoiceDialog extends MageDialog {
this.listChoices.setModel(dataModel); this.listChoices.setModel(dataModel);
this.setModal(true); this.setModal(true);
} }
public boolean setChoice() { public boolean setChoice() {
KeyValueItem item = (KeyValueItem)this.listChoices.getSelectedValue(); KeyValueItem item = (KeyValueItem) this.listChoices.getSelectedValue();
// auto select one item (after incemental filtering) // auto select one item (after incemental filtering)
if((item == null) && (this.listChoices.getModel().getSize() == 1)){ if ((item == null) && (this.listChoices.getModel().getSize() == 1)) {
this.listChoices.setSelectedIndex(0); this.listChoices.setSelectedIndex(0);
item = (KeyValueItem)this.listChoices.getSelectedValue(); item = (KeyValueItem) this.listChoices.getSelectedValue();
} }
if(item != null){ if (item != null) {
if(choice.isKeyChoice()){ if (choice.isKeyChoice()) {
choice.setChoiceByKey(item.getKey()); choice.setChoiceByKey(item.getKey());
}else{ } else {
choice.setChoice(item.getKey()); choice.setChoice(item.getKey());
} }
return true; return true;
}else{ } else {
choice.clearChoice(); choice.clearChoice();
return false; return false;
} }
} }
class KeyValueItem class KeyValueItem {
{
private final String Key; private final String Key;
private final String Value; private final String Value;
public KeyValueItem(String value, String label) { public KeyValueItem(String value, String label) {
this.Key = value; this.Key = value;
this.Value = label; this.Value = label;
@ -311,7 +290,7 @@ public class PickChoiceDialog extends MageDialog {
@Override @Override
public String toString() { public String toString() {
return this.Value; return this.Value;
} }
} }
/** /**
@ -345,20 +324,20 @@ public class PickChoiceDialog extends MageDialog {
javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader); javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader);
panelHeader.setLayout(panelHeaderLayout); panelHeader.setLayout(panelHeaderLayout);
panelHeaderLayout.setHorizontalGroup( panelHeaderLayout.setHorizontalGroup(
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelHeaderLayout.createSequentialGroup() .addGroup(panelHeaderLayout.createSequentialGroup()
.addGroup(panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE) .addComponent(labelMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)
.addComponent(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)) .addComponent(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE))
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelHeaderLayout.setVerticalGroup( panelHeaderLayout.setVerticalGroup(
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelHeaderLayout.createSequentialGroup() .addGroup(panelHeaderLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(labelMessage) .addComponent(labelMessage)
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(labelSubMessage)) .addComponent(labelSubMessage))
); );
labelSearch.setText("Search:"); labelSearch.setText("Search:");
@ -368,28 +347,34 @@ public class PickChoiceDialog extends MageDialog {
javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch); javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch);
panelSearch.setLayout(panelSearchLayout); panelSearch.setLayout(panelSearchLayout);
panelSearchLayout.setHorizontalGroup( panelSearchLayout.setHorizontalGroup(
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSearchLayout.createSequentialGroup() .addGroup(panelSearchLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(labelSearch) .addComponent(labelSearch)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editSearch) .addComponent(editSearch)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelSearchLayout.setVerticalGroup( panelSearchLayout.setVerticalGroup(
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSearchLayout.createSequentialGroup() .addGroup(panelSearchLayout.createSequentialGroup()
.addGap(3, 3, 3) .addGap(3, 3, 3)
.addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(labelSearch) .addComponent(labelSearch)
.addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3)) .addGap(3, 3, 3))
); );
listChoices.setModel(new javax.swing.AbstractListModel() { listChoices.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "item1", "item2", "item3" }; String[] strings = {"item1", "item2", "item3"};
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; } public int getSize() {
return strings.length;
}
public Object getElementAt(int i) {
return strings[i];
}
}); });
scrollList.setViewportView(listChoices); scrollList.setViewportView(listChoices);
@ -410,25 +395,25 @@ public class PickChoiceDialog extends MageDialog {
javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands); javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands);
panelCommands.setLayout(panelCommandsLayout); panelCommands.setLayout(panelCommandsLayout);
panelCommandsLayout.setHorizontalGroup( panelCommandsLayout.setHorizontalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btOK) .addComponent(btOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btCancel, btOK}); panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[]{btCancel, btOK});
panelCommandsLayout.setVerticalGroup( panelCommandsLayout.setVerticalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btCancel) .addComponent(btCancel)
.addComponent(btOK)) .addComponent(btOK))
.addContainerGap()) .addContainerGap())
); );
getRootPane().setDefaultButton(btOK); getRootPane().setDefaultButton(btOK);
@ -436,28 +421,28 @@ public class PickChoiceDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(panelHeader, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelHeader, 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(panelSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelSearch, 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(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE) .addComponent(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
pack(); pack();

View file

@ -1,31 +1,21 @@
/*
* PickNumberDialog.java
*
* Created on Feb 25, 2010, 12:03:39 PM
*/
package mage.client.dialog; package mage.client.dialog;
import java.awt.Point; import mage.client.MageFrame;
import javax.swing.*;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.KeyListener; import java.awt.event.KeyListener;
import javax.swing.*;
import mage.client.MageFrame;
import mage.client.util.SettingsManager;
import mage.client.util.gui.GuiDisplayUtil;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class PickNumberDialog extends MageDialog { public class PickNumberDialog extends MageDialog {
private boolean cancel; private boolean cancel;
/** Creates new form PickNumberDialog */ /**
* Creates new form PickNumberDialog
*/
public PickNumberDialog() { public PickNumberDialog() {
initComponents(); initComponents();
this.setModal(true); this.setModal(true);
@ -40,16 +30,16 @@ public class PickNumberDialog extends MageDialog {
this.pack(); this.pack();
// window settings // window settings
if (this.isModal()){ if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
}else{ } else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
} }
this.getRootPane().setDefaultButton(this.btnOk); // restore default button after root panel change (no need actually) this.getRootPane().setDefaultButton(this.btnOk); // restore default button after root panel change (no need actually)
// enable spinner's enter key like text (one enter press instead two) // enable spinner's enter key like text (one enter press instead two)
// https://stackoverflow.com/questions/3873870/java-keylistener-not-firing-on-jspinner // https://stackoverflow.com/questions/3873870/java-keylistener-not-firing-on-jspinner
((JSpinner.DefaultEditor)this.spnAmount.getEditor()).getTextField().addKeyListener(new KeyListener(){ ((JSpinner.DefaultEditor) this.spnAmount.getEditor()).getTextField().addKeyListener(new KeyListener() {
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
@ -68,23 +58,22 @@ public class PickNumberDialog extends MageDialog {
}); });
Point centered = SettingsManager.instance.getComponentPosition(getWidth(), getHeight()); this.makeWindowCentered();
this.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
// TODO: need to fix focus restore on second popup (it's not focues, test on Manamorphose) // TODO: need to fix focus restore on second popup (it's not focues, test on Manamorphose)
this.setVisible(true); this.setVisible(true);
} }
public int getAmount() { public int getAmount() {
return ((Number)spnAmount.getValue()).intValue(); return ((Number) spnAmount.getValue()).intValue();
} }
public boolean isCancel() { public boolean isCancel() {
return cancel; return cancel;
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -105,7 +94,7 @@ public class PickNumberDialog extends MageDialog {
lblMessage.setEditable(false); lblMessage.setEditable(false);
lblMessage.setText("long text long text long text long text long text long text long text long text"); lblMessage.setText("long text long text long text long text long text long text long text long text");
lblMessage.setCursor(null ); lblMessage.setCursor(null);
lblMessage.setFocusable(false); lblMessage.setFocusable(false);
lblMessage.setOpaque(false); lblMessage.setOpaque(false);
jScrollPane1.setViewportView(lblMessage); jScrollPane1.setViewportView(lblMessage);
@ -129,22 +118,22 @@ public class PickNumberDialog extends MageDialog {
javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands); javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands);
panelCommands.setLayout(panelCommandsLayout); panelCommands.setLayout(panelCommandsLayout);
panelCommandsLayout.setHorizontalGroup( panelCommandsLayout.setHorizontalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnOk) .addComponent(btnOk)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel) .addComponent(btnCancel)
.addContainerGap()) .addContainerGap())
); );
panelCommandsLayout.setVerticalGroup( panelCommandsLayout.setVerticalGroup(
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelCommandsLayout.createSequentialGroup() .addGroup(panelCommandsLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnOk) .addComponent(btnOk)
.addComponent(btnCancel)) .addComponent(btnCancel))
.addContainerGap()) .addContainerGap())
); );
getRootPane().setDefaultButton(btnOk); getRootPane().setDefaultButton(btnOk);
@ -152,27 +141,27 @@ public class PickNumberDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE)
.addComponent(panelCommands, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelCommands, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
pack(); pack();

View file

@ -1,23 +1,16 @@
package mage.client.dialog; package mage.client.dialog;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Point;
import java.util.UUID;
import javax.swing.JButton;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.cards.CardArea; import mage.client.cards.CardArea;
import mage.client.util.SettingsManager;
import mage.client.util.gui.GuiDisplayUtil;
import mage.view.CardsView; import mage.view.CardsView;
import org.mage.card.arcane.CardPanel; import org.mage.card.arcane.CardPanel;
import javax.swing.*;
import java.awt.*;
import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class PickPileDialog extends MageDialog { public class PickPileDialog extends MageDialog {
@ -81,18 +74,16 @@ public class PickPileDialog extends MageDialog {
} }
pack(); pack();
Point centered = SettingsManager.instance.getComponentPosition(getWidth(), getHeight()); this.makeWindowCentered();
this.setLocation(centered.x, centered.y);
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
this.setModal(true); this.setModal(true);
// window settings // window settings
if (this.isModal()){ if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
}else{ } else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
} }

View file

@ -236,7 +236,7 @@
<Property name="toolTipText" type="java.lang.String" value="Write the card&apos;s name on the card to make the card name more recognizable."/> <Property name="toolTipText" type="java.lang.String" value="Write the card&apos;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>
@ -267,7 +267,7 @@
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
<Property name="toolTipText" type="java.lang.String" value="Show the path Xmage is expecting for this card&apos;s image (only displays if missing)"/> <Property name="toolTipText" type="java.lang.String" value="Show the path Xmage is expecting for this card&apos;s image (only displays if missing)"/>
<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>
<Property name="label" type="java.lang.String" value="Display image path for missing images"/> <Property name="label" type="java.lang.String" value="Display image path for missing images"/>
</Properties> </Properties>
@ -4425,6 +4425,7 @@
</Component> </Component>
<Component class="javax.swing.JComboBox" name="cbPreferedImageLanguage"> <Component class="javax.swing.JComboBox" name="cbPreferedImageLanguage">
<Properties> <Properties>
<Property name="maximumRowCount" type="int" value="20"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4"> <StringArray count="4">
<StringItem index="0" value="Item 1"/> <StringItem index="0" value="Item 1"/>
@ -4451,6 +4452,7 @@
</Component> </Component>
<Component class="javax.swing.JComboBox" name="cbNumberOfDownloadThreads"> <Component class="javax.swing.JComboBox" name="cbNumberOfDownloadThreads">
<Properties> <Properties>
<Property name="maximumRowCount" type="int" value="20"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4"> <StringArray count="4">
<StringItem index="0" value="Item 1"/> <StringItem index="0" value="Item 1"/>

View file

@ -41,6 +41,8 @@ import mage.client.MageFrame;
import mage.client.SessionHandler; import mage.client.SessionHandler;
import mage.client.components.KeyBindButton; import mage.client.components.KeyBindButton;
import static mage.client.constants.Constants.BATTLEFIELD_FEEDBACK_COLORIZING_MODE_ENABLE_BY_MULTICOLOR; import static mage.client.constants.Constants.BATTLEFIELD_FEEDBACK_COLORIZING_MODE_ENABLE_BY_MULTICOLOR;
import mage.client.util.CardLanguage;
import mage.client.util.Config; import mage.client.util.Config;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
@ -338,6 +340,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
fc_i.addChoosableFileFilter(new ImageFileFilter()); fc_i.addChoosableFileFilter(new ImageFileFilter());
} }
public static CardLanguage getPrefImagesLanguage() {
return CardLanguage.valueByCode(getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, CardLanguage.ENGLISH.getCode()));
}
private static class ImageFileFilter extends FileFilter { private static class ImageFileFilter extends FileFilter {
@Override @Override
@ -374,7 +380,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
cbProxyType.setModel(new DefaultComboBoxModel<>(Connection.ProxyType.values())); cbProxyType.setModel(new DefaultComboBoxModel<>(Connection.ProxyType.values()));
addAvatars(); addAvatars();
cbPreferedImageLanguage.setModel(new DefaultComboBoxModel<>(new String[]{"en", "de", "fr", "it", "es", "pt", "jp", "cn", "ru", "tw", "ko"})); cbPreferedImageLanguage.setModel(new DefaultComboBoxModel<>(CardLanguage.toList()));
cbNumberOfDownloadThreads.setModel(new DefaultComboBoxModel<>(new String[]{"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"})); cbNumberOfDownloadThreads.setModel(new DefaultComboBoxModel<>(new String[]{"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"}));
} }
@ -1558,6 +1564,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
} }
}); });
cbPreferedImageLanguage.setMaximumRowCount(20);
cbPreferedImageLanguage.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); cbPreferedImageLanguage.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
labelPreferedImageLanguage.setText("Prefered image language:"); labelPreferedImageLanguage.setText("Prefered image language:");
@ -1565,6 +1572,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
labelNumberOfDownloadThreads.setText("Number of download threads:"); labelNumberOfDownloadThreads.setText("Number of download threads:");
cbNumberOfDownloadThreads.setMaximumRowCount(20);
cbNumberOfDownloadThreads.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); cbNumberOfDownloadThreads.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
org.jdesktop.layout.GroupLayout panelCardImagesLayout = new org.jdesktop.layout.GroupLayout(panelCardImages); org.jdesktop.layout.GroupLayout panelCardImagesLayout = new org.jdesktop.layout.GroupLayout(panelCardImages);
@ -3411,7 +3419,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
load(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true"); load(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true");
load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true"); load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true");
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, CardLanguage.ENGLISH.getCode()));
// rendering settings // rendering settings
load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true"); load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true");

View file

@ -21,7 +21,6 @@ import mage.client.util.audio.AudioManager;
import mage.client.util.gui.BufferedImageBuilder; import mage.client.util.gui.BufferedImageBuilder;
import mage.constants.PlayerAction; import mage.constants.PlayerAction;
import mage.view.*; import mage.view.*;
import org.apache.log4j.Logger;
import javax.swing.*; import javax.swing.*;
import javax.swing.Timer; import javax.swing.Timer;
@ -31,21 +30,16 @@ import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.List;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class DraftPanel extends javax.swing.JPanel { public class DraftPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logger.getLogger(DraftPanel.class);
private UUID draftId; private UUID draftId;
private Timer countdown; private Timer countdown;
private int timeout; private int timeout;
@ -63,8 +57,11 @@ public class DraftPanel extends javax.swing.JPanel {
// id of card with popup menu // id of card with popup menu
protected UUID cardIdPopupMenu; protected UUID cardIdPopupMenu;
// Filename for the draft log (only updated if writing the log). // Helper for writing the draft log.
private String logFilename; private DraftPickLogger draftLogger;
// List of set codes (for draft log writing).
private List<String> setCodes;
// Number of the current booster (for draft log writing). // Number of the current booster (for draft log writing).
private int packNo; private int packNo;
@ -73,7 +70,6 @@ public class DraftPanel extends javax.swing.JPanel {
private int pickNo; private int pickNo;
// Cached booster data to be written into the log (see logLastPick). // Cached booster data to be written into the log (see logLastPick).
private String currentBoosterHeader;
private String[] currentBooster; private String[] currentBooster;
private static final CardsView EMPTY_VIEW = new CardsView(); private static final CardsView EMPTY_VIEW = new CardsView();
@ -139,17 +135,11 @@ public class DraftPanel extends javax.swing.JPanel {
} }
if (isLogging()) { if (isLogging()) {
// If we are logging the draft create a file that will contain
// the log.
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
logFilename = "Draft_" + sdf.format(new Date()) + '_' + draftId + ".txt"; String logFilename = "Draft_" + sdf.format(new Date()) + '_' + draftId + ".txt";
try { draftLogger = new DraftPickLogger(new File("gamelogs"), logFilename);
Files.write(pathToDraftLog(), "".getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException ex) {
LOGGER.error(null, ex);
}
} else { } else {
logFilename = null; draftLogger = new DraftPickLogger();
} }
} }
@ -171,6 +161,8 @@ public class DraftPanel extends javax.swing.JPanel {
packNo = draftView.getBoosterNum(); packNo = draftView.getBoosterNum();
pickNo = draftView.getCardNum(); pickNo = draftView.getCardNum();
setCodes = draftView.getSetCodes();
draftLogger.updateDraft(draftId, draftView);
int right = draftView.getPlayers().size() / 2; int right = draftView.getPlayers().size() / 2;
int left = draftView.getPlayers().size() - right; int left = draftView.getPlayers().size() - right;
@ -251,7 +243,7 @@ public class DraftPanel extends javax.swing.JPanel {
} }
} }
public void loadBooster(DraftPickView draftPickView) { public void loadBooster(DraftPickView draftPickView) {
logLastPick(draftPickView); logLastPick(draftPickView);
// upper area that shows the picks // upper area that shows the picks
loadCardsToPickedCardsArea(draftPickView.getPicks()); loadCardsToPickedCardsArea(draftPickView.getPicks());
@ -416,13 +408,21 @@ public class DraftPanel extends javax.swing.JPanel {
if (currentBooster != null) { if (currentBooster != null) {
String lastPick = getCardName(getLastPick(pickView.getPicks().values())); String lastPick = getCardName(getLastPick(pickView.getPicks().values()));
if (lastPick != null && currentBooster.length > 1) { if (lastPick != null && currentBooster.length > 1) {
logPick(lastPick); draftLogger.logPick(getCurrentSetCode(), packNo, pickNo-1, lastPick, currentBooster);
} }
currentBooster = null; currentBooster = null;
} }
setCurrentBoosterForLog(pickView.getBooster()); setCurrentBoosterForLog(pickView.getBooster());
if (currentBooster.length == 1) { if (currentBooster.length == 1) {
logPick(currentBooster[0]); draftLogger.logPick(getCurrentSetCode(), packNo, pickNo, currentBooster[0], currentBooster);
}
}
private String getCurrentSetCode() {
if (!setCodes.isEmpty()) {
return setCodes.get(packNo-1);
} else {
return "";
} }
} }
@ -440,39 +440,10 @@ public class DraftPanel extends javax.swing.JPanel {
} }
} }
currentBoosterHeader = "Pack " + packNo + " pick " + pickNo + ":\n";
currentBooster = cards.toArray(new String[cards.size()]); currentBooster = cards.toArray(new String[cards.size()]);
} }
private void logPick(String pick) { private static SimpleCardView getLastPick(Collection<SimpleCardView> picks) {
StringBuilder b = new StringBuilder();
b.append(currentBoosterHeader);
for (String name : currentBooster) {
b.append(pick.equals(name) ? "--> " : " ");
b.append(name);
b.append('\n');
}
b.append('\n');
appendToDraftLog(b.toString());
}
private Path pathToDraftLog() {
File saveDir = new File("gamelogs");
if (!saveDir.exists()) {
saveDir.mkdirs();
}
return new File(saveDir, logFilename).toPath();
}
private void appendToDraftLog(String data) {
try {
Files.write(pathToDraftLog(), data.getBytes(), StandardOpenOption.APPEND);
} catch (IOException ex) {
LOGGER.error(null, ex);
}
}
private static SimpleCardView getLastPick(Collection<SimpleCardView> picks) {
SimpleCardView last = null; SimpleCardView last = null;
for (SimpleCardView pick : picks) { for (SimpleCardView pick : picks) {
last = pick; last = pick;

View file

@ -0,0 +1,85 @@
package mage.client.draft;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import org.apache.log4j.Logger;
import mage.view.DraftView;
public class DraftPickLogger {
private static final Logger LOGGER = Logger.getLogger(DraftPickLogger.class);
private final Path logPath;
private final boolean logging;
private boolean headerWritten = false;
public DraftPickLogger(File directory, String logFilename) {
this.logging = true;
if (!directory.exists()) {
directory.mkdirs();
}
this.logPath = new File(directory, logFilename).toPath();
try {
Files.write(logPath, new byte[0], StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException ex) {
LOGGER.error(null, ex);
}
}
public DraftPickLogger() {
this.logging = false;
this.logPath = null;
}
public void updateDraft(UUID draftId, DraftView draftView) {
if (headerWritten) {
return;
}
headerWritten = true;
Date now = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("M/d/yyyy h:mm:ss a");
StringBuilder buffer = new StringBuilder()
.append("Event #: ").append(draftId).append("\n")
.append("Time: ").append(formatter.format(now)).append('\n');
buffer.append("Players:\n");
for (String player : draftView.getPlayers()) {
buffer.append(" ").append(player).append('\n');
}
buffer.append('\n');
appendToDraftLog(buffer.toString());
}
public void logPick(String setCode, int packNo, int pickNo, String pick, String[] currentBooster) {
StringBuilder b = new StringBuilder();
if (pickNo == 1) {
b.append("------ ").append(setCode).append(" ------\n\n");
}
b.append("Pack ").append(packNo).append(" pick ").append(pickNo).append(":\n");
for (String name : currentBooster) {
b.append(pick.equals(name) ? "--> " : " ");
b.append(name);
b.append('\n');
}
b.append('\n');
appendToDraftLog(b.toString());
}
private void appendToDraftLog(String data) {
if (logging) {
try {
Files.write(logPath, data.getBytes(), StandardOpenOption.APPEND);
} catch (IOException ex) {
LOGGER.error(null, ex);
}
}
}
}

View file

@ -353,8 +353,9 @@ public class CallbackClientImpl implements CallbackClient {
} }
case DRAFT_UPDATE: { case DRAFT_UPDATE: {
DraftPanel panel = MageFrame.getDraft(callback.getObjectId()); DraftPanel panel = MageFrame.getDraft(callback.getObjectId());
DraftClientMessage message = (DraftClientMessage) callback.getData();
if (panel != null) { if (panel != null) {
panel.updateDraft((DraftView) callback.getData()); panel.updateDraft(message.getDraftView());
} }
break; break;
} }

View file

@ -0,0 +1,145 @@
package mage.client.table;
import mage.remote.MageRemoteException;
import mage.view.MatchView;
import javax.swing.table.AbstractTableModel;
import java.util.Collection;
import java.util.Date;
import java.util.UUID;
public class MatchesTableModel extends AbstractTableModel {
private final String[] columnNames = new String[]{"Deck Type", "Players", "Game Type", "Rating", "Result", "Duration", "Start Time", "End Time", "Action"};
public static final int COLUMN_DURATION = 5;
public static final int COLUMN_START = 6;
public static final int COLUMN_END = 7;
public static final int COLUMN_ACTION = 8; // column the action is located (starting with 0)
private MatchView[] matches = new MatchView[0];
public void loadData(Collection<MatchView> matches) throws MageRemoteException {
this.matches = matches.toArray(new MatchView[0]);
this.fireTableDataChanged();
}
MatchesTableModel() {
}
public String getTableAndGameInfo(int row) {
return this.matches[row].getTableId().toString() + ";" + (!matches[row].getGames().isEmpty() ? matches[row].getGames().get(0).toString() : "null");
}
public String findTableAndGameInfoByRow(int row) {
if (row >= 0 && row < this.matches.length) {
return getTableAndGameInfo(row);
} else {
return null;
}
}
public int findRowByTableAndGameInfo(String tableAndGame) {
for (int i = 0; i < this.matches.length; i++) {
String rowID = this.matches[i].getTableId().toString() + ";" + (!this.matches[i].getGames().isEmpty() ? this.matches[i].getGames().get(0).toString() : "null");
if (tableAndGame.equals(rowID)) {
return i;
}
}
return -1;
}
@Override
public int getRowCount() {
return matches.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return matches[arg0].getDeckType();
case 1:
return matches[arg0].getPlayers();
case 2:
return matches[arg0].getGameType();
case 3:
return matches[arg0].isRated() ? TablesTableModel.RATED_VALUE_YES : TablesTableModel.RATED_VALUE_NO;
case 4:
return matches[arg0].getResult();
case 5:
if (matches[arg0].getEndTime() != null) {
return matches[arg0].getEndTime().getTime() - matches[arg0].getStartTime().getTime() + new Date().getTime();
} else {
return 0L;
}
case 6:
return matches[arg0].getStartTime();
case 7:
return matches[arg0].getEndTime();
case 8:
if (matches[arg0].isTournament()) {
return "Show";
} else if (matches[arg0].isReplayAvailable()) {
return "Replay";
} else {
return "None";
}
case 9:
return matches[arg0].getGames();
}
return "";
}
public java.util.List<UUID> getListofGames(int row) {
return matches[row].getGames();
}
public boolean isTournament(int row) {
return matches[row].isTournament();
}
public UUID getMatchId(int row) {
return matches[row].getMatchId();
}
public UUID getTableId(int row) {
return matches[row].getTableId();
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case COLUMN_DURATION:
return Long.class;
case COLUMN_START:
return Date.class;
case COLUMN_END:
return Date.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == COLUMN_ACTION;
}
}

View file

@ -1,25 +1,21 @@
package mage.client.table;
package mage.client.util; import mage.client.util.GUISizeHelper;
import java.awt.Component; import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener { public class TablesButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener {
private final JTable table; private final JTable table;
private final Action action; private final Action action;
@ -28,7 +24,7 @@ public class ButtonColumn extends AbstractCellEditor implements TableCellRendere
private String text; private String text;
private boolean isButtonColumnEditor; private boolean isButtonColumnEditor;
public ButtonColumn(JTable table, Action action, int column) { public TablesButtonColumn(JTable table, Action action, int column) {
super(); super();
this.table = table; this.table = table;
this.action = action; this.action = action;
@ -88,7 +84,7 @@ public class ButtonColumn extends AbstractCellEditor implements TableCellRendere
if (table.getRowCount() > 0 && table.getRowCount() >= table.getEditingRow() && table.getEditingRow() >= 0) { if (table.getRowCount() > 0 && table.getRowCount() >= table.getEditingRow() && table.getEditingRow() >= 0) {
int row = table.convertRowIndexToModel(table.getEditingRow()); int row = table.convertRowIndexToModel(table.getEditingRow());
fireEditingStopped(); fireEditingStopped();
ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, String.valueOf(row)); ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, TablesUtil.getSearchIdFromTable(table, row));
action.actionPerformed(event); action.actionPerformed(event);
} }
} }

View file

@ -6,7 +6,10 @@ import mage.client.SessionHandler;
import mage.client.chat.ChatPanelBasic; import mage.client.chat.ChatPanelBasic;
import mage.client.components.MageComponents; import mage.client.components.MageComponents;
import mage.client.dialog.*; import mage.client.dialog.*;
import mage.client.util.*; import mage.client.util.GUISizeHelper;
import mage.client.util.IgnoreList;
import mage.client.util.MageTableRowSorter;
import mage.client.util.URLHandler;
import mage.client.util.gui.GuiDisplayUtil; import mage.client.util.gui.GuiDisplayUtil;
import mage.client.util.gui.TableUtil; import mage.client.util.gui.TableUtil;
import mage.constants.*; import mage.constants.*;
@ -25,7 +28,6 @@ import org.ocpsoft.prettytime.units.JustNow;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import java.awt.*; import java.awt.*;
@ -52,7 +54,7 @@ public class TablesPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logger.getLogger(TablesPanel.class); private static final Logger LOGGER = Logger.getLogger(TablesPanel.class);
private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60}; private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60};
private final TableTableModel tableModel; private final TablesTableModel tableModel;
private final MatchesTableModel matchesModel; private final MatchesTableModel matchesModel;
private UUID roomId; private UUID roomId;
private UpdateTablesTask updateTablesTask; private UpdateTablesTask updateTablesTask;
@ -67,8 +69,8 @@ public class TablesPanel extends javax.swing.JPanel {
private final MageTableRowSorter activeTablesSorter; private final MageTableRowSorter activeTablesSorter;
private final MageTableRowSorter completedTablesSorter; private final MageTableRowSorter completedTablesSorter;
private final ButtonColumn actionButton1; private final TablesButtonColumn actionButton1;
private final ButtonColumn actionButton2; private final TablesButtonColumn actionButton2;
final JToggleButton[] filterButtons; final JToggleButton[] filterButtons;
@ -161,7 +163,7 @@ public class TablesPanel extends javax.swing.JPanel {
*/ */
public TablesPanel() { public TablesPanel() {
tableModel = new TableTableModel(); tableModel = new TablesTableModel();
matchesModel = new MatchesTableModel(); matchesModel = new MatchesTableModel();
gameChooser = new GameChooser(); gameChooser = new GameChooser();
@ -179,12 +181,12 @@ public class TablesPanel extends javax.swing.JPanel {
tableTables.setRowSorter(activeTablesSorter); tableTables.setRowSorter(activeTablesSorter);
// time ago // time ago
tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer); tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer);
// skill level // skill level
tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer); tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer);
/* date sorter (not need, default is good - see getColumnClass) /* date sorter (not need, default is good - see getColumnClass)
activeTablesSorter.setComparator(TableTableModel.COLUMN_CREATED, new Comparator<Date>() { activeTablesSorter.setComparator(TablesTableModel.COLUMN_CREATED, new Comparator<Date>() {
@Override @Override
public int compare(Date v1, Date v2) { public int compare(Date v1, Date v2) {
return v1.compareTo(v2); return v1.compareTo(v2);
@ -194,7 +196,7 @@ public class TablesPanel extends javax.swing.JPanel {
// default sort by created date (last games from above) // default sort by created date (last games from above)
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
list.add(new RowSorter.SortKey(TableTableModel.COLUMN_CREATED, SortOrder.DESCENDING)); list.add(new RowSorter.SortKey(TablesTableModel.COLUMN_CREATED, SortOrder.DESCENDING));
activeTablesSorter.setSortKeys(list); activeTablesSorter.setSortKeys(list);
TableUtil.setColumnWidthAndOrder(tableTables, DEFAULT_COLUMNS_WIDTH, KEY_TABLES_COLUMNS_WIDTH, KEY_TABLES_COLUMNS_ORDER); TableUtil.setColumnWidthAndOrder(tableTables, DEFAULT_COLUMNS_WIDTH, KEY_TABLES_COLUMNS_WIDTH, KEY_TABLES_COLUMNS_ORDER);
@ -239,19 +241,18 @@ public class TablesPanel extends javax.swing.JPanel {
openTableAction = new AbstractAction() { openTableAction = new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// tableUUID;gameUUID
String searchID = e.getActionCommand(); String searchID = e.getActionCommand();
int modelRow = tableModel.findRowByTableAndGameInfo(searchID); int modelRow = TablesUtil.findTableRowFromSearchId(tableModel, searchID);
if (modelRow == -1) { if (modelRow == -1) {
return; return;
} }
UUID tableId = (UUID) tableModel.getValueAt(modelRow, TableTableModel.ACTION_COLUMN + 3); UUID tableId = (UUID) tableModel.getValueAt(modelRow, TablesTableModel.ACTION_COLUMN + 3);
UUID gameId = (UUID) tableModel.getValueAt(modelRow, TableTableModel.ACTION_COLUMN + 2); UUID gameId = (UUID) tableModel.getValueAt(modelRow, TablesTableModel.ACTION_COLUMN + 2);
String action = (String) tableModel.getValueAt(modelRow, TableTableModel.ACTION_COLUMN); String action = (String) tableModel.getValueAt(modelRow, TablesTableModel.ACTION_COLUMN);
String deckType = (String) tableModel.getValueAt(modelRow, TableTableModel.COLUMN_DECK_TYPE); String deckType = (String) tableModel.getValueAt(modelRow, TablesTableModel.COLUMN_DECK_TYPE);
boolean isTournament = (Boolean) tableModel.getValueAt(modelRow, TableTableModel.ACTION_COLUMN + 1); boolean isTournament = (Boolean) tableModel.getValueAt(modelRow, TablesTableModel.ACTION_COLUMN + 1);
String owner = (String) tableModel.getValueAt(modelRow, TableTableModel.COLUMN_OWNER); String owner = (String) tableModel.getValueAt(modelRow, TablesTableModel.COLUMN_OWNER);
String pwdColumn = (String) tableModel.getValueAt(modelRow, TableTableModel.COLUMN_PASSWORD); String pwdColumn = (String) tableModel.getValueAt(modelRow, TablesTableModel.COLUMN_PASSWORD);
switch (action) { switch (action) {
case "Join": case "Join":
if (owner.equals(SessionHandler.getUserName()) || owner.startsWith(SessionHandler.getUserName() + ',')) { if (owner.equals(SessionHandler.getUserName()) || owner.startsWith(SessionHandler.getUserName() + ',')) {
@ -278,7 +279,7 @@ public class TablesPanel extends javax.swing.JPanel {
if (isTournament) { if (isTournament) {
LOGGER.info("Joining tournament " + tableId); LOGGER.info("Joining tournament " + tableId);
if (deckType.startsWith("Limited")) { if (deckType.startsWith("Limited")) {
if (TableTableModel.PASSWORD_VALUE_YES.equals(pwdColumn)) { if (TablesTableModel.PASSWORD_VALUE_YES.equals(pwdColumn)) {
joinTableDialog.showDialog(roomId, tableId, true, deckType.startsWith("Limited")); joinTableDialog.showDialog(roomId, tableId, true, deckType.startsWith("Limited"));
} else { } else {
SessionHandler.joinTournamentTable(roomId, tableId, SessionHandler.getUserName(), PlayerType.HUMAN, 1, null, ""); SessionHandler.joinTournamentTable(roomId, tableId, SessionHandler.getUserName(), PlayerType.HUMAN, 1, null, "");
@ -321,9 +322,8 @@ public class TablesPanel extends javax.swing.JPanel {
closedTableAction = new AbstractAction() { closedTableAction = new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// tableUUID;gameUUID
String searchID = e.getActionCommand(); String searchID = e.getActionCommand();
int modelRow = tableModel.findRowByTableAndGameInfo(searchID); int modelRow = TablesUtil.findTableRowFromSearchId(matchesModel, searchID);
if (modelRow == -1) { if (modelRow == -1) {
return; return;
} }
@ -351,8 +351,8 @@ public class TablesPanel extends javax.swing.JPanel {
}; };
// !!!! adds action buttons to the table panel (don't delete this) // !!!! adds action buttons to the table panel (don't delete this)
actionButton1 = new ButtonColumn(tableTables, openTableAction, tableTables.convertColumnIndexToView(TableTableModel.ACTION_COLUMN)); actionButton1 = new TablesButtonColumn(tableTables, openTableAction, tableTables.convertColumnIndexToView(TablesTableModel.ACTION_COLUMN));
actionButton2 = new ButtonColumn(tableCompleted, closedTableAction, tableCompleted.convertColumnIndexToView(MatchesTableModel.COLUMN_ACTION)); actionButton2 = new TablesButtonColumn(tableCompleted, closedTableAction, tableCompleted.convertColumnIndexToView(MatchesTableModel.COLUMN_ACTION));
// !!!! // !!!!
addTableDoubleClickListener(tableTables, openTableAction); addTableDoubleClickListener(tableTables, openTableAction);
addTableDoubleClickListener(tableCompleted, closedTableAction); addTableDoubleClickListener(tableCompleted, closedTableAction);
@ -364,7 +364,7 @@ public class TablesPanel extends javax.swing.JPanel {
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
int row = table.getSelectedRow(); int row = table.getSelectedRow();
if (e.getClickCount() == 2 && row != -1) { if (e.getClickCount() == 2 && row != -1) {
action.actionPerformed(new ActionEvent(table, ActionEvent.ACTION_PERFORMED, tableModel.findTableAndGameInfoByRow(row))); action.actionPerformed(new ActionEvent(table, ActionEvent.ACTION_PERFORMED, TablesUtil.getSearchIdFromTable(table, row)));
} }
} }
}); });
@ -608,87 +608,87 @@ public class TablesPanel extends javax.swing.JPanel {
// state // state
java.util.List<RowFilter<Object, Object>> stateFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> stateFilterList = new ArrayList<>();
if (btnStateWaiting.isSelected()) { if (btnStateWaiting.isSelected()) {
stateFilterList.add(RowFilter.regexFilter("Waiting", TableTableModel.COLUMN_STATUS)); stateFilterList.add(RowFilter.regexFilter("Waiting", TablesTableModel.COLUMN_STATUS));
} }
if (btnStateActive.isSelected()) { if (btnStateActive.isSelected()) {
stateFilterList.add(RowFilter.regexFilter("Dueling|Constructing|Drafting|Sideboard", TableTableModel.COLUMN_STATUS)); stateFilterList.add(RowFilter.regexFilter("Dueling|Constructing|Drafting|Sideboard", TablesTableModel.COLUMN_STATUS));
} }
// type // type
java.util.List<RowFilter<Object, Object>> typeFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> typeFilterList = new ArrayList<>();
if (btnTypeMatch.isSelected()) { if (btnTypeMatch.isSelected()) {
typeFilterList.add(RowFilter.regexFilter("Two|Commander|Free|Tiny|Momir", TableTableModel.COLUMN_GAME_TYPE)); typeFilterList.add(RowFilter.regexFilter("Two|Commander|Free|Tiny|Momir", TablesTableModel.COLUMN_GAME_TYPE));
} }
if (btnTypeTourneyConstructed.isSelected()) { if (btnTypeTourneyConstructed.isSelected()) {
typeFilterList.add(RowFilter.regexFilter("Constructed", TableTableModel.COLUMN_GAME_TYPE)); typeFilterList.add(RowFilter.regexFilter("Constructed", TablesTableModel.COLUMN_GAME_TYPE));
} }
if (btnTypeTourneyLimited.isSelected()) { if (btnTypeTourneyLimited.isSelected()) {
typeFilterList.add(RowFilter.regexFilter("Booster|Sealed", TableTableModel.COLUMN_GAME_TYPE)); typeFilterList.add(RowFilter.regexFilter("Booster|Sealed", TablesTableModel.COLUMN_GAME_TYPE));
} }
// format // format
java.util.List<RowFilter<Object, Object>> formatFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> formatFilterList = new ArrayList<>();
if (btnFormatBlock.isSelected()) { if (btnFormatBlock.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed.*Block", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed.*Block", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatStandard.isSelected()) { if (btnFormatStandard.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Standard", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Standard", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatModern.isSelected()) { if (btnFormatModern.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatLegacy.isSelected()) { if (btnFormatLegacy.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatVintage.isSelected()) { if (btnFormatVintage.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Vintage", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Vintage", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatCommander.isSelected()) { if (btnFormatCommander.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatTinyLeader.isSelected()) { if (btnFormatTinyLeader.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatLimited.isSelected()) { if (btnFormatLimited.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Limited", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Limited", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatOther.isSelected()) { if (btnFormatOther.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander|^Constructed - Old", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander|^Constructed - Old", TablesTableModel.COLUMN_DECK_TYPE));
} }
// skill // skill
java.util.List<RowFilter<Object, Object>> skillFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> skillFilterList = new ArrayList<>();
if (btnSkillBeginner.isSelected()) { if (btnSkillBeginner.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.BEGINNER, true), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.BEGINNER, true), TablesTableModel.COLUMN_SKILL));
} }
if (btnSkillCasual.isSelected()) { if (btnSkillCasual.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.CASUAL, true), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.CASUAL, true), TablesTableModel.COLUMN_SKILL));
} }
if (btnSkillSerious.isSelected()) { if (btnSkillSerious.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.SERIOUS, true), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.SERIOUS, true), TablesTableModel.COLUMN_SKILL));
} }
String ratedMark = TableTableModel.RATED_VALUE_YES; String ratedMark = TablesTableModel.RATED_VALUE_YES;
java.util.List<RowFilter<Object, Object>> ratingFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> ratingFilterList = new ArrayList<>();
if (btnRated.isSelected()) { if (btnRated.isSelected()) {
// yes word // yes word
ratingFilterList.add(RowFilter.regexFilter("^" + ratedMark, TableTableModel.COLUMN_RATING)); ratingFilterList.add(RowFilter.regexFilter("^" + ratedMark, TablesTableModel.COLUMN_RATING));
} }
if (btnUnrated.isSelected()) { if (btnUnrated.isSelected()) {
// not yes word, see https://stackoverflow.com/a/406408/1276632 // not yes word, see https://stackoverflow.com/a/406408/1276632
ratingFilterList.add(RowFilter.regexFilter("^((?!" + ratedMark + ").)*$", TableTableModel.COLUMN_RATING)); ratingFilterList.add(RowFilter.regexFilter("^((?!" + ratedMark + ").)*$", TablesTableModel.COLUMN_RATING));
} }
// Password // Password
String passwordMark = TableTableModel.PASSWORD_VALUE_YES; String passwordMark = TablesTableModel.PASSWORD_VALUE_YES;
java.util.List<RowFilter<Object, Object>> passwordFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> passwordFilterList = new ArrayList<>();
if (btnPassword.isSelected()) { if (btnPassword.isSelected()) {
// yes // yes
passwordFilterList.add(RowFilter.regexFilter("^" + passwordMark, TableTableModel.COLUMN_PASSWORD)); passwordFilterList.add(RowFilter.regexFilter("^" + passwordMark, TablesTableModel.COLUMN_PASSWORD));
} }
if (btnOpen.isSelected()) { if (btnOpen.isSelected()) {
// no // no
passwordFilterList.add(RowFilter.regexFilter("^((?!" + passwordMark + ").)*$", TableTableModel.COLUMN_PASSWORD)); passwordFilterList.add(RowFilter.regexFilter("^((?!" + passwordMark + ").)*$", TablesTableModel.COLUMN_PASSWORD));
} }
// Hide games of ignored players // Hide games of ignored players
@ -699,7 +699,7 @@ public class TablesPanel extends javax.swing.JPanel {
ignoreListFilterList.add(new RowFilter<Object, Object>() { ignoreListFilterList.add(new RowFilter<Object, Object>() {
@Override @Override
public boolean include(Entry<? extends Object, ? extends Object> entry) { public boolean include(Entry<? extends Object, ? extends Object> entry) {
final String owner = entry.getStringValue(TableTableModel.COLUMN_OWNER); final String owner = entry.getStringValue(TablesTableModel.COLUMN_OWNER);
return !ignoreListCopy.contains(owner); return !ignoreListCopy.contains(owner);
} }
}); });
@ -708,7 +708,7 @@ public class TablesPanel extends javax.swing.JPanel {
if (stateFilterList.isEmpty() || typeFilterList.isEmpty() || formatFilterList.isEmpty() if (stateFilterList.isEmpty() || typeFilterList.isEmpty() || formatFilterList.isEmpty()
|| skillFilterList.isEmpty() || ratingFilterList.isEmpty() || skillFilterList.isEmpty() || ratingFilterList.isEmpty()
|| passwordFilterList.isEmpty()) { // no selection || passwordFilterList.isEmpty()) { // no selection
activeTablesSorter.setRowFilter(RowFilter.regexFilter("Nothing", TableTableModel.COLUMN_SKILL)); activeTablesSorter.setRowFilter(RowFilter.regexFilter("Nothing", TablesTableModel.COLUMN_SKILL));
} else { } else {
java.util.List<RowFilter<Object, Object>> filterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> filterList = new ArrayList<>();
@ -1357,201 +1357,6 @@ public class TablesPanel extends javax.swing.JPanel {
} }
class TableTableModel extends AbstractTableModel {
final ImageIcon tourneyIcon = new javax.swing.ImageIcon(getClass().getResource("/tables/tourney_icon.png"));
final ImageIcon matchIcon = new javax.swing.ImageIcon(getClass().getResource("/tables/match_icon.png"));
public static final int COLUMN_ICON = 0;
public static final int COLUMN_DECK_TYPE = 1; // column the deck type is located (starting with 0) Start string is used to check for Limited
public static final int COLUMN_OWNER = 2;
public static final int COLUMN_GAME_TYPE = 3;
public static final int COLUMN_INFO = 4;
public static final int COLUMN_STATUS = 5;
public static final int COLUMN_PASSWORD = 6;
public static final int COLUMN_CREATED = 7;
public static final int COLUMN_SKILL = 8;
public static final int COLUMN_RATING = 9;
public static final int COLUMN_QUIT_RATIO = 10;
public static final int COLUMN_MINIMUM_RATING = 11;
public static final int ACTION_COLUMN = 12; // column the action is located (starting with 0)
public static final String RATED_VALUE_YES = "YES";
public static final String RATED_VALUE_NO = "";
public static final String PASSWORD_VALUE_YES = "YES";
private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rated", "Quit %", "Min Rating", "Action"};
private TableView[] tables = new TableView[0];
TableTableModel() {
}
public void loadData(Collection<TableView> tables) throws MageRemoteException {
this.tables = tables.toArray(new TableView[0]);
this.fireTableDataChanged();
}
public String getTableAndGameInfo(int row) {
return this.tables[row].getTableId().toString() + ";" + (!tables[row].getGames().isEmpty() ? tables[row].getGames().get(0) : null).toString();
}
public String findTableAndGameInfoByRow(int row) {
if (row >= 0 && this.tables.length < row) {
return getTableAndGameInfo(row);
} else {
return null;
}
}
public int findRowByTableAndGameInfo(String tableAndGame) {
for (int i = 0; i < this.tables.length; i++) {
String rowID = this.tables[i].getTableId().toString() + ";" + (!tables[i].getGames().isEmpty() ? tables[i].getGames().get(0) : null).toString();
if (tableAndGame.equals(rowID)) {
return i;
}
}
return -1;
}
public String getSkillLevelAsCode(SkillLevel skill, boolean asRegExp) {
String res;
switch (skill) {
case BEGINNER:
res = "*";
break;
case CASUAL:
res = "**";
break;
case SERIOUS:
res = "***";
break;
default:
res = "";
break;
}
// regexp format for search table rows
if (asRegExp) {
res = String.format("^%s$", res.replace("*", "\\*"));
}
return res;
}
@Override
public int getRowCount() {
return tables.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return tables[arg0].isTournament() ? tourneyIcon : matchIcon;
case 1:
return tables[arg0].getDeckType();
case 2:
return tables[arg0].getControllerName();
case 3:
return tables[arg0].getGameType();
case 4:
return tables[arg0].getAdditionalInfo();
case 5:
return tables[arg0].getTableStateText();
case 6:
return tables[arg0].isPassworded() ? PASSWORD_VALUE_YES : "";
case 7:
return tables[arg0].getCreateTime(); // use cell render, not format here
case 8:
return this.getSkillLevelAsCode(tables[arg0].getSkillLevel(), false);
case 9:
return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO;
case 10:
return tables[arg0].getQuitRatio();
case 11:
return tables[arg0].getMinimumRating();
case 12:
switch (tables[arg0].getTableState()) {
case WAITING:
String owner = tables[arg0].getControllerName();
if (SessionHandler.getSession() != null && owner.equals(SessionHandler.getUserName())) {
return "";
}
return "Join";
case CONSTRUCTING:
case DRAFTING:
if (tables[arg0].isTournament()) {
return "Show";
}
case DUELING:
if (tables[arg0].isTournament()) {
return "Show";
} else {
owner = tables[arg0].getControllerName();
if (SessionHandler.getSession() != null && owner.equals(SessionHandler.getUserName())) {
return "";
}
if (tables[arg0].getSpectatorsAllowed()) {
return "Watch";
}
return "";
}
default:
return "";
}
case 13:
return tables[arg0].isTournament();
case 14:
if (!tables[arg0].getGames().isEmpty()) {
return tables[arg0].getGames().get(0);
}
return null;
case 15:
return tables[arg0].getTableId();
}
return "";
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case COLUMN_ICON:
return Icon.class;
case COLUMN_SKILL:
return SkillLevel.class;
case COLUMN_CREATED:
return Date.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == ACTION_COLUMN;
}
}
class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> { class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
private final UUID roomId; private final UUID roomId;
@ -1640,119 +1445,6 @@ class UpdatePlayersTask extends SwingWorker<Void, Collection<RoomUsersView>> {
} }
class MatchesTableModel extends AbstractTableModel {
private final String[] columnNames = new String[]{"Deck Type", "Players", "Game Type", "Rating", "Result", "Duration", "Start Time", "End Time", "Action"};
public static final int COLUMN_DURATION = 5;
public static final int COLUMN_START = 6;
public static final int COLUMN_END = 7;
public static final int COLUMN_ACTION = 8; // column the action is located (starting with 0)
private MatchView[] matches = new MatchView[0];
public void loadData(Collection<MatchView> matches) throws MageRemoteException {
this.matches = matches.toArray(new MatchView[0]);
this.fireTableDataChanged();
}
MatchesTableModel() {
}
@Override
public int getRowCount() {
return matches.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return matches[arg0].getDeckType();
case 1:
return matches[arg0].getPlayers();
case 2:
return matches[arg0].getGameType();
case 3:
return matches[arg0].isRated() ? TableTableModel.RATED_VALUE_YES : TableTableModel.RATED_VALUE_NO;
case 4:
return matches[arg0].getResult();
case 5:
if (matches[arg0].getEndTime() != null) {
return matches[arg0].getEndTime().getTime() - matches[arg0].getStartTime().getTime() + new Date().getTime();
} else {
return 0L;
}
case 6:
return matches[arg0].getStartTime();
case 7:
return matches[arg0].getEndTime();
case 8:
if (matches[arg0].isTournament()) {
return "Show";
} else if (matches[arg0].isReplayAvailable()) {
return "Replay";
} else {
return "None";
}
case 9:
return matches[arg0].getGames();
}
return "";
}
public java.util.List<UUID> getListofGames(int row) {
return matches[row].getGames();
}
public boolean isTournament(int row) {
return matches[row].isTournament();
}
public UUID getMatchId(int row) {
return matches[row].getMatchId();
}
public UUID getTableId(int row) {
return matches[row].getTableId();
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case COLUMN_DURATION:
return Long.class;
case COLUMN_START:
return Date.class;
case COLUMN_END:
return Date.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == COLUMN_ACTION;
}
}
class UpdateMatchesTask extends SwingWorker<Void, Collection<MatchView>> { class UpdateMatchesTask extends SwingWorker<Void, Collection<MatchView>> {
private final UUID roomId; private final UUID roomId;

View file

@ -0,0 +1,206 @@
package mage.client.table;
import mage.client.SessionHandler;
import mage.constants.SkillLevel;
import mage.remote.MageRemoteException;
import mage.view.TableView;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.util.Collection;
import java.util.Date;
public class TablesTableModel extends AbstractTableModel {
final ImageIcon tourneyIcon = new ImageIcon(getClass().getResource("/tables/tourney_icon.png"));
final ImageIcon matchIcon = new ImageIcon(getClass().getResource("/tables/match_icon.png"));
public static final int COLUMN_ICON = 0;
public static final int COLUMN_DECK_TYPE = 1; // column the deck type is located (starting with 0) Start string is used to check for Limited
public static final int COLUMN_OWNER = 2;
public static final int COLUMN_GAME_TYPE = 3;
public static final int COLUMN_INFO = 4;
public static final int COLUMN_STATUS = 5;
public static final int COLUMN_PASSWORD = 6;
public static final int COLUMN_CREATED = 7;
public static final int COLUMN_SKILL = 8;
public static final int COLUMN_RATING = 9;
public static final int COLUMN_QUIT_RATIO = 10;
public static final int COLUMN_MINIMUM_RATING = 11;
public static final int ACTION_COLUMN = 12; // column the action is located (starting with 0)
public static final String RATED_VALUE_YES = "YES";
public static final String RATED_VALUE_NO = "";
public static final String PASSWORD_VALUE_YES = "YES";
private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rated", "Quit %", "Min Rating", "Action"};
private TableView[] tables = new TableView[0];
TablesTableModel() {
}
public void loadData(Collection<TableView> tables) throws MageRemoteException {
this.tables = tables.toArray(new TableView[0]);
this.fireTableDataChanged();
}
public String getTableAndGameInfo(int row) {
return this.tables[row].getTableId().toString() + ";" + (!tables[row].getGames().isEmpty() ? tables[row].getGames().get(0).toString() : "null");
}
public String findTableAndGameInfoByRow(int row) {
if (row >= 0 && row < this.tables.length) {
return getTableAndGameInfo(row);
} else {
return null;
}
}
public int findRowByTableAndGameInfo(String tableAndGame) {
for (int i = 0; i < this.tables.length; i++) {
String rowID = this.tables[i].getTableId().toString() + ";" + (!this.tables[i].getGames().isEmpty() ? this.tables[i].getGames().get(0).toString() : "null");
if (tableAndGame.equals(rowID)) {
return i;
}
}
return -1;
}
public String getSkillLevelAsCode(SkillLevel skill, boolean asRegExp) {
String res;
switch (skill) {
case BEGINNER:
res = "*";
break;
case CASUAL:
res = "**";
break;
case SERIOUS:
res = "***";
break;
default:
res = "";
break;
}
// regexp format for search table rows
if (asRegExp) {
res = String.format("^%s$", res.replace("*", "\\*"));
}
return res;
}
@Override
public int getRowCount() {
return tables.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return tables[arg0].isTournament() ? tourneyIcon : matchIcon;
case 1:
return tables[arg0].getDeckType();
case 2:
return tables[arg0].getControllerName();
case 3:
return tables[arg0].getGameType();
case 4:
return tables[arg0].getAdditionalInfo();
case 5:
return tables[arg0].getTableStateText();
case 6:
return tables[arg0].isPassworded() ? PASSWORD_VALUE_YES : "";
case 7:
return tables[arg0].getCreateTime(); // use cell render, not format here
case 8:
return this.getSkillLevelAsCode(tables[arg0].getSkillLevel(), false);
case 9:
return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO;
case 10:
return tables[arg0].getQuitRatio();
case 11:
return tables[arg0].getMinimumRating();
case 12:
switch (tables[arg0].getTableState()) {
case WAITING:
String owner = tables[arg0].getControllerName();
if (SessionHandler.getSession() != null && owner.equals(SessionHandler.getUserName())) {
return "";
}
return "Join";
case CONSTRUCTING:
case DRAFTING:
if (tables[arg0].isTournament()) {
return "Show";
}
case DUELING:
if (tables[arg0].isTournament()) {
return "Show";
} else {
owner = tables[arg0].getControllerName();
if (SessionHandler.getSession() != null && owner.equals(SessionHandler.getUserName())) {
return "";
}
if (tables[arg0].getSpectatorsAllowed()) {
return "Watch";
}
return "";
}
default:
return "";
}
case 13:
return tables[arg0].isTournament();
case 14:
if (!tables[arg0].getGames().isEmpty()) {
return tables[arg0].getGames().get(0);
}
return null;
case 15:
return tables[arg0].getTableId();
}
return "";
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case COLUMN_ICON:
return Icon.class;
case COLUMN_SKILL:
return SkillLevel.class;
case COLUMN_CREATED:
return Date.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == ACTION_COLUMN;
}
}

View file

@ -0,0 +1,40 @@
package mage.client.table;
import org.apache.log4j.Logger;
import javax.swing.*;
/**
* @author JayDi85
*/
public class TablesUtil {
private static final Logger logger = Logger.getLogger(TablesUtil.class);
public static String getSearchIdFromTable(JTable table, int row) {
// tableUUID;gameUUID
String searchId = null;
if (table.getModel() instanceof TablesTableModel) {
searchId = ((TablesTableModel) table.getModel()).findTableAndGameInfoByRow(row);
} else if (table.getModel() instanceof MatchesTableModel) {
searchId = ((MatchesTableModel) table.getModel()).findTableAndGameInfoByRow(row);
} else {
logger.error("Not supported tables model " + table.getModel().getClass().toString());
}
return searchId;
}
public static int findTableRowFromSearchId(Object tableModel, String searchId) {
// tableUUID;gameUUID
int row = -1;
if (tableModel instanceof TablesTableModel) {
row = ((TablesTableModel) tableModel).findRowByTableAndGameInfo(searchId);
} else if (tableModel instanceof MatchesTableModel) {
row = ((MatchesTableModel) tableModel).findRowByTableAndGameInfo(searchId);
} else {
logger.error("Not supported tables model " + tableModel.getClass().toString());
}
return row;
}
}

View file

@ -1,15 +1,21 @@
/*
* TournamentPanel.java
*
* Created on 20-Jan-2011, 9:18:30 PM
*/
package mage.client.tournament; package mage.client.tournament;
import java.awt.Component; import mage.client.MageFrame;
import java.awt.Dimension; import mage.client.SessionHandler;
import java.awt.Rectangle; import mage.client.chat.ChatPanelBasic;
import mage.client.dialog.PreferencesDialog;
import mage.client.table.TablesButtonColumn;
import mage.client.util.Format;
import mage.client.util.GUISizeHelper;
import mage.client.util.gui.TableUtil;
import mage.client.util.gui.countryBox.CountryCellRenderer;
import mage.constants.PlayerAction;
import mage.view.*;
import org.apache.log4j.Logger;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,34 +25,10 @@ import java.util.UUID;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.swing.AbstractAction;
import javax.swing.Action; import static mage.client.dialog.PreferencesDialog.*;
import javax.swing.Icon;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.chat.ChatPanelBasic;
import mage.client.dialog.PreferencesDialog;
import static mage.client.dialog.PreferencesDialog.KEY_TOURNAMENT_MATCH_COLUMNS_ORDER;
import static mage.client.dialog.PreferencesDialog.KEY_TOURNAMENT_MATCH_COLUMNS_WIDTH;
import static mage.client.dialog.PreferencesDialog.KEY_TOURNAMENT_PLAYER_COLUMNS_ORDER;
import static mage.client.dialog.PreferencesDialog.KEY_TOURNAMENT_PLAYER_COLUMNS_WIDTH;
import mage.client.util.ButtonColumn;
import mage.client.util.Format;
import mage.client.util.GUISizeHelper;
import mage.client.util.gui.TableUtil;
import mage.client.util.gui.countryBox.CountryCellRenderer;
import mage.constants.PlayerAction;
import mage.view.RoundView;
import mage.view.TournamentGameView;
import mage.view.TournamentPlayerView;
import mage.view.TournamentView;
import mage.view.UserRequestMessage;
import org.apache.log4j.Logger;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TournamentPanel extends javax.swing.JPanel { public class TournamentPanel extends javax.swing.JPanel {
@ -64,7 +46,7 @@ public class TournamentPanel extends javax.swing.JPanel {
private UpdateTournamentTask updateTask; private UpdateTournamentTask updateTask;
private final DateFormat df; private final DateFormat df;
private final ButtonColumn actionButtonColumn1; private final TablesButtonColumn actionButtonColumn1;
/** /**
* Creates new form TournamentPanel * Creates new form TournamentPanel
@ -111,7 +93,7 @@ public class TournamentPanel extends javax.swing.JPanel {
}; };
// action button, don't delete this // action button, don't delete this
actionButtonColumn1 = new ButtonColumn(tableMatches, action, tableMatches.convertColumnIndexToView(TournamentMatchesTableModel.ACTION_COLUMN)); actionButtonColumn1 = new TablesButtonColumn(tableMatches, action, tableMatches.convertColumnIndexToView(TournamentMatchesTableModel.ACTION_COLUMN));
setGUISize(); setGUISize();
} }
@ -390,67 +372,67 @@ public class TournamentPanel extends javax.swing.JPanel {
javax.swing.GroupLayout actionPanelLayout = new javax.swing.GroupLayout(actionPanel); javax.swing.GroupLayout actionPanelLayout = new javax.swing.GroupLayout(actionPanel);
actionPanel.setLayout(actionPanelLayout); actionPanel.setLayout(actionPanelLayout);
actionPanelLayout.setHorizontalGroup( actionPanelLayout.setHorizontalGroup(
actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lblName) .addComponent(lblName)
.addComponent(lblState) .addComponent(lblState)
.addComponent(txtName, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) .addComponent(txtName, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)
.addComponent(txtTournamentState)) .addComponent(txtTournamentState))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lblType) .addComponent(lblType)
.addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, 440, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, 440, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblStartTime)) .addComponent(lblStartTime))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblEndTime) .addComponent(lblEndTime)
.addComponent(txtEndTime)))) .addComponent(txtEndTime))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 126, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 126, Short.MAX_VALUE)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnQuitTournament, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnQuitTournament, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCloseWindow, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(btnCloseWindow, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
); );
actionPanelLayout.setVerticalGroup( actionPanelLayout.setVerticalGroup(
actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addGap(7, 7, 7) .addGap(7, 7, 7)
.addComponent(lblName)) .addComponent(lblName))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, actionPanelLayout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, actionPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(lblType))) .addComponent(lblType)))
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnQuitTournament)) .addComponent(btnQuitTournament))
.addGap(13, 13, 13) .addGap(13, 13, 13)
.addComponent(btnCloseWindow)) .addComponent(btnCloseWindow))
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addGap(6, 6, 6) .addGap(6, 6, 6)
.addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtName, 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)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblState) .addComponent(lblState)
.addComponent(lblStartTime) .addComponent(lblStartTime)
.addComponent(lblEndTime)) .addComponent(lblEndTime))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(actionPanelLayout.createSequentialGroup() .addGroup(actionPanelLayout.createSequentialGroup()
.addComponent(txtTournamentState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtTournamentState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)) .addGap(0, 0, Short.MAX_VALUE))
.addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtStartTime) .addComponent(txtStartTime)
.addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
.addContainerGap()) .addContainerGap())
); );
jSplitPane2.setResizeWeight(1.0); jSplitPane2.setResizeWeight(1.0);
@ -481,17 +463,17 @@ public class TournamentPanel extends javax.swing.JPanel {
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(actionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(actionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSplitPane2, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jSplitPane2, javax.swing.GroupLayout.Alignment.TRAILING)
); );
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(actionPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(actionPanel, 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(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 454, Short.MAX_VALUE) .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 454, Short.MAX_VALUE)
.addContainerGap()) .addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View file

@ -0,0 +1,68 @@
package mage.client.util;
import java.util.ArrayList;
/**
* @author JayDi85
*/
public enum CardLanguage {
ENGLISH("en", "English"),
SPANISH("es", "Spanish"),
FRENCH("fr", "French"),
GERMAN("de", "German"),
ITALIAN("it", "Italian"),
PORTUGUESE("pt", "Portuguese"),
JAPANESE("jp", "Japanese"),
KOREAN("ko", "Korean"),
RUSSIAN("ru", "Russian"),
CHINES_SIMPLE("cns", "Chinese Simplified"),
CHINES_TRADITION("cnt", "Chinese Traditional");
private final String code;
private final String text;
CardLanguage(String code, String text) {
this.code = code;
this.text = text;
}
@Override
public String toString() {
return code;
}
public String getCode() {
return code;
}
public String getText() {
return text;
}
public static String[] toList() {
ArrayList<String> res = new ArrayList<>();
for (CardLanguage l : values()) {
res.add(l.toString());
}
return res.toArray(new String[0]);
}
public static CardLanguage valueByText(String text) {
for (CardLanguage type : values()) {
if (type.text.equals(text)) {
return type;
}
}
return CardLanguage.ENGLISH;
}
public static CardLanguage valueByCode(String code) {
for (CardLanguage type : values()) {
if (type.code.equals(code)) {
return type;
}
}
return CardLanguage.ENGLISH;
}
}

View file

@ -57,7 +57,7 @@ public class AudioManager {
try { try {
linePool = new LinePool(); linePool = new LinePool();
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to initialize AudioManager. No sounds will be played.", e); log.warn("Failed to initialize AudioManager (can't find compatible sound device). No sounds will be played.");
} }
} }

View file

@ -19,12 +19,16 @@ public class FastSearchUtil {
public static String DEFAULT_EXPANSION_SEARCH_MESSAGE = "Select set or expansion"; public static String DEFAULT_EXPANSION_SEARCH_MESSAGE = "Select set or expansion";
public static String DEFAULT_EXPANSION_TOOLTIP_MESSAGE = "Fast search set or expansion"; public static String DEFAULT_EXPANSION_TOOLTIP_MESSAGE = "Fast search set or expansion";
public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage){
showFastSearchForStringComboBox(combo, chooseMessage, 300, 500);
}
/** /**
* Show fast choice modal dialog with incremental searching for any string combobox components * Show fast choice modal dialog with incremental searching for any string combobox components
* @param combo combobox control with default data model * @param combo combobox control with default data model
* @param chooseMessage caption message for dialog * @param chooseMessage caption message for dialog
*/ */
public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage){ public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage, int windowWidth, int windowHeight){
// fast search/choice dialog for string combobox // fast search/choice dialog for string combobox
mage.choices.Choice choice = new ChoiceImpl(false); mage.choices.Choice choice = new ChoiceImpl(false);
@ -51,7 +55,7 @@ public class FastSearchUtil {
// ask for new value // ask for new value
PickChoiceDialog dlg = new PickChoiceDialog(); PickChoiceDialog dlg = new PickChoiceDialog();
dlg.setWindowSize(300, 500); dlg.setWindowSize(windowWidth, windowHeight);
dlg.showDialog(choice, needSelectValue); dlg.showDialog(choice, needSelectValue);
if(choice.isChosen()){ if(choice.isChosen()){
item = choice.getChoiceKey(); item = choice.getChoiceKey();

View file

@ -1,10 +1,11 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import java.util.ArrayList; import mage.client.util.CardLanguage;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.util.ArrayList;
/** /**
*
* @author North * @author North
*/ */
public interface CardImageSource { public interface CardImageSource {
@ -31,10 +32,21 @@ public interface CardImageSource {
return false; return false;
} }
default boolean isLanguagesSupport() {
return false;
}
default void setCurrentLanguage(CardLanguage cardLanguage) {
}
default CardLanguage getCurrentLanguage() {
return CardLanguage.ENGLISH;
}
void doPause(String httpImageUrl); void doPause(String httpImageUrl);
default ArrayList<String> getSupportedSets() { default ArrayList<String> getSupportedSets() {
return null; return new ArrayList<>();
} }
default boolean isSetSupportedComplete(String setCode) { default boolean isSetSupportedComplete(String setCode) {

View file

@ -1,439 +0,0 @@
package org.mage.plugins.card.dl.sources;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import mage.client.dialog.PreferencesDialog;
import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.utils.CardImageUtils;
/**
* @author North
*/
public enum MagicCardsImageSource implements CardImageSource {
instance;
private static final Set<String> supportedSets = new LinkedHashSet<String>() {
{
// add("PTC"); // Prerelease Events
add("LEA");
add("LEB");
add("2ED");
add("ARN");
add("ATQ");
add("3ED");
add("LEG");
add("DRK");
add("FEM");
add("4ED");
add("ICE");
add("CHR");
add("HML");
add("ALL");
add("MIR");
add("VIS");
add("5ED");
add("POR");
add("WTH");
add("TMP");
add("STH");
add("EXO");
add("P02");
add("UGL");
add("USG");
add("DD3DVD");
add("DD3EVG");
add("DD3GVL");
add("DD3JVC");
add("ULG");
add("6ED");
add("UDS");
add("PTK");
add("S99");
add("MMQ");
// add("BRB");Battle Royale Box Set
add("NEM");
add("S00");
add("PCY");
add("INV");
// add("BTD"); // Beatdown Boxset
add("PLS");
add("7ED");
add("APC");
add("ODY");
// add("DKM"); // Deckmasters 2001
add("TOR");
add("JUD");
add("ONS");
add("LGN");
add("SCG");
add("8ED");
add("MRD");
add("DST");
add("5DN");
add("CHK");
add("UNH");
add("BOK");
add("SOK");
add("9ED");
add("RAV");
add("GPT");
add("DIS");
add("CSP");
add("TSP");
add("TSB");
add("PLC");
add("FUT");
add("10E");
add("MED");
add("LRW");
add("EVG");
add("MOR");
add("SHM");
add("EVE");
add("DRB");
add("ME2");
add("ALA");
add("DD2");
add("CON");
add("DDC");
add("ARB");
add("M10");
// add("TD0"); // Magic Online Deck Series
add("V09");
add("HOP");
add("ME3");
add("ZEN");
add("DDD");
add("H09");
add("WWK");
add("DDE");
add("ROE");
add("DPA");
add("ARC");
add("M11");
add("V10");
add("DDF");
add("SOM");
// add("TD0"); // Commander Theme Decks
add("PD2");
add("ME4");
add("MBS");
add("DDG");
add("NPH");
add("CMD");
add("M12");
add("V11");
add("DDH");
add("ISD");
add("PD3");
add("DKA");
add("DDI");
add("AVR");
add("PC2");
add("M13");
add("V12");
add("DDJ");
add("RTR");
add("CM1");
// add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
add("GTC");
add("DDK");
add("DGM");
add("MMA");
add("M14");
add("V13");
add("DDL");
add("THS");
add("C13");
add("BNG");
add("DDM");
add("JOU");
// add("MD1"); // Modern Event Deck
add("CNS");
add("VMA");
add("M15");
add("V14");
add("DDN");
add("KTK");
add("C14");
// add("DD3"); // Duel Decks Anthology
add("FRF");
add("DDO");
add("DTK");
add("TPR");
add("MM2");
add("ORI");
add("V15");
add("DDP");
add("BFZ");
add("EXP");
add("C15");
// add("PZ1"); // Legendary Cube
add("OGW");
add("DDQ");
add("W16");
add("SOI");
add("EMA");
add("EMN");
add("V16");
add("CN2");
add("DDR");
add("KLD");
add("MPS");
// add("PZ2"); // Treasure Chests
add("C16");
add("PCA");
add("AER");
add("MM3");
add("DDS");
add("W17");
add("AKH");
add("MPS");
add("CMA");
add("E01");
add("HOU");
add("C17");
add("XLN");
add("DDT");
add("DDU");
add("IMA");
add("E02");
add("V17");
add("UST");
add("RIX");
add("A25");
add("DOM");
// add("CM2");
// add("M19");
}
};
private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() {
{
put("10E", "tenth-edition");
put("AER", "aether-revolt");
put("AKH", "amonkhet");
put("ALA", "shards-of-alara");
put("ANB", "archenemy-nicol-bolas");
put("APAC", "asia-pacific-land-program");
put("APC", "player-rewards-2001");
put("ARB", "alara-reborn");
put("ARC", "archenemy");
put("ARENA", "arena-league");
put("AVR", "avacyn-restored");
put("BFZ", "battle-for-zendikar");
put("BNG", "born-of-the-gods");
put("C13", "commander-2013-edition");
put("C14", "commander-2014");
put("C15", "commander-2015");
put("C16", "commander-2016");
put("CLASH", "clash-pack");
put("CMA", "commander-anthology");
put("CMA", "commanders-arsenal");
put("CMD", "commander");
put("CN2", "conspiracy-take-the-crown");
put("CNS", "conspiracy");
put("CON", "conflux");
put("CP", "champs");
put("CSP", "coldsnap");
put("DD2", "duel-decks-jace-vs-chandra");
put("DD3DVD", "duel-decks-anthology-divine-vs-demonic");
put("DD3EVG", "duel-decks-anthology-elves-vs-goblins");
put("DD3GVL", "duel-decks-anthology-garruk-vs-liliana");
put("DD3JVC", "duel-decks-anthology-jace-vs-chandra");
put("DDC", "duel-decks-divine-vs-demonic");
put("DDD", "duel-decks-garruk-vs-liliana");
put("DDE", "duel-decks-phyrexia-vs-the-coalition");
put("DDF", "duel-decks-elspeth-vs-tezzeret");
put("DDG", "duel-decks-knights-vs-dragons");
put("DDH", "duel-decks-ajani-vs-nicol-bolas");
put("DDI", "duel-decks-venser-vs-koth");
put("DDJ", "duel-decks-izzet-vs-golgari");
put("DDK", "duel-decks-sorin-vs-tibalt");
put("DDL", "duel-decks-heroes-vs-monsters");
put("DDM", "duel-decks-jace-vs-vraska");
put("DDN", "duel-decks-speed-vs-cunning");
put("DDO", "duel-decks-elspeth-vs-kiora");
put("DDP", "duel-decks-zendikar-vs-eldrazi");
put("DDQ", "duel-decks-blessed-vs-cursed");
put("DDR", "duel-decks-nissa-vs-ob-nixilis");
put("DDS", "duel-decks-mind-vs-might");
put("DDT", "duel-decks-merfolk-vs-goblin");
put("DDU", "duel-decks-elves-vs-inventors");
put("DGM", "dragons-maze");
put("DKA", "dark-ascension");
put("DRB", "from-the-vault-dragons");
put("DTK", "dragons-of-tarkir");
put("EMA", "eternal-masters");
put("EMN", "eldritch-moon");
put("EURO", "european-land-program");
put("EVE", "eventide");
put("EVG", "duel-decks-elves-vs-goblins");
put("EXP", "zendikar-expeditions");
put("FNMP", "friday-night-magic");
put("FRF", "fate-reforged");
put("GPX", "grand-prix");
put("GRC", "wpngateway");
put("GTC", "gatecrash");
put("HOP", "planechase");
put("HOU", "hour-of-devastation");
put("INV", "player-rewards-2001");
put("ISD", "innistrad");
put("JOU", "journey-into-nyx");
put("JR", "judge-gift-program");
put("KLD", "kaladesh");
put("KTK", "khans-of-tarkir");
put("LRW", "lorwyn");
put("M10", "magic-2010");
put("M11", "magic-2011");
put("M12", "magic-2012");
put("M13", "magic-2013");
put("M14", "magic-2014");
put("M15", "magic-2015");
put("MBP", "media-inserts");
put("MBS", "mirrodin-besieged");
put("MGDC", "magic-game-day-cards");
put("MLP", "launch-party");
put("MM2", "modern-masters-2015");
put("MM3", "modern-masters-2017");
put("MMA", "modern-masters");
put("MOR", "morningtide");
put("MPRP", "magic-player-rewards");
put("MPS", "masterpiece-series");
put("NPH", "new-phyrexia");
put("ODY", "player-rewards-2002");
put("OGW", "oath-of-the-gatewatch");
put("ORG", "oath-of-the-gatewatch");
put("ORI", "magic-origins");
put("PC2", "planechase-2012-edition");
put("PO2", "portal-second-age");
put("PLS", "player-rewards-2001");
put("POR", "portal");
put("PTC", "prerelease-events");
put("PTK", "portal-three-kingdoms");
put("ROE", "rise-of-the-eldrazi");
put("RTR", "return-to-ravnica");
put("SHM", "shadowmoor");
put("SOI", "shadows-over-innistrad");
put("SOM", "scars-of-mirrodin");
put("SUS", "super-series");
put("THS", "theros");
put("TPR", "tempest-remastered");
put("UGIN", "ugins-fate");
put("V09", "from-the-vault-exiled");
put("V10", "from-the-vault-relics");
put("V11", "from-the-vault-legends");
put("V12", "from-the-vault-realms");
put("V13", "from-the-vault-twenty");
put("V14", "from-the-vault-annihilation");
put("V15", "from-the-vault-angels");
put("V16", "from-the-vault-lore");
put("VMA", "vintage-masters");
put("W16", "welcome-deck-2016");
put("W17", "welcome-deck-2017");
put("WMCQ", "world-magic-cup-qualifier");
put("WWK", "worldwake");
put("ZEN", "zendikar");
}
private static final long serialVersionUID = 1L;
};
@Override
public String getSourceName() {
return "magiccards.info";
}
@Override
public String getNextHttpImageUrl() {
return null;
}
@Override
public String getFileForHttpImage(String httpImageUrl) {
return null;
}
@Override
public CardImageUrls generateURL(CardDownloadData card) throws Exception {
String collectorId = card.getCollectorId();
String cardSet = card.getSet();
if (collectorId == null || cardSet == null) {
throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet);
}
String set = CardImageUtils.updateSet(cardSet, true);
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
StringBuilder url = new StringBuilder("http://magiccards.info/scans/").append(preferedLanguage).append('/');
url.append(set.toLowerCase(Locale.ENGLISH)).append('/').append(collectorId);
if (card.isTwoFacedCard()) {
url.append(card.isSecondSide() ? "b" : "a");
}
if (card.isSplitCard()) {
url.append('a');
}
if (card.isFlipCard()) {
if (card.isFlippedSide()) { // download rotated by 180 degree image
url.append('b');
} else {
url.append('a');
}
}
url.append(".jpg");
return new CardImageUrls(url.toString());
}
@Override
public CardImageUrls generateTokenUrl(CardDownloadData card) {
String name = card.getName();
// add type to name if it's not 0
if (card.getType() > 0) {
name = name + ' ' + card.getType();
}
name = name.replaceAll(" ", "-").replace(",", "").toLowerCase(Locale.ENGLISH);
String set = "not-supported-set";
if (setNameTokenReplacement.containsKey(card.getSet())) {
set = setNameTokenReplacement.get(card.getSet());
} else {
set += '-' + card.getSet();
}
return new CardImageUrls("http://magiccards.info/extras/token/" + set + '/' + name + ".jpg");
}
@Override
public float getAverageSize() {
return 70.0f;
}
@Override
public int getTotalImages() {
return -1;
}
@Override
public boolean isTokenSource() {
return true;
}
@Override
public ArrayList<String> getSupportedSets() {
ArrayList<String> supportedSetsCopy = new ArrayList<>();
supportedSetsCopy.addAll(supportedSets);
return supportedSetsCopy;
}
@Override
public void doPause(String httpImageUrl) {
}
}

View file

@ -1,6 +1,6 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import mage.client.dialog.PreferencesDialog; import mage.client.util.CardLanguage;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.util.*; import java.util.*;
@ -13,21 +13,23 @@ public enum ScryfallImageSource implements CardImageSource {
instance; instance;
private final Set<String> supportedSets; private final Set<String> supportedSets;
private final Map<String, String> languageAliases; private final Map<CardLanguage, String> languageAliases;
private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language
ScryfallImageSource() { ScryfallImageSource() {
// https://scryfall.com/docs/api/languages // https://scryfall.com/docs/api/languages
languageAliases = new HashMap<>(); languageAliases = new HashMap<>();
languageAliases.put("en", "en"); languageAliases.put(CardLanguage.ENGLISH, "en");
languageAliases.put("es", "es"); languageAliases.put(CardLanguage.SPANISH, "es");
languageAliases.put("jp", "ja"); languageAliases.put(CardLanguage.FRENCH, "fr");
languageAliases.put("it", "it"); languageAliases.put(CardLanguage.GERMAN, "de");
languageAliases.put("fr", "fr"); languageAliases.put(CardLanguage.ITALIAN, "it");
languageAliases.put("cn", "zhs"); // Simplified Chinese languageAliases.put(CardLanguage.PORTUGUESE, "pt");
languageAliases.put("de", "de"); languageAliases.put(CardLanguage.JAPANESE, "ja");
languageAliases.put("ko", "ko"); languageAliases.put(CardLanguage.KOREAN, "ko");
languageAliases.put("pt", "pt"); languageAliases.put(CardLanguage.RUSSIAN, "ru");
languageAliases.put("ru", "ru"); languageAliases.put(CardLanguage.CHINES_SIMPLE, "zhs");
languageAliases.put(CardLanguage.CHINES_TRADITION, "zht");
supportedSets = new LinkedHashSet<>(); supportedSets = new LinkedHashSet<>();
// supportedSets.add("PTC"); // // supportedSets.add("PTC"); //
@ -234,6 +236,7 @@ public enum ScryfallImageSource implements CardImageSource {
supportedSets.add("GNT"); supportedSets.add("GNT");
supportedSets.add("UMA"); supportedSets.add("UMA");
supportedSets.add("PUMA"); supportedSets.add("PUMA");
supportedSets.add("RNA");
// //
supportedSets.add("EURO"); supportedSets.add("EURO");
supportedSets.add("GPX"); supportedSets.add("GPX");
@ -245,9 +248,9 @@ public enum ScryfallImageSource implements CardImageSource {
@Override @Override
public CardImageUrls generateURL(CardDownloadData card) throws Exception { public CardImageUrls generateURL(CardDownloadData card) throws Exception {
String preferredLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); String preferredCode = this.getCurrentLanguage().getCode();
String defaultCode = "en"; String defaultCode = CardLanguage.ENGLISH.getCode();
String localizedCode = languageAliases.getOrDefault(preferredLanguage, defaultCode); String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode);
// loc example: https://api.scryfall.com/cards/xln/121/ru?format=image // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image
// WARNING, some cards haven't direct images and uses random GUID: // WARNING, some cards haven't direct images and uses random GUID:
@ -345,6 +348,21 @@ public enum ScryfallImageSource implements CardImageSource {
return false; return false;
} }
@Override
public boolean isLanguagesSupport() {
return true;
}
@Override
public void setCurrentLanguage(CardLanguage cardLanguage) {
this.currentLanguage = cardLanguage;
}
@Override
public CardLanguage getCurrentLanguage() {
return currentLanguage;
}
@Override @Override
public void doPause(String httpImageUrl) { public void doPause(String httpImageUrl) {
@ -368,6 +386,7 @@ public enum ScryfallImageSource implements CardImageSource {
put("WMCQ", "pwcq"); put("WMCQ", "pwcq");
put("EURO", "pelp"); put("EURO", "pelp");
put("GPX", "pgpx"); put("GPX", "pgpx");
put("MED", "me1");
} }
}; };

View file

@ -20,7 +20,7 @@ import java.util.logging.Level;
import mage.constants.SubType; import mage.constants.SubType;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.images.DownloadPictures; import org.mage.plugins.card.images.DownloadPicturesService;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
/** /**
@ -182,7 +182,7 @@ public enum TokensMtgImageSource implements CardImageSource {
private HashMap<String, ArrayList<TokenData>> getTokensData() throws IOException { private HashMap<String, ArrayList<TokenData>> getTokensData() throws IOException {
synchronized (tokensDataSync) { synchronized (tokensDataSync) {
if (tokensData == null) { if (tokensData == null) {
DownloadPictures.getInstance().updateAndViewMessage("Creating token data..."); DownloadPicturesService.getInstance().updateAndViewMessage("Find tokens data...");
tokensData = new HashMap<>(); tokensData = new HashMap<>();
// get tokens data from resource file // get tokens data from resource file
@ -233,10 +233,10 @@ public enum TokensMtgImageSource implements CardImageSource {
} }
} }
} }
DownloadPictures.getInstance().updateAndViewMessage(""); DownloadPicturesService.getInstance().updateAndViewMessage("");
} catch (Exception ex) { } catch (Exception ex) {
logger.warn("Failed to get tokens description from tokens.mtg.onl", ex); logger.warn("Failed to get tokens description from tokens.mtg.onl", ex);
DownloadPictures.getInstance().updateAndViewMessage(ex.getMessage()); DownloadPicturesService.getInstance().updateAndViewMessage(ex.getMessage());
} }
} }
} }

View file

@ -1,22 +1,10 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import mage.client.dialog.PreferencesDialog; import mage.client.util.CardLanguage;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@ -24,6 +12,12 @@ import org.jsoup.select.Elements;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/** /**
* @author North * @author North
*/ */
@ -34,9 +28,10 @@ public enum WizardCardsImageSource implements CardImageSource {
private static final Logger logger = Logger.getLogger(WizardCardsImageSource.class); private static final Logger logger = Logger.getLogger(WizardCardsImageSource.class);
private final Map<String, String> setsAliases; private final Map<String, String> setsAliases;
private final Map<String, String> languageAliases; private final Map<CardLanguage, String> languageAliases;
private final Map<String, Map<String, String>> sets; private final Map<String, Map<String, String>> sets;
private final Set<String> supportedSets; private final Set<String> supportedSets;
private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language
@Override @Override
public String getSourceName() { public String getSourceName() {
@ -44,6 +39,20 @@ public enum WizardCardsImageSource implements CardImageSource {
} }
WizardCardsImageSource() { WizardCardsImageSource() {
languageAliases = new HashMap<>();
languageAliases.put(CardLanguage.ENGLISH, "English");
languageAliases.put(CardLanguage.SPANISH, "Spanish");
languageAliases.put(CardLanguage.FRENCH, "French");
languageAliases.put(CardLanguage.GERMAN, "German");
languageAliases.put(CardLanguage.ITALIAN, "Italian");
languageAliases.put(CardLanguage.PORTUGUESE, "Portuguese (Brazil)");
languageAliases.put(CardLanguage.JAPANESE, "Japanese");
languageAliases.put(CardLanguage.KOREAN, "Korean");
languageAliases.put(CardLanguage.RUSSIAN, "Russian");
languageAliases.put(CardLanguage.CHINES_SIMPLE, "Chinese Simplified");
languageAliases.put(CardLanguage.CHINES_TRADITION, "Chinese Traditional ");
supportedSets = new LinkedHashSet<>(); supportedSets = new LinkedHashSet<>();
// supportedSets.add("PTC"); // Prerelease Events // supportedSets.add("PTC"); // Prerelease Events
supportedSets.add("LEA"); supportedSets.add("LEA");
@ -430,18 +439,6 @@ public enum WizardCardsImageSource implements CardImageSource {
setsAliases.put("WTH", "Weatherlight"); setsAliases.put("WTH", "Weatherlight");
setsAliases.put("WWK", "Worldwake"); setsAliases.put("WWK", "Worldwake");
setsAliases.put("ZEN", "Zendikar"); setsAliases.put("ZEN", "Zendikar");
languageAliases = new HashMap<>();
languageAliases.put("en", "English");
languageAliases.put("es", "Spanish");
languageAliases.put("jp", "Japanese");
languageAliases.put("it", "Italian");
languageAliases.put("fr", "French");
languageAliases.put("cn", "Chinese Simplified");
languageAliases.put("de", "German");
languageAliases.put("ko", "Korean");
languageAliases.put("pt", "Portuguese (Brazil)");
languageAliases.put("ru", "Russian");
} }
@Override @Override
@ -517,7 +514,7 @@ public enum WizardCardsImageSource implements CardImageSource {
if (setNames == null) { if (setNames == null) {
setNames = Sets.getInstance().get(cardSet).getName(); setNames = Sets.getInstance().get(cardSet).getName();
} }
String preferredLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
for (String setName : setNames.split("\\^")) { for (String setName : setNames.split("\\^")) {
// String URLSetName = URLEncoder.encode(setName, "UTF-8"); // String URLSetName = URLEncoder.encode(setName, "UTF-8");
String URLSetName = setName.replaceAll(" ", "%20"); String URLSetName = setName.replaceAll(" ", "%20");
@ -555,7 +552,7 @@ public enum WizardCardsImageSource implements CardImageSource {
cardName = cardName.substring(0, pos1); cardName = cardName.substring(0, pos1);
} }
} }
Integer preferredMultiverseId = getLocalizedMultiverseId(preferredLanguage, multiverseId); Integer preferredMultiverseId = getLocalizedMultiverseId(getCurrentLanguage(), multiverseId);
setLinks.put(cardName.toLowerCase(Locale.ENGLISH) + numberChar, generateLink(preferredMultiverseId)); setLinks.put(cardName.toLowerCase(Locale.ENGLISH) + numberChar, generateLink(preferredMultiverseId));
} }
} }
@ -617,8 +614,8 @@ public enum WizardCardsImageSource implements CardImageSource {
return "/Handlers/Image.ashx?multiverseid=" + landMultiverseId + "&type=card"; return "/Handlers/Image.ashx?multiverseid=" + landMultiverseId + "&type=card";
} }
private int getLocalizedMultiverseId(String preferredLanguage, Integer multiverseId) throws IOException { private int getLocalizedMultiverseId(CardLanguage preferredLanguage, Integer multiverseId) throws IOException {
if (preferredLanguage.equals("en")) { if (preferredLanguage.equals(CardLanguage.ENGLISH)) {
return multiverseId; return multiverseId;
} }
@ -682,43 +679,6 @@ public enum WizardCardsImageSource implements CardImageSource {
return 60.0f; return 60.0f;
} }
// private final class GetImageLinkTask implements Runnable {
//
// private int multiverseId;
// private String cardName;
// private String preferredLanguage;
// private LinkedHashMap setLinks;
//
// public GetImageLinkTask(int multiverseId, String cardName, String preferredLanguage, LinkedHashMap setLinks) {
// try {
// this.multiverseId = multiverseId;
// this.cardName = cardName;
// this.preferredLanguage = preferredLanguage;
// this.setLinks = setLinks;
// } catch (Exception ex) {
// logger.error(ex.getMessage());
// logger.error("multiverseId: " + multiverseId);
// logger.error("cardName: " + cardName);
// logger.error("preferredLanguage: " + preferredLanguage);
// logger.error("setLinks: " + setLinks.toString());
// }
// }
//
// @Override
// public void run() {
// try {
// if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) {
// setLinks.putAll(getLandVariations(multiverseId, cardName));
// } else {
// Integer preferredMultiverseId = getLocalizedMultiverseId(preferredLanguage, multiverseId);
// setLinks.put(cardName.toLowerCase(Locale.ENGLISH), generateLink(preferredMultiverseId));
// }
// } catch (IOException | NumberFormatException ex) {
// logger.error("Exception when parsing the wizards page: " + ex.getMessage());
// }
// }
//
// }
@Override @Override
public int getTotalImages() { public int getTotalImages() {
return -1; return -1;
@ -729,6 +689,21 @@ public enum WizardCardsImageSource implements CardImageSource {
return false; return false;
} }
@Override
public boolean isLanguagesSupport() {
return true;
}
@Override
public void setCurrentLanguage(CardLanguage cardLanguage) {
this.currentLanguage = cardLanguage;
}
@Override
public CardLanguage getCurrentLanguage() {
return currentLanguage;
}
@Override @Override
public void doPause(String httpImageUrl) { public void doPause(String httpImageUrl) {
} }

View file

@ -1,28 +1,14 @@
package org.mage.plugins.card.images; package org.mage.plugins.card.images;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.io.*;
import java.net.*;
import java.nio.file.AccessDeniedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.dialog.DownloadImagesDialog;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import mage.client.util.CardLanguage;
import mage.client.util.sets.ConstructedFormats; import mage.client.util.sets.ConstructedFormats;
import mage.remote.Connection; import mage.remote.Connection;
import mage.util.StreamUtils; import mage.util.StreamUtils;
@ -35,46 +21,49 @@ import org.mage.plugins.card.dl.sources.*;
import org.mage.plugins.card.properties.SettingsManager; import org.mage.plugins.card.properties.SettingsManager;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.io.*;
import java.net.*;
import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable { /**
* @author JayDi85
*/
public class DownloadPicturesService extends DefaultBoundedRangeModel implements Runnable {
// don't forget to remove new sets from ignore.urls to download (propeties file in resources) // don't forget to remove new sets from ignore.urls to download (properties file in resources)
private static DownloadPictures instance; private static DownloadPicturesService instance;
private static final Logger logger = Logger.getLogger(DownloadPicturesService.class);
private static final Logger logger = Logger.getLogger(DownloadPictures.class); public static final String ALL_IMAGES = "- ALL images from selected source (can be slow)";
public static final String ALL_MODERN_IMAGES = "- MODERN images (can be slow)";
public static final String ALL_STANDARD_IMAGES = "- STANDARD images";
public static final String ALL_TOKENS = "- TOKEN images";
public static final String ALL_IMAGES = "- ALL images from selected source (CAN BE VERY SLOW)"; private DownloadImagesDialog uiDialog;
public static final String ALL_STANDARD_IMAGES = "- Only images from STANDARD sets"; private boolean needCancel;
public static final String ALL_TOKENS = "- Only token images from selected source";
private JDialog dialog;
private final JProgressBar bar;
private final JOptionPane dlg;
private boolean cancel;
private final JButton closeButton;
private final JButton startDownloadButton;
private int cardIndex; private int cardIndex;
private List<CardDownloadData> allCardsMissingImage;
private List<CardDownloadData> cardsToDownload;
private int missingCards = 0; private List<CardInfo> cardsAll;
private int missingTokens = 0; private List<CardDownloadData> cardsMissing;
private List<CardDownloadData> cardsDownloadQueue;
private int missingCardsCount = 0;
private int missingTokensCount = 0;
List<String> selectedSetCodes = new ArrayList<>(); List<String> selectedSets = new ArrayList<>();
private static CardImageSource selectedSource;
private final JComboBox jComboBoxServer;
private final JLabel jLabelMessage;
private final JLabel jLabelAllMissing;
private final JLabel jLabelServer;
private final JComboBox jComboBoxSet;
private final JLabel jLabelSet;
private final Object sync = new Object(); private final Object sync = new Object();
private static CardImageSource cardImageSource;
private Proxy p = Proxy.NO_PROXY; private Proxy p = Proxy.NO_PROXY;
enum DownloadSources { enum DownloadSources {
@ -87,7 +76,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
ALTERNATIVE("7. alternative.mtg.onl", AltMtgOnlTokensImageSource.instance), ALTERNATIVE("7. alternative.mtg.onl", AltMtgOnlTokensImageSource.instance),
COPYPASTE("8. Copy and Paste Image URLs", CopyPasteImageSource.instance); COPYPASTE("8. Copy and Paste Image URLs", CopyPasteImageSource.instance);
// MTG_ONL("mtg.onl", MtgOnlTokensImageSource.instance), Not working correctly yet // MTG_ONL("mtg.onl", MtgOnlTokensImageSource.instance), Not working correctly yet
// MAGICCARDS("magiccards.info", MagicCardsImageSource.instance)
private final String text; private final String text;
private final CardImageSource source; private final CardImageSource source;
@ -108,7 +96,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
public static DownloadPictures getInstance() { public static DownloadPicturesService getInstance() {
return instance; return instance;
} }
@ -117,245 +105,245 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
public static void startDownload() { public static void startDownload() {
// load images info in background task
instance = new DownloadPicturesService(MageFrame.getInstance());
new Thread(new LoadMissingCardDataNew(instance)).start();
/* // show dialog
* if (cards == null || cards.isEmpty()) { instance.setNeedCancel(false);
* JOptionPane.showMessageDialog(null, instance.uiDialog.showDialog();
* "All card pictures have been downloaded."); return; } instance.uiDialog.dispose();
*/ instance.setNeedCancel(true);
instance = new DownloadPictures(MageFrame.getInstance());
Thread t1 = new Thread(new LoadMissingCardData(instance));
t1.start();
instance.getDlg().setVisible(true);
instance.getDlg().dispose();
instance.cancel = true;
} }
public JDialog getDlg() { public boolean getNeedCancel() {
return dialog; return this.needCancel;
} }
public void setCancel(boolean cancel) { public void setNeedCancel(boolean needCancel) {
this.cancel = cancel; this.needCancel = needCancel;
} }
static int WIDTH = 400; public DownloadPicturesService(JFrame frame) {
// init service and dialog
cardsAll = Collections.synchronizedList(new ArrayList<>());
cardsMissing = Collections.synchronizedList(new ArrayList<>());
cardsDownloadQueue = Collections.synchronizedList(new ArrayList<>());
uiDialog = new DownloadImagesDialog();
public DownloadPictures(JFrame frame) { // MESSAGE
uiDialog.setGlobalInfo("Initializing image download...");
cardsToDownload = new ArrayList<>(); // SOURCES - scryfall is default source
uiDialog.getSourcesCombo().setModel(new DefaultComboBoxModel(DownloadSources.values()));
JPanel p0 = new JPanel(); uiDialog.getSourcesCombo().setSelectedItem(DownloadSources.SCRYFALL);
p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS)); selectedSource = ScryfallImageSource.instance;
uiDialog.getSourcesCombo().addItemListener((ItemEvent event) -> {
p0.add(Box.createVerticalStrut(5));
jLabelMessage = new JLabel();
jLabelMessage.setAlignmentX(Component.CENTER_ALIGNMENT);
jLabelMessage.setText("Initializing image download...");
p0.add(jLabelMessage);
p0.add(Box.createVerticalStrut(5));
jLabelAllMissing = new JLabel();
jLabelAllMissing.setAlignmentX(Component.LEFT_ALIGNMENT);
// jLabelAllMissing.setText("Computing number of missing images...");
p0.add(jLabelAllMissing);
p0.add(Box.createVerticalStrut(5));
jLabelServer = new JLabel();
jLabelServer.setText("Please select image source:");
jLabelServer.setAlignmentX(Component.LEFT_ALIGNMENT);
jLabelServer.setVisible(false);
p0.add(jLabelServer);
p0.add(Box.createVerticalStrut(5));
jComboBoxServer = new JComboBox();
jComboBoxServer.setModel(new DefaultComboBoxModel(DownloadSources.values()));
jComboBoxServer.setAlignmentX(Component.LEFT_ALIGNMENT);
jComboBoxServer.setAlignmentY(Component.LEFT_ALIGNMENT);
jComboBoxServer.addItemListener((ItemEvent event) -> {
if (event.getStateChange() == ItemEvent.SELECTED) { if (event.getStateChange() == ItemEvent.SELECTED) {
comboBoxServerItemSelected(event); comboboxSourceSelected(event);
}
});
Dimension d = jComboBoxServer.getPreferredSize();
d.width = WIDTH;
jComboBoxServer.setPreferredSize(d);
p0.add(jComboBoxServer);
jComboBoxServer.setVisible(false);
// set the first source as default
cardImageSource = WizardCardsImageSource.instance;
p0.add(Box.createVerticalStrut(5));
// Set selection ---------------------------------
jLabelSet = new JLabel();
jLabelSet.setText("Please select sets to download the images for:");
jLabelSet.setAlignmentX(Component.LEFT_ALIGNMENT);
jLabelSet.setVisible(false);
p0.add(jLabelSet);
jComboBoxSet = new JComboBox();
// jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
jComboBoxSet.setAlignmentX(Component.LEFT_ALIGNMENT);
jComboBoxSet.addItemListener((ItemEvent event) -> {
if (event.getStateChange() == ItemEvent.SELECTED) {
comboBoxSetItemSelected(event);
} }
}); });
p0.add(jComboBoxSet); // LANGUAGES
jComboBoxSet.setVisible(false); uiDialog.getLaunguagesCombo().setModel(new DefaultComboBoxModel(CardLanguage.values()));
uiDialog.getLaunguagesCombo().setSelectedItem(PreferencesDialog.getPrefImagesLanguage());
reloadLanguagesForSelectedSource();
p0.add(Box.createVerticalStrut(5)); // REDOWNLOAD
uiDialog.getRedownloadCheckbox().setSelected(false);
uiDialog.getRedownloadCheckbox().addItemListener(this::checkboxRedowloadChanged);
// Start
startDownloadButton = new JButton("Start download"); // SETS (fills after source and language select)
startDownloadButton.addActionListener(e -> { //uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel(DownloadSources.values()));
new Thread(DownloadPictures.this).start(); uiDialog.getSetsCombo().addItemListener((ItemEvent event) -> {
startDownloadButton.setEnabled(false); if (event.getStateChange() == ItemEvent.SELECTED) {
comboboxSetSelected(event);
}
}); });
p0.add(Box.createVerticalStrut(5));
// Progress // BUTTON START
bar = new JProgressBar(this); uiDialog.getStartButton().addActionListener(e -> {
p0.add(bar); // selected language setup
bar.setStringPainted(true); if (selectedSource != null) {
if (selectedSource.isLanguagesSupport()) {
selectedSource.setCurrentLanguage((CardLanguage) uiDialog.getLaunguagesCombo().getSelectedItem());
}
}
d = bar.getPreferredSize(); // run
d.width = WIDTH; uiDialog.enableActionControls(false);
bar.setPreferredSize(d); uiDialog.getStartButton().setEnabled(false);
bar.setVisible(false); new Thread(DownloadPicturesService.this).start();
});
// JOptionPane // BUTTON CANCEL (dialog and loading)
Object[] options = {startDownloadButton, closeButton = new JButton("Cancel")}; uiDialog.getCancelButton().addActionListener(e -> uiDialog.setVisible(false));
startDownloadButton.setVisible(false); uiDialog.getStopButton().addActionListener(e -> uiDialog.setVisible(false));
closeButton.addActionListener(e -> dialog.setVisible(false));
closeButton.setVisible(false);
dlg = new JOptionPane(p0, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]); // PROGRESS BAR
dialog = this.dlg.createDialog(frame, "Downloading images"); uiDialog.getProgressBar().setValue(0);
uiDialog.showDownloadControls(false);
} }
public void setAllMissingCards() { public void findMissingCards() {
updateAndViewMessage("Get all available cards from the repository..."); updateAndViewMessage("Loading...");
List<CardInfo> cards = CardRepository.instance.findCards(new CardCriteria()); this.cardsAll.clear();
updateAndViewMessage("Check which images are missing ..."); this.cardsMissing.clear();
this.allCardsMissingImage = getNeededCards(cards); this.cardsDownloadQueue.clear();
updateAndViewMessage("Check which images the current source is providing ...");
jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString()); updateAndViewMessage("Loading cards list...");
this.cardsAll = Collections.synchronizedList(CardRepository.instance.findCards(new CardCriteria()));
jComboBoxServer.setVisible(true); updateAndViewMessage("Finding missing images...");
jLabelServer.setVisible(true); this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected());
jComboBoxSet.setVisible(true);
jLabelSet.setVisible(true);
bar.setVisible(true);
startDownloadButton.setVisible(true);
closeButton.setVisible(true);
updateAndViewMessage("Finding available sets from selected source...");
this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString());
this.uiDialog.showDownloadControls(true);
updateAndViewMessage(""); updateAndViewMessage("");
} }
private void comboBoxServerItemSelected(ItemEvent evt) { private void reloadLanguagesForSelectedSource() {
if (jComboBoxServer.isEnabled()) { this.uiDialog.showLanguagesSupport(selectedSource != null && selectedSource.isLanguagesSupport());
cardImageSource = ((DownloadSources) evt.getItem()).getSource(); }
// update the available sets / token comboBox
jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); private void reloadSetsForSelectedSource() {
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString()); // update the available sets / token combobox
Object oldSelection = this.uiDialog.getSetsCombo().getSelectedItem();
this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
if (oldSelection != null) {
this.uiDialog.getSetsCombo().setSelectedItem(oldSelection);
}
reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString());
}
private void comboboxSourceSelected(ItemEvent evt) {
if (this.uiDialog.getSourcesCombo().isEnabled()) {
selectedSource = ((DownloadSources) evt.getItem()).getSource();
reloadSetsForSelectedSource();
reloadLanguagesForSelectedSource();
} }
} }
public void updateAndViewMessage(String text) { public void updateAndViewMessage(String text) {
jLabelMessage.setText(text); this.uiDialog.setGlobalInfo(text);
if (dialog != null) {
dialog.pack(); // auto-size on empty message (on complete)
dialog.validate(); if (text.isEmpty()) {
dialog.repaint(); this.uiDialog.showDownloadControls(true);
} }
} }
private String getSetNameWithYear(ExpansionSet exp) {
Calendar cal = Calendar.getInstance();
cal.setTime(exp.getReleaseDate());
String year = String.valueOf(cal.get(Calendar.YEAR));
return exp.getName() + " (" + exp.getCode() + ", " + year + ")";
/*
if (!exp.getName().contains(year)) {
return exp.getName() + " (" + year + ")";
} else {
return exp.getName();
}
*/
}
private ExpansionSet findSetByNameWithYear(String name) {
return Sets.getInstance().values().stream()
.filter(exp -> getSetNameWithYear(exp).equals(name))
.findFirst()
.orElse(null);
}
private Object[] getSetsForCurrentImageSource() { private Object[] getSetsForCurrentImageSource() {
// Set the available sets to the combo box // Set the available sets to the combo box
ArrayList<String> supportedSets = cardImageSource.getSupportedSets(); ArrayList<String> supportedSets = selectedSource.getSupportedSets();
List<String> setNames = new ArrayList<>(); List<String> setNames = new ArrayList<>();
if (supportedSets != null) {
setNames.add(ALL_IMAGES); // multiple sets selection
setNames.add(ALL_STANDARD_IMAGES); setNames.add(ALL_IMAGES);
} setNames.add(ALL_MODERN_IMAGES);
if (cardImageSource.isTokenSource()) { setNames.add(ALL_STANDARD_IMAGES);
if (selectedSource.isTokenSource()) {
setNames.add(ALL_TOKENS); setNames.add(ALL_TOKENS);
} }
if (supportedSets != null) {
for (String setCode : supportedSets) {
ExpansionSet expansionSet = Sets.findSet(setCode);
if (expansionSet != null) {
setNames.add(expansionSet.getName());
} else {
logger.warn("Source: " + cardImageSource.getSourceName() + ": Expansion set for code " + setCode + " not found in xmage sets!");
}
}
} // single set selection
Collection<ExpansionSet> dbSets = Sets.getInstance().values();
Collection<String> comboSets = dbSets.stream()
.filter(exp -> supportedSets.contains(exp.getCode()))
.sorted(Comparator.comparing(ExpansionSet::getReleaseDate).reversed())
.map(this::getSetNameWithYear)
.collect(Collectors.toList());
setNames.addAll(comboSets);
if (setNames.isEmpty()) { if (setNames.isEmpty()) {
logger.error("Source " + cardImageSource.getSourceName() + " creates no selectable items."); logger.error("Source " + selectedSource.getSourceName() + " creates no selectable items.");
setNames.add("not avalable"); setNames.add("not available");
} }
return setNames.toArray(new String[0]); return setNames.toArray(new String[0]);
} }
private void updateCardsToDownload(String itemText) { private void reloadCardsToDownload(String selectedItem) {
selectedSetCodes.clear(); // find selected sets
switch (itemText) { selectedSets.clear();
List<String> formatSets;
List<String> sourceSets = selectedSource.getSupportedSets();
switch (selectedItem) {
case ALL_IMAGES: case ALL_IMAGES:
if (cardImageSource.getSupportedSets() == null) { selectedSets.addAll(selectedSource.getSupportedSets());
selectedSetCodes = cardImageSource.getSupportedSets();
} else {
selectedSetCodes.addAll(cardImageSource.getSupportedSets());
}
break; break;
case ALL_STANDARD_IMAGES: case ALL_STANDARD_IMAGES:
List<String> standardSets = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD); formatSets = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD);
for (String setCode : cardImageSource.getSupportedSets()) { formatSets.stream()
if (standardSets.contains(setCode)) { .filter(sourceSets::contains)
selectedSetCodes.add(setCode); .forEachOrdered(selectedSets::add);
} else {
logger.debug("Set code " + setCode + " from download source " + cardImageSource.getSourceName());
}
}
break; break;
case ALL_MODERN_IMAGES:
formatSets = ConstructedFormats.getSetsByFormat(ConstructedFormats.MODERN);
formatSets.stream()
.filter(sourceSets::contains)
.forEachOrdered(selectedSets::add);
break;
case ALL_TOKENS: case ALL_TOKENS:
break; break;
default: default:
int nonSetEntries = 0; // selects one set
if (cardImageSource.getSupportedSets() != null) { ExpansionSet selectedExp = findSetByNameWithYear(selectedItem);
nonSetEntries = 2; if (selectedExp != null) {
selectedSets.add(selectedExp.getCode());
} }
if (cardImageSource.isTokenSource()) { break;
nonSetEntries++;
}
selectedSetCodes.add(cardImageSource.getSupportedSets().get(jComboBoxSet.getSelectedIndex() - nonSetEntries));
} }
cardsToDownload.clear();
// find missing cards to download
cardsDownloadQueue.clear();
int numberTokenImagesAvailable = 0; int numberTokenImagesAvailable = 0;
int numberCardImagesAvailable = 0; int numberCardImagesAvailable = 0;
for (CardDownloadData data : allCardsMissingImage) { for (CardDownloadData data : cardsMissing) {
if (data.isToken()) { if (data.isToken()) {
if (cardImageSource.isTokenSource() && cardImageSource.isImageProvided(data.getSet(), data.getName())) { if (selectedSource.isTokenSource() && selectedSource.isImageProvided(data.getSet(), data.getName())) {
numberTokenImagesAvailable++; numberTokenImagesAvailable++;
cardsToDownload.add(data); cardsDownloadQueue.add(data);
} else { } else {
//logger.warn("Source do not support token (set " + data.getSet() + ", token " + data.getName() + ")"); //logger.warn("Source do not support token (set " + data.getSet() + ", token " + data.getName() + ")");
} }
} else { } else {
if (selectedSetCodes != null && selectedSetCodes.contains(data.getSet())) { if (selectedSets != null && selectedSets.contains(data.getSet())) {
if (cardImageSource.isSetSupportedComplete(data.getSet()) || cardImageSource.isImageProvided(data.getSet(), data.getName())) { if (selectedSource.isSetSupportedComplete(data.getSet()) || selectedSource.isImageProvided(data.getSet(), data.getName())) {
numberCardImagesAvailable++; numberCardImagesAvailable++;
cardsToDownload.add(data); cardsDownloadQueue.add(data);
} }
} }
} }
@ -363,24 +351,40 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
updateProgressText(numberCardImagesAvailable, numberTokenImagesAvailable); updateProgressText(numberCardImagesAvailable, numberTokenImagesAvailable);
} }
private void comboBoxSetItemSelected(ItemEvent event) { private void comboboxSetSelected(ItemEvent event) {
// Update the cards to download related to the selected set // Update the cards to download related to the selected set
updateCardsToDownload(event.getItem().toString()); reloadCardsToDownload(event.getItem().toString());
}
private void checkboxRedowloadChanged(ItemEvent event) {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
this.cardsMissing.clear();
this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected());
reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString());
} finally {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
} }
private void updateProgressText(int cardCount, int tokenCount) { private void updateProgressText(int cardCount, int tokenCount) {
missingTokens = 0; missingTokensCount = 0;
for (CardDownloadData card : allCardsMissingImage) { for (CardDownloadData card : cardsMissing) {
if (card.isToken()) { if (card.isToken()) {
missingTokens++; missingTokensCount++;
} }
} }
missingCards = allCardsMissingImage.size() - missingTokens; missingCardsCount = cardsMissing.size() - missingTokensCount;
jLabelAllMissing.setText("Missing: " + missingCards + " card images / " + missingTokens + " token images");
uiDialog.setCurrentInfo("Missing: " + missingCardsCount + " card images / " + missingTokensCount + " token images");
int imageSum = cardCount + tokenCount; int imageSum = cardCount + tokenCount;
float mb = (imageSum * cardImageSource.getAverageSize()) / 1024; float mb = (imageSum * selectedSource.getAverageSize()) / 1024;
bar.setString(String.format(cardIndex == imageSum ? "%d of %d (%d cards/%d tokens) image downloads finished! Please close!" uiDialog.getProgressBar().setString(String.format(
: "%d of %d (%d cards/%d tokens) image downloads finished! Please wait! [%.1f Mb]", 0, imageSum, cardCount, tokenCount, mb)); cardIndex == imageSum
? "%d of %d (%d cards/%d tokens) image downloads finished! Please close!"
: "%d of %d (%d cards/%d tokens) image downloads finished! Please wait! [%.1f Mb]",
0, imageSum, cardCount, tokenCount, mb
));
} }
private static String createDownloadName(CardInfo card) { private static String createDownloadName(CardInfo card) {
@ -388,16 +392,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
return className.substring(className.lastIndexOf('.') + 1); return className.substring(className.lastIndexOf('.') + 1);
} }
private static List<CardDownloadData> getNeededCards(List<CardInfo> allCards) { private static List<CardDownloadData> prepareMissingCards(List<CardInfo> allCards, boolean redownloadMode) {
/**
* read all card names and urls
*/
HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls(); HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
/** // get filter for Standard Type 2 cards
* get filter for Standard Type 2 cards
*/
Set<String> type2SetsFilter = new HashSet<>(); Set<String> type2SetsFilter = new HashSet<>();
List<String> constructedFormats = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD); List<String> constructedFormats = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD);
if (constructedFormats != null && !constructedFormats.isEmpty()) { if (constructedFormats != null && !constructedFormats.isEmpty()) {
@ -406,6 +404,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
logger.warn("No formats defined. Try connecting to a server first!"); logger.warn("No formats defined. Try connecting to a server first!");
} }
// prepare checking list
List<CardDownloadData> allCardsUrls = Collections.synchronizedList(new ArrayList<>()); List<CardDownloadData> allCardsUrls = Collections.synchronizedList(new ArrayList<>());
try { try {
allCards.parallelStream().forEach(card -> { allCards.parallelStream().forEach(card -> {
@ -455,32 +454,33 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
logger.info("Card was not selected: " + card.getName()); logger.info("Card was not selected: " + card.getName());
} }
}); });
allCardsUrls.addAll(getTokenCardUrls()); allCardsUrls.addAll(getTokenCardUrls());
} catch (Exception e) { } catch (Exception e) {
logger.error(e); logger.error(e);
} }
/** // find missing files
* check to see which cards we already have
*/
List<CardDownloadData> cardsToDownload = Collections.synchronizedList(new ArrayList<>()); List<CardDownloadData> cardsToDownload = Collections.synchronizedList(new ArrayList<>());
allCardsUrls.parallelStream().forEach(card -> { allCardsUrls.parallelStream().forEach(card -> {
File file = new TFile(CardImageUtils.buildImagePathToCard(card)); if (redownloadMode) {
logger.debug(card.getName() + " (is_token=" + card.isToken() + "). Image is here:" + file.getAbsolutePath() + " (exists=" + file.exists() + ')'); // need all cards
if (!file.exists()) {
logger.debug("Missing: " + file.getAbsolutePath());
// logger.info("Missing image: " + (card.isToken() ? "TOKEN " : "CARD ") + card.getSet() + "/" + card.getName() + " type: " + card.getType());
cardsToDownload.add(card); cardsToDownload.add(card);
} else {
// need missing cards
File file = new TFile(CardImageUtils.buildImagePathToCard(card));
if (!file.exists()) {
cardsToDownload.add(card);
}
} }
}); });
return new ArrayList<>(cardsToDownload); return Collections.synchronizedList(new ArrayList<>(cardsToDownload));
} }
public static ArrayList<CardDownloadData> getTokenCardUrls() throws RuntimeException { public static ArrayList<CardDownloadData> getTokenCardUrls() throws RuntimeException {
ArrayList<CardDownloadData> list = new ArrayList<>(); ArrayList<CardDownloadData> list = new ArrayList<>();
InputStream in = DownloadPictures.class InputStream in = DownloadPicturesService.class.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
if (in == null) { if (in == null) {
logger.error("resources input stream is null"); logger.error("resources input stream is null");
@ -545,7 +545,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} catch (Exception ex) { } catch (Exception ex) {
logger.error(ex); logger.error(ex);
throw new RuntimeException("DownloadPictures : readFile() error"); throw new RuntimeException("DownloadPicturesService : readFile() error");
} }
return list; return list;
} }
@ -581,62 +581,62 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80")); Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80"));
p = new Proxy(type, new InetSocketAddress(address, port)); p = new Proxy(type, new InetSocketAddress(address, port));
} catch (Exception ex) { } catch (Exception ex) {
throw new RuntimeException("Gui_DownloadPictures : error 1 - " + ex); throw new RuntimeException("Gui_DownloadPicturesService : error 1 - " + ex);
} }
} }
if (p != null) { if (p != null) {
HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls(); HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
update(0, cardsToDownload.size()); update(0, cardsDownloadQueue.size());
logger.info("Started download of " + cardsToDownload.size() + " images from source: " + cardImageSource.getSourceName()); logger.info("Started download of " + cardsDownloadQueue.size() + " images"
+ " from source: " + selectedSource.getSourceName()
+ ", language: " + selectedSource.getCurrentLanguage().getCode());
int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10")); int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10"));
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < cardsToDownload.size() && !cancel; i++) { for (int i = 0; i < cardsDownloadQueue.size() && !this.getNeedCancel(); i++) {
try { try {
CardDownloadData card = cardsDownloadQueue.get(i);
CardDownloadData card = cardsToDownload.get(i);
logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')'); logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')');
CardImageUrls urls; CardImageUrls urls;
if (ignoreUrls.contains(card.getSet()) || card.isToken()) { if (ignoreUrls.contains(card.getSet()) || card.isToken()) {
if (!"0".equals(card.getCollectorId())) { if (!"0".equals(card.getCollectorId())) {
continue; continue;
} }
urls = cardImageSource.generateTokenUrl(card); urls = selectedSource.generateTokenUrl(card);
} else { } else {
urls = cardImageSource.generateURL(card); urls = selectedSource.generateURL(card);
} }
if (urls == null) { if (urls == null) {
String imageRef = cardImageSource.getNextHttpImageUrl(); String imageRef = selectedSource.getNextHttpImageUrl();
String fileName = cardImageSource.getFileForHttpImage(imageRef); String fileName = selectedSource.getFileForHttpImage(imageRef);
if (imageRef != null && fileName != null) { if (imageRef != null && fileName != null) {
imageRef = cardImageSource.getSourceName() + imageRef; imageRef = selectedSource.getSourceName() + imageRef;
try { try {
card.setToken(cardImageSource.isTokenSource()); card.setToken(selectedSource.isTokenSource());
Runnable task = new DownloadTask(card, imageRef, fileName, cardImageSource.getTotalImages()); Runnable task = new DownloadTask(card, imageRef, fileName, selectedSource.getTotalImages());
executor.execute(task); executor.execute(task);
} catch (Exception ex) { } catch (Exception ex) {
} }
} else if (cardImageSource.getTotalImages() == -1) { } else if (selectedSource.getTotalImages() == -1) {
logger.info("Image not available on " + cardImageSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')'); logger.info("Image not available on " + selectedSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')');
synchronized (sync) { synchronized (sync) {
update(cardIndex + 1, cardsToDownload.size()); update(cardIndex + 1, cardsDownloadQueue.size());
} }
} }
} else { } else {
Runnable task = new DownloadTask(card, urls, cardsToDownload.size()); Runnable task = new DownloadTask(card, urls, cardsDownloadQueue.size());
executor.execute(task); executor.execute(task);
} }
} catch (Exception ex) { } catch (Exception ex) {
logger.error(ex, ex); logger.error(ex, ex);
} }
} }
executor.shutdown(); executor.shutdown();
while (!executor.isTerminated()) { while (!executor.isTerminated()) {
try { try {
@ -645,6 +645,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
} }
} }
try { try {
TVFS.umount(); TVFS.umount();
} catch (FsSyncException e) { } catch (FsSyncException e) {
@ -653,11 +654,15 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} finally { } finally {
// //
} }
closeButton.setText("Close");
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString()); // stop
reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString());
// reset images cache
ImageCache.clearCache();
} }
static String convertStreamToString(java.io.InputStream is) { static String convertStreamToString(InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : ""; return s.hasNext() ? s.next() : "";
} }
@ -670,10 +675,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
private final String actualFilename; private final String actualFilename;
private final boolean useSpecifiedPaths; private final boolean useSpecifiedPaths;
DownloadTask(CardDownloadData card, String baseUrl, int count) {
this(card, new CardImageUrls(baseUrl, null), count);
}
DownloadTask(CardDownloadData card, CardImageUrls urls, int count) { DownloadTask(CardDownloadData card, CardImageUrls urls, int count) {
this.card = card; this.card = card;
this.urls = urls; this.urls = urls;
@ -692,7 +693,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
@Override @Override
public void run() { public void run() {
if (cancel) { if (DownloadPicturesService.getInstance().getNeedCancel()) {
synchronized (sync) { synchronized (sync) {
update(cardIndex + 1, count); update(cardIndex + 1, count);
} }
@ -736,20 +737,23 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
// FILE already exists (in zip or in dir) // FILE already exists (in zip or in dir)
// don't use, images can be re-downloaded
/*
if (destFile.exists()) { if (destFile.exists()) {
synchronized (sync) { synchronized (sync) {
update(cardIndex + 1, count); update(cardIndex + 1, count);
} }
return; return;
} }
*/
// zip can't be read // check zip access
TFile testArchive = destFile.getTopLevelArchive(); TFile testArchive = destFile.getTopLevelArchive();
if (testArchive != null && testArchive.exists()) { if (testArchive != null && testArchive.exists()) {
try { try {
testArchive.list(); testArchive.list();
} catch (Exception e) { } catch (Exception e) {
logger.error("Error reading archive, may be it was corrapted. Try to delete it: " + testArchive.toString()); logger.error("Error reading archive, it's can be corrupted. Try to delete it: " + testArchive.toString());
synchronized (sync) { synchronized (sync) {
update(cardIndex + 1, count); update(cardIndex + 1, count);
@ -773,12 +777,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
URL url = new URL(currentUrl); URL url = new URL(currentUrl);
// on download cancel need to stop // on download cancel need to stop
if (cancel) { if (DownloadPicturesService.getInstance().getNeedCancel()) {
return; return;
} }
// download // download
cardImageSource.doPause(url.getPath()); selectedSource.doPause(url.getPath());
httpConn = url.openConnection(p); httpConn = url.openConnection(p);
httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
httpConn.connect(); httpConn.connect();
@ -819,7 +823,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
int len; int len;
while ((len = in.read(buf)) != -1) { while ((len = in.read(buf)) != -1) {
// user cancelled // user cancelled
if (cancel) { if (DownloadPicturesService.getInstance().getNeedCancel()) {
// stop download, save current state and exit // stop download, save current state and exit
TFile archive = destFile.getTopLevelArchive(); TFile archive = destFile.getTopLevelArchive();
///* not need to unmout/close - it's auto action ///* not need to unmout/close - it's auto action
@ -881,34 +885,38 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
} }
private void update(int card, int count) { private void update(int lastCardIndex, int needDownloadCount) {
this.cardIndex = card; this.cardIndex = lastCardIndex;
if (cardIndex < count) { if (cardIndex < needDownloadCount) {
float mb = ((count - card) * cardImageSource.getAverageSize()) / 1024; // downloading
bar.setString(String.format("%d of %d image downloads finished! Please wait! [%.1f Mb]", float mb = ((needDownloadCount - lastCardIndex) * selectedSource.getAverageSize()) / 1024;
card, count, mb)); uiDialog.getProgressBar().setString(String.format("%d of %d image downloads finished! Please wait! [%.1f Mb]",
lastCardIndex, needDownloadCount, mb));
} else { } else {
List<CardDownloadData> remainingCards = Collections.synchronizedList(new ArrayList<>()); // finished
DownloadPictures.this.allCardsMissingImage.parallelStream().forEach(cardDownloadData -> { List<CardDownloadData> downloadedCards = Collections.synchronizedList(new ArrayList<>());
DownloadPicturesService.this.cardsMissing.parallelStream().forEach(cardDownloadData -> {
TFile file = new TFile(CardImageUtils.buildImagePathToCard(cardDownloadData)); TFile file = new TFile(CardImageUtils.buildImagePathToCard(cardDownloadData));
if (!file.exists()) { if (file.exists()) {
remainingCards.add(cardDownloadData); downloadedCards.add(cardDownloadData);
} }
}); });
// remove the cards not downloaded to get the siccessfull downloaded cards // remove all downloaded cards, missing must be remains
DownloadPictures.this.cardsToDownload.removeAll(remainingCards); this.cardsDownloadQueue.removeAll(downloadedCards);
DownloadPictures.this.allCardsMissingImage.removeAll(DownloadPictures.this.cardsToDownload); this.cardsMissing.removeAll(downloadedCards);
count = remainingCards.size(); if (this.cardsDownloadQueue.size() == 0) {
// stop download
if (count == 0) { uiDialog.getProgressBar().setString("0 images remaining. Please close.");
bar.setString("0 images remaining! Please close!");
} else { } else {
// bar.setString(String.format("%d cards remaining! Please choose another source!", count)); // try download again
startDownloadButton.setEnabled(true);
} }
this.uiDialog.getRedownloadCheckbox().setSelected(false);
uiDialog.enableActionControls(true);
uiDialog.getStartButton().setEnabled(true);
} }
} }
@ -916,22 +924,21 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
} }
class LoadMissingCardData implements Runnable { class LoadMissingCardDataNew implements Runnable {
private static DownloadPictures downloadPictures; private static DownloadPicturesService downloadPicturesService;
public LoadMissingCardData(DownloadPictures downloadPictures) { public LoadMissingCardDataNew(DownloadPicturesService downloadPicturesService) {
LoadMissingCardData.downloadPictures = downloadPictures; this.downloadPicturesService = downloadPicturesService;
} }
@Override @Override
public void run() { public void run() {
downloadPictures.setAllMissingCards(); downloadPicturesService.findMissingCards();
} }
public static void main() { public static void main() {
(new Thread(new LoadMissingCardDataNew(downloadPicturesService))).start();
(new Thread(new LoadMissingCardData(downloadPictures))).start();
} }
} }

View file

@ -3,15 +3,6 @@ package org.mage.plugins.card.images;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ComputationException; import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import mage.client.constants.Constants; import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import mage.client.util.TransformedImageCache; import mage.client.util.TransformedImageCache;
@ -23,13 +14,23 @@ import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.sources.DirectLinksForDownload; import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* This class stores ALL card images in a cache with soft values. this means * This class stores ALL card images in a cache with soft values. this means
* that the images may be garbage collected when they are not needed any more, * that the images may be garbage collected when they are not needed any more,
* but will be kept as long as possible. * but will be kept as long as possible.
* * <p>
* Key format: "[cardname]#[setname]#[type]#[collectorID]#[param]" * Key format: "[cardname]#[setname]#[type]#[collectorID]#[param]"
* * <p>
* where param is: * where param is:
* <ul> * <ul>
* <li>size of image</li> * <li>size of image</li>
@ -228,6 +229,10 @@ public final class ImageCache {
}); });
} }
public static void clearCache() {
IMAGE_CACHE.clear();
}
public static String getFilePath(CardView card, int width) { public static String getFilePath(CardView card, int width) {
String key = getKey(card, card.getName(), Integer.toString(width)); String key = getKey(card, card.getName(), Integer.toString(width));
boolean usesVariousArt = false; boolean usesVariousArt = false;
@ -389,7 +394,7 @@ public final class ImageCache {
return getImage(getKey(card, card.getName(), "")); return getImage(getKey(card, card.getName(), ""));
} }
// public static BufferedImage getImageFaceOriginal(CardView card) { // public static BufferedImage getImageFaceOriginal(CardView card) {
// return getFaceImage(getFaceKey(card, card.getName(), card.getExpansionSetCode())); // return getFaceImage(getFaceKey(card, card.getName(), card.getExpansionSetCode()));
// } // }
public static BufferedImage getImageOriginalAlternateName(CardView card) { public static BufferedImage getImageOriginalAlternateName(CardView card) {
@ -472,6 +477,7 @@ public final class ImageCache {
// return alternateName + "#" + card.getExpansionSetCode() + "#" +card.getType()+ "#" + card.getCardNumber() + "#" // return alternateName + "#" + card.getExpansionSetCode() + "#" +card.getType()+ "#" + card.getCardNumber() + "#"
// + (card.getTokenSetCode() == null ? "":card.getTokenSetCode()); // + (card.getTokenSetCode() == null ? "":card.getTokenSetCode());
// } // }
/** /**
* Load image from file * Load image from file
* *

View file

@ -187,6 +187,7 @@
|Generate|TOK:ALL|Graveborn|||SekKuarDeathkeeperGravebornToken| |Generate|TOK:ALL|Graveborn|||SekKuarDeathkeeperGravebornToken|
|Generate|TOK:ALL|Hippo|||HippoToken| |Generate|TOK:ALL|Hippo|||HippoToken|
|Generate|TOK:ALL|Soldier|||SoldierToken| |Generate|TOK:ALL|Soldier|||SoldierToken|
|Generate|TOK:ALL|Starfish|||StarfishToken|
|Generate|TOK:ALL|Zombie|||ZombieToken| |Generate|TOK:ALL|Zombie|||ZombieToken|
|Generate|TOK:APC|Angel|||HauntedAngelToken| |Generate|TOK:APC|Angel|||HauntedAngelToken|
|Generate|TOK:APC|Cat|||PenumbraBobcatToken| |Generate|TOK:APC|Cat|||PenumbraBobcatToken|

View file

@ -1,5 +1,7 @@
package mage.utils; package mage.utils;
import mage.util.JarVersion;
import java.io.Serializable; import java.io.Serializable;
/** /**

View file

@ -13,21 +13,12 @@ public class DraftClientMessage implements Serializable {
private DraftView draftView; private DraftView draftView;
private DraftPickView draftPickView; private DraftPickView draftPickView;
private String message;
public DraftClientMessage(DraftView draftView) { public DraftClientMessage(DraftView draftView, DraftPickView draftPickView) {
this.draftView = draftView; this.draftView = draftView;
}
public DraftClientMessage(DraftPickView draftPickView) {
this.draftPickView = draftPickView; this.draftPickView = draftPickView;
} }
public DraftClientMessage(DraftView draftView, String message) {
this.message = message;
this.draftView = draftView;
}
public DraftPickView getDraftPickView() { public DraftPickView getDraftPickView() {
return draftPickView; return draftPickView;
} }

View file

@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.game.draft.Draft; import mage.game.draft.Draft;
import mage.game.draft.DraftCube;
import mage.game.draft.DraftPlayer; import mage.game.draft.DraftPlayer;
/** /**
@ -17,6 +18,7 @@ public class DraftView implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final List<String> sets = new ArrayList<>(); private final List<String> sets = new ArrayList<>();
private final List<String> setCodes = new ArrayList<>();
private final int boosterNum; private final int boosterNum;
private final int cardNum; private final int cardNum;
private final List<String> players = new ArrayList<>(); private final List<String> players = new ArrayList<>();
@ -24,11 +26,14 @@ public class DraftView implements Serializable {
public DraftView(Draft draft) { public DraftView(Draft draft) {
if (draft.getDraftCube() != null) { if (draft.getDraftCube() != null) {
for (int i = 0; i < draft.getNumberBoosters(); i++) { for (int i = 0; i < draft.getNumberBoosters(); i++) {
sets.add(draft.getDraftCube().getName()); DraftCube cube = draft.getDraftCube();
sets.add(cube.getName());
setCodes.add(cube.getCode());
} }
} else { } else {
for (ExpansionSet set: draft.getSets()) { for (ExpansionSet set: draft.getSets()) {
sets.add(set.getName()); sets.add(set.getName());
setCodes.add(set.getCode());
} }
} }
this.boosterNum = draft.getBoosterNum(); this.boosterNum = draft.getBoosterNum();
@ -42,6 +47,10 @@ public class DraftView implements Serializable {
return sets; return sets;
} }
public List<String> getSetCodes() {
return setCodes;
}
public List<String> getPlayers() { public List<String> getPlayers() {
return players; return players;
} }

View file

@ -43,7 +43,7 @@ public class TournamentGameView implements Serializable {
String duelingTime = ""; String duelingTime = "";
if (game.hasEnded()) { if (game.hasEnded()) {
if (game.getEndTime() != null) { if (game.getEndTime() != null && game.getStartTime() != null) {
duelingTime = " (" + DateFormat.getDuration((game.getEndTime().getTime() - game.getStartTime().getTime())/1000) + ')'; duelingTime = " (" + DateFormat.getDuration((game.getEndTime().getTime() - game.getStartTime().getTime())/1000) + ')';
} }
this.state = "Finished" + duelingTime; this.state = "Finished" + duelingTime;

View file

@ -4,7 +4,6 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -82,7 +81,7 @@ public class AusHighlander extends Constructed {
public AusHighlander() { public AusHighlander() {
this("Australian Highlander"); this("Australian Highlander");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -4,7 +4,6 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -64,7 +63,7 @@ public class CanadianHighlander extends Constructed {
public CanadianHighlander() { public CanadianHighlander() {
this("Canadian Highlander"); this("Canadian Highlander");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -1,6 +1,5 @@
package mage.deck; package mage.deck;
import java.util.*;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.CanBeYourCommanderAbility; import mage.abilities.common.CanBeYourCommanderAbility;
@ -12,11 +11,11 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import java.util.*;
/** /**
*
* @author Plopman * @author Plopman
*/ */
public class Commander extends Constructed { public class Commander extends Constructed {
@ -27,7 +26,7 @@ public class Commander extends Constructed {
public Commander() { public Commander() {
this("Commander"); this("Commander");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -4,7 +4,6 @@ package mage.deck;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.constants.SetType;
/** /**
* This class implements the new casual format "Eternal", which is legacy with * This class implements the new casual format "Eternal", which is legacy with
@ -18,7 +17,7 @@ public class Eternal extends Constructed {
public Eternal() { public Eternal() {
super("Constructed - Eternal"); super("Constructed - Eternal");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -26,6 +26,9 @@ public class FreeformCommander extends Constructed {
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
// no banned cards
this.banned.clear();
} }
public FreeformCommander(String name) { public FreeformCommander(String name) {

View file

@ -14,7 +14,7 @@ public class Legacy extends Constructed {
public Legacy() { public Legacy() {
super("Constructed - Legacy"); super("Constructed - Legacy");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -9,10 +9,8 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.SetType;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public class Pauper extends Constructed { public class Pauper extends Constructed {
@ -22,7 +20,7 @@ public class Pauper extends Constructed {
//TODO: Add only Magic Online sets for pauper //TODO: Add only Magic Online sets for pauper
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -1,8 +1,6 @@
package mage.deck; package mage.deck;
import java.util.*;
import java.util.Map.Entry;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.CanBeYourCommanderAbility; import mage.abilities.common.CanBeYourCommanderAbility;
import mage.abilities.keyword.PartnerAbility; import mage.abilities.keyword.PartnerAbility;
@ -12,11 +10,12 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import java.util.*;
import java.util.Map.Entry;
/** /**
*
* @author spjspj * @author spjspj
*/ */
public class PennyDreadfulCommander extends Constructed { public class PennyDreadfulCommander extends Constructed {
@ -28,7 +27,7 @@ public class PennyDreadfulCommander extends Constructed {
public PennyDreadfulCommander() { public PennyDreadfulCommander() {
this("Penny Dreadful Commander"); this("Penny Dreadful Commander");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -1,10 +1,6 @@
package mage.deck; package mage.deck;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mage.abilities.common.CanBeYourCommanderAbility; import mage.abilities.common.CanBeYourCommanderAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
@ -12,12 +8,15 @@ import mage.cards.Sets;
import mage.cards.SplitCard; import mage.cards.SplitCard;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import mage.game.GameTinyLeadersImpl; import mage.game.GameTinyLeadersImpl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
*
* @author JRHerlehy * @author JRHerlehy
*/ */
public class TinyLeaders extends Constructed { public class TinyLeaders extends Constructed {
@ -27,7 +26,7 @@ public class TinyLeaders extends Constructed {
public TinyLeaders() { public TinyLeaders() {
this("Tiny Leaders"); this("Tiny Leaders");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }
@ -85,7 +84,6 @@ public class TinyLeaders extends Constructed {
} }
/** /**
*
* @param deck * @param deck
* @return - True if deck is valid * @return - True if deck is valid
*/ */
@ -212,9 +210,8 @@ public class TinyLeaders extends Constructed {
} }
/** /**
*
* @param commander FilterMana object with Color Identity of Commander set * @param commander FilterMana object with Color Identity of Commander set
* @param card Card to validate * @param card Card to validate
* @return True if card has a valid color identity * @return True if card has a valid color identity
*/ */
public boolean cardHasValideColor(FilterMana commander, Card card) { public boolean cardHasValideColor(FilterMana commander, Card card) {

View file

@ -4,10 +4,8 @@ package mage.deck;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.constants.SetType;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class Vintage extends Constructed { public class Vintage extends Constructed {
@ -15,7 +13,7 @@ public class Vintage extends Constructed {
public Vintage() { public Vintage() {
super("Constructed - Vintage"); super("Constructed - Vintage");
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType() != SetType.CUSTOM_SET) { if (set.isEternalLegal()) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
} }
} }

View file

@ -111,9 +111,8 @@ public class ComputerPlayer7 extends ComputerPlayer6 {
Game sim = createSimulation(game); Game sim = createSimulation(game);
SimulationNode2.resetCount(); SimulationNode2.resetCount();
root = new SimulationNode2(null, sim, maxDepth, playerId); root = new SimulationNode2(null, sim, maxDepth, playerId);
addActionsTimed(); addActionsTimed(); // TODO: root can be null again after addActionsTimed O_o need to research (it's a CPU AI problem?)
if (root.children != null if (root != null && root.children != null && !root.children.isEmpty()) {
&& !root.children.isEmpty()) {
logger.trace("After add actions timed: root.children.size = " + root.children.size()); logger.trace("After add actions timed: root.children.size = " + root.children.size());
root = root.children.get(0); root = root.children.get(0);
// prevent repeating always the same action with no cost // prevent repeating always the same action with no cost

View file

@ -1,31 +1,26 @@
package mage.player.ai.utils; package mage.player.ai.utils;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.*;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.constants.ColoredManaSymbol; import mage.constants.ColoredManaSymbol;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubType;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetAttackingCreature;
import mage.target.common.TargetAttackingOrBlockingCreature;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import mage.abilities.Mode;
import mage.abilities.effects.common.DamageWithPowerTargetEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.constants.Rarity;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetAttackingCreature;
import mage.target.common.TargetAttackingOrBlockingCreature;
import mage.target.common.TargetPlayerOrPlaneswalker;
/** /**
* Class responsible for reading ratings from resources and rating given cards. * Class responsible for reading ratings from resources and rating given cards.
@ -43,13 +38,12 @@ public final class RateCard {
* Rating that is given for new cards. * Rating that is given for new cards.
* Ratings are in [1,10] range, so setting it high will make new cards appear more often. * Ratings are in [1,10] range, so setting it high will make new cards appear more often.
* nowadays, cards that are more rare are more powerful, lets trust that and play the shiny cards. * nowadays, cards that are more rare are more powerful, lets trust that and play the shiny cards.
*
*/ */
private static final int DEFAULT_NOT_RATED_CARD_RATING = 40; private static final int DEFAULT_NOT_RATED_CARD_RATING = 40;
private static final int DEFAULT_NOT_RATED_UNCOMMON_RATING = 60; private static final int DEFAULT_NOT_RATED_UNCOMMON_RATING = 60;
private static final int DEFAULT_NOT_RATED_RARE_RATING = 75; private static final int DEFAULT_NOT_RATED_RARE_RATING = 75;
private static final int DEFAULT_NOT_RATED_MYTHIC_RATING = 90; private static final int DEFAULT_NOT_RATED_MYTHIC_RATING = 90;
private static String RATINGS_DIR = "/ratings/"; private static String RATINGS_DIR = "/ratings/";
private static String RATINGS_SET_LIST = RATINGS_DIR + "setsWithRatings.csv"; private static String RATINGS_SET_LIST = RATINGS_DIR + "setsWithRatings.csv";
@ -100,54 +94,54 @@ public final class RateCard {
if (card.isEnchantment() || card.isInstant() || card.isSorcery()) { if (card.isEnchantment() || card.isInstant() || card.isSorcery()) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities()) {
for (Effect effect : ability.getEffects()) { for (Effect effect : ability.getEffects()) {
if (isEffectRemoval(card, ability, effect) == 1){ if (isEffectRemoval(card, ability, effect) == 1) {
return 1; return 1;
} }
} }
for (Mode mode: ability.getModes().values() ){ for (Mode mode : ability.getModes().values()) {
for (Effect effect: mode.getEffects()){ for (Effect effect : mode.getEffects()) {
if (isEffectRemoval(card, ability, effect) == 1){ if (isEffectRemoval(card, ability, effect) == 1) {
return 1; return 1;
} }
} }
} }
} }
} }
return 0; return 0;
} }
private static int isEffectRemoval(Card card, Ability ability, Effect effect){ private static int isEffectRemoval(Card card, Ability ability, Effect effect) {
if (effect.getOutcome() == Outcome.Removal) { if (effect.getOutcome() == Outcome.Removal) {
log.debug("Found removal: " + card.getName()); log.debug("Found removal: " + card.getName());
return 1; return 1;
} }
//static List<Effect> removalEffects =[BoostTargetEffect,BoostEnchantedEffect] //static List<Effect> removalEffects =[BoostTargetEffect,BoostEnchantedEffect]
if (effect instanceof BoostTargetEffect || effect instanceof BoostEnchantedEffect){ if (effect instanceof BoostTargetEffect || effect instanceof BoostEnchantedEffect) {
String text = effect.getText(null); String text = effect.getText(null);
if (text.contains("/-")){ if (text.contains("/-")) {
// toughness reducer, aka removal // toughness reducer, aka removal
return 1; return 1;
} }
} }
if (effect instanceof FightTargetsEffect || effect instanceof DamageWithPowerTargetEffect){ if (effect instanceof FightTargetsEffect || effect instanceof DamageWithPowerTargetEffect) {
return 1; return 1;
} }
if (effect.getOutcome() == Outcome.Damage || effect instanceof DamageTargetEffect) { if (effect.getOutcome() == Outcome.Damage || effect instanceof DamageTargetEffect) {
for (Target target : ability.getTargets()) { for (Target target : ability.getTargets()) {
if (!(target instanceof TargetPlayerOrPlaneswalker)){ if (!(target instanceof TargetPlayerOrPlaneswalker)) {
log.debug("Found damage dealer: " + card.getName()); log.debug("Found damage dealer: " + card.getName());
return 1; return 1;
} }
} }
} }
if (effect.getOutcome() == Outcome.DestroyPermanent || if (effect.getOutcome() == Outcome.DestroyPermanent ||
effect instanceof DestroyTargetEffect || effect instanceof DestroyTargetEffect ||
effect instanceof ExileTargetEffect || effect instanceof ExileTargetEffect ||
effect instanceof ExileUntilSourceLeavesEffect) { effect instanceof ExileUntilSourceLeavesEffect) {
for (Target target : ability.getTargets()) { for (Target target : ability.getTargets()) {
if (target instanceof TargetCreaturePermanent || if (target instanceof TargetCreaturePermanent ||
target instanceof TargetAttackingCreature || target instanceof TargetAttackingCreature ||
target instanceof TargetAttackingOrBlockingCreature || target instanceof TargetAttackingOrBlockingCreature ||
target instanceof TargetPermanent) { target instanceof TargetPermanent) {
@ -175,37 +169,37 @@ public final class RateCard {
} }
Rarity r = card.getRarity(); Rarity r = card.getRarity();
if (Rarity.COMMON == r){ if (Rarity.COMMON == r) {
return DEFAULT_NOT_RATED_CARD_RATING; return DEFAULT_NOT_RATED_CARD_RATING;
}else if (Rarity.UNCOMMON == r){ } else if (Rarity.UNCOMMON == r) {
return DEFAULT_NOT_RATED_UNCOMMON_RATING; return DEFAULT_NOT_RATED_UNCOMMON_RATING;
}else if (Rarity.RARE == r){ } else if (Rarity.RARE == r) {
return DEFAULT_NOT_RATED_RARE_RATING; return DEFAULT_NOT_RATED_RARE_RATING;
}else if (Rarity.MYTHIC == r){ } else if (Rarity.MYTHIC == r) {
return DEFAULT_NOT_RATED_MYTHIC_RATING; return DEFAULT_NOT_RATED_MYTHIC_RATING;
} }
return DEFAULT_NOT_RATED_CARD_RATING; return DEFAULT_NOT_RATED_CARD_RATING;
} }
/** /**
* reads the list of sets that have ratings csv files * reads the list of sets that have ratings csv files
* populates the setsWithRatingsToBeLoaded * populates the setsWithRatingsToBeLoaded
*/ */
private synchronized static void readRatingSetList(){ private synchronized static void readRatingSetList() {
try { try {
if (setsWithRatingsToBeLoaded == null){ if (setsWithRatingsToBeLoaded == null) {
setsWithRatingsToBeLoaded = new LinkedList<>(); setsWithRatingsToBeLoaded = new LinkedList<>();
InputStream is = RateCard.class.getResourceAsStream(RATINGS_SET_LIST); InputStream is = RateCard.class.getResourceAsStream(RATINGS_SET_LIST);
Scanner scanner = new Scanner(is); Scanner scanner = new Scanner(is);
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
if (!line.substring(0,1).equals("#")){ if (!line.substring(0, 1).equals("#")) {
setsWithRatingsToBeLoaded.add(line); setsWithRatingsToBeLoaded.add(line);
}
} }
}
} }
}catch (Exception e) { } catch (Exception e) {
log.info("failed to read ratings set list file: " + RATINGS_SET_LIST ); log.info("failed to read ratings set list file: " + RATINGS_SET_LIST);
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -217,15 +211,16 @@ public final class RateCard {
if (ratings == null) { if (ratings == null) {
ratings = new HashMap<>(); ratings = new HashMap<>();
} }
if (setsWithRatingsToBeLoaded.contains(expCode)){ if (setsWithRatingsToBeLoaded.contains(expCode)) {
log.info("reading draftbot ratings for the set" + expCode); log.info("reading draftbot ratings for the set " + expCode);
readFromFile(RATINGS_DIR + expCode + ".csv"); readFromFile(RATINGS_DIR + expCode + ".csv");
setsWithRatingsToBeLoaded.remove(expCode); setsWithRatingsToBeLoaded.remove(expCode);
} }
} }
/** /**
* reads ratings from the file * reads ratings from the file
*/ */
private synchronized static void readFromFile(String path) { private synchronized static void readFromFile(String path) {
Integer min = Integer.MAX_VALUE, max = 0; Integer min = Integer.MAX_VALUE, max = 0;
Map<String, Integer> thisFileRatings = new HashMap<>(); Map<String, Integer> thisFileRatings = new HashMap<>();
@ -248,21 +243,21 @@ public final class RateCard {
} }
} }
// normalize for the file to [1..100] // normalize for the file to [1..100]
for (String name: thisFileRatings.keySet()){ for (String name : thisFileRatings.keySet()) {
int r = thisFileRatings.get(name); int r = thisFileRatings.get(name);
int newrating = (int)(100.0f * (r - min) / (max - min)); int newrating = (int) (100.0f * (r - min) / (max - min));
if (!ratings.containsKey(name) || if (!ratings.containsKey(name) ||
(ratings.containsKey(name) && newrating > ratings.get(name)) ){ (ratings.containsKey(name) && newrating > ratings.get(name))) {
ratings.put(name, newrating); ratings.put(name, newrating);
} }
} }
} catch (Exception e) { } catch (Exception e) {
log.info("failed to read ratings file: " + path ); log.info("failed to read ratings file: " + path);
e.printStackTrace(); e.printStackTrace();
} }
} }
private static final int SINGLE_PENALTY[] = {0, 1, 1, 3, 6, 9}; private static final int[] SINGLE_PENALTY = {0, 1, 1, 3, 6, 9};
private static final int MULTICOLOR_BONUS = 15; private static final int MULTICOLOR_BONUS = 15;
/** /**
@ -271,7 +266,6 @@ public final class RateCard {
* If allowed colors are not chosen, then score based on converted cost is returned with penalty for heavy colored cards. * If allowed colors are not chosen, then score based on converted cost is returned with penalty for heavy colored cards.
* gives bonus to multicolor cards that fit within allowed colors and if allowed colors is <5 * gives bonus to multicolor cards that fit within allowed colors and if allowed colors is <5
* *
*
* @param card * @param card
* @param allowedColors Can be null. * @param allowedColors Can be null.
* @return * @return
@ -282,7 +276,7 @@ public final class RateCard {
int colorPenalty = 0; int colorPenalty = 0;
for (String symbol : card.getManaCost().getSymbols()) { for (String symbol : card.getManaCost().getSymbols()) {
if (isColoredMana(symbol)) { if (isColoredMana(symbol)) {
colorPenalty++; colorPenalty++;
} }
} }
return 2 * (converted - colorPenalty + 1); return 2 * (converted - colorPenalty + 1);
@ -314,22 +308,22 @@ public final class RateCard {
maxSingleCount = 5; maxSingleCount = 5;
int rate = 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]); int rate = 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]);
if( singleCount.size() > 1 && singleCount.size() < 5){ if (singleCount.size() > 1 && singleCount.size() < 5) {
rate += MULTICOLOR_BONUS; rate += MULTICOLOR_BONUS;
} }
return rate; return rate;
} }
/** /**
* Determines whether mana symbol is color. * Determines whether mana symbol is color.
* *
* @param symbol * @param symbol
* @return * @return
*/ */
public static boolean isColoredMana(String symbol) { public static boolean isColoredMana(String symbol) {
String s = symbol; String s = symbol;
if (s.length() > 1) { if (s.length() > 1) {
s = s.replace("{","").replace("}",""); s = s.replace("{", "").replace("}", "");
} }
if (s.length() > 1) { if (s.length() > 1) {
return false; return false;
@ -339,6 +333,7 @@ public final class RateCard {
/** /**
* Return number of color mana symbols in manacost. * Return number of color mana symbols in manacost.
*
* @param card * @param card
* @return * @return
*/ */
@ -354,6 +349,7 @@ public final class RateCard {
/** /**
* Return number of different color mana symbols in manacost. * Return number of different color mana symbols in manacost.
*
* @param card * @param card
* @return * @return
*/ */

View file

@ -0,0 +1,556 @@
package mage.tournament.cubes;
import mage.game.draft.DraftCube;
/**
*
* @author themogwi
*/
public class VintageCubeDecember2018 extends DraftCube {
public VintageCubeDecember2018() {
super("MTGO Vintage Cube December 2018");
cubeCards.add(new DraftCube.CardIdentity("Dauntless Bodyguard", ""));
cubeCards.add(new DraftCube.CardIdentity("Kytheon, Hero of Akros", ""));
cubeCards.add(new DraftCube.CardIdentity("Mother of Runes", ""));
cubeCards.add(new DraftCube.CardIdentity("Student of Warfare", ""));
cubeCards.add(new DraftCube.CardIdentity("Adanto Vanguard", ""));
cubeCards.add(new DraftCube.CardIdentity("Leonin Relic-Warder", ""));
cubeCards.add(new DraftCube.CardIdentity("Remorseful Cleric", ""));
cubeCards.add(new DraftCube.CardIdentity("Selfless Spirit", ""));
cubeCards.add(new DraftCube.CardIdentity("Soulfire Grand Master", ""));
cubeCards.add(new DraftCube.CardIdentity("Stoneforge Mystic", ""));
cubeCards.add(new DraftCube.CardIdentity("Thalia, Guardian of Thraben", ""));
cubeCards.add(new DraftCube.CardIdentity("Wall of Omens", ""));
cubeCards.add(new DraftCube.CardIdentity("Banisher Priest", ""));
cubeCards.add(new DraftCube.CardIdentity("Blade Splicer", ""));
cubeCards.add(new DraftCube.CardIdentity("Brightling", ""));
cubeCards.add(new DraftCube.CardIdentity("Brimaz, King of Oreskos", ""));
cubeCards.add(new DraftCube.CardIdentity("Flickerwisp", ""));
cubeCards.add(new DraftCube.CardIdentity("Mirran Crusader", ""));
cubeCards.add(new DraftCube.CardIdentity("Monastery Mentor", ""));
cubeCards.add(new DraftCube.CardIdentity("Recruiter of the Guard", ""));
cubeCards.add(new DraftCube.CardIdentity("Silverblade Paladin", ""));
cubeCards.add(new DraftCube.CardIdentity("Emeria Angel", ""));
cubeCards.add(new DraftCube.CardIdentity("Hero of Bladehold", ""));
cubeCards.add(new DraftCube.CardIdentity("Linvala, Keeper of Silence", ""));
cubeCards.add(new DraftCube.CardIdentity("Palace Jailer", ""));
cubeCards.add(new DraftCube.CardIdentity("Restoration Angel", ""));
cubeCards.add(new DraftCube.CardIdentity("Angel of Invention", ""));
cubeCards.add(new DraftCube.CardIdentity("Angel of Sanctions", ""));
cubeCards.add(new DraftCube.CardIdentity("Archangel Avacyn", ""));
cubeCards.add(new DraftCube.CardIdentity("Baneslayer Angel", ""));
cubeCards.add(new DraftCube.CardIdentity("Lyra Dawnbringer", ""));
cubeCards.add(new DraftCube.CardIdentity("Reveillark", ""));
cubeCards.add(new DraftCube.CardIdentity("Sun Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Elesh Norn, Grand Cenobite", ""));
cubeCards.add(new DraftCube.CardIdentity("Avacyn, Angel of Hope", ""));
cubeCards.add(new DraftCube.CardIdentity("Iona, Shield of Emeria", ""));
cubeCards.add(new DraftCube.CardIdentity("Gideon of the Trials", ""));
cubeCards.add(new DraftCube.CardIdentity("Elspeth, Knight-Errant", ""));
cubeCards.add(new DraftCube.CardIdentity("Gideon, Ally of Zendikar", ""));
cubeCards.add(new DraftCube.CardIdentity("Gideon Jura", ""));
cubeCards.add(new DraftCube.CardIdentity("Elspeth, Sun's Champion", ""));
cubeCards.add(new DraftCube.CardIdentity("Porcelain Legionnaire", ""));
cubeCards.add(new DraftCube.CardIdentity("Condemn", ""));
cubeCards.add(new DraftCube.CardIdentity("Enlightened Tutor", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Tithe", ""));
cubeCards.add(new DraftCube.CardIdentity("Path to Exile", ""));
cubeCards.add(new DraftCube.CardIdentity("Swords to Plowshares", ""));
cubeCards.add(new DraftCube.CardIdentity("Disenchant", ""));
cubeCards.add(new DraftCube.CardIdentity("Unexpectedly Absent", ""));
cubeCards.add(new DraftCube.CardIdentity("Balance", ""));
cubeCards.add(new DraftCube.CardIdentity("Council's Judgment", ""));
cubeCards.add(new DraftCube.CardIdentity("Lingering Souls", ""));
cubeCards.add(new DraftCube.CardIdentity("Spectral Procession", ""));
cubeCards.add(new DraftCube.CardIdentity("Timely Reinforcements", ""));
cubeCards.add(new DraftCube.CardIdentity("Armageddon", ""));
cubeCards.add(new DraftCube.CardIdentity("Day of Judgment", ""));
cubeCards.add(new DraftCube.CardIdentity("Ravages of War", ""));
cubeCards.add(new DraftCube.CardIdentity("Wrath of God", ""));
cubeCards.add(new DraftCube.CardIdentity("Terminus", ""));
cubeCards.add(new DraftCube.CardIdentity("Land Tax", ""));
cubeCards.add(new DraftCube.CardIdentity("Legion's Landing", ""));
cubeCards.add(new DraftCube.CardIdentity("Honor of the Pure", ""));
cubeCards.add(new DraftCube.CardIdentity("Banishing Light", ""));
cubeCards.add(new DraftCube.CardIdentity("History of Benalia", ""));
cubeCards.add(new DraftCube.CardIdentity("Oblivion Ring", ""));
cubeCards.add(new DraftCube.CardIdentity("Faith's Fetters", ""));
cubeCards.add(new DraftCube.CardIdentity("Moat", ""));
cubeCards.add(new DraftCube.CardIdentity("Parallax Wave", ""));
cubeCards.add(new DraftCube.CardIdentity("Spear of Heliod", ""));
cubeCards.add(new DraftCube.CardIdentity("Karakas", ""));
cubeCards.add(new DraftCube.CardIdentity("Baral, Chief of Compliance", ""));
cubeCards.add(new DraftCube.CardIdentity("Jace, Vryn's Prodigy", ""));
cubeCards.add(new DraftCube.CardIdentity("Looter il-Kor", ""));
cubeCards.add(new DraftCube.CardIdentity("Phantasmal Image", ""));
cubeCards.add(new DraftCube.CardIdentity("Snapcaster Mage", ""));
cubeCards.add(new DraftCube.CardIdentity("Thing in the Ice", ""));
cubeCards.add(new DraftCube.CardIdentity("Arcane Artisan", ""));
cubeCards.add(new DraftCube.CardIdentity("Deceiver Exarch", ""));
cubeCards.add(new DraftCube.CardIdentity("Pestermite", ""));
cubeCards.add(new DraftCube.CardIdentity("Trinket Mage", ""));
cubeCards.add(new DraftCube.CardIdentity("True-Name Nemesis", ""));
cubeCards.add(new DraftCube.CardIdentity("Vendilion Clique", ""));
cubeCards.add(new DraftCube.CardIdentity("Glen Elendra Archmage", ""));
cubeCards.add(new DraftCube.CardIdentity("Sower of Temptation", ""));
cubeCards.add(new DraftCube.CardIdentity("Venser, Shaper Savant", ""));
cubeCards.add(new DraftCube.CardIdentity("Mulldrifter", ""));
cubeCards.add(new DraftCube.CardIdentity("Riftwing Cloudskate", ""));
cubeCards.add(new DraftCube.CardIdentity("Consecrated Sphinx", ""));
cubeCards.add(new DraftCube.CardIdentity("Frost Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Palinchron", ""));
cubeCards.add(new DraftCube.CardIdentity("Jace Beleren", ""));
cubeCards.add(new DraftCube.CardIdentity("Jace, Architect of Thought", ""));
cubeCards.add(new DraftCube.CardIdentity("Jace, the Mind Sculptor", ""));
cubeCards.add(new DraftCube.CardIdentity("Tamiyo, the Moon Sage", ""));
cubeCards.add(new DraftCube.CardIdentity("Tezzeret the Seeker", ""));
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Metamorph", ""));
cubeCards.add(new DraftCube.CardIdentity("Torrential Gearhulk", ""));
cubeCards.add(new DraftCube.CardIdentity("Inkwell Leviathan", ""));
cubeCards.add(new DraftCube.CardIdentity("Ancestral Recall", ""));
cubeCards.add(new DraftCube.CardIdentity("Brainstorm", ""));
cubeCards.add(new DraftCube.CardIdentity("High Tide", ""));
cubeCards.add(new DraftCube.CardIdentity("Mystical Tutor", ""));
cubeCards.add(new DraftCube.CardIdentity("Spell Pierce", ""));
cubeCards.add(new DraftCube.CardIdentity("Blink of an Eye", ""));
cubeCards.add(new DraftCube.CardIdentity("Brain Freeze", ""));
cubeCards.add(new DraftCube.CardIdentity("Counterspell", ""));
cubeCards.add(new DraftCube.CardIdentity("Daze", ""));
cubeCards.add(new DraftCube.CardIdentity("Impulse", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Drain", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Leak", ""));
cubeCards.add(new DraftCube.CardIdentity("Remand", ""));
cubeCards.add(new DraftCube.CardIdentity("Disallow", ""));
cubeCards.add(new DraftCube.CardIdentity("Frantic Search", ""));
cubeCards.add(new DraftCube.CardIdentity("Thirst for Knowledge", ""));
cubeCards.add(new DraftCube.CardIdentity("Cryptic Command", ""));
cubeCards.add(new DraftCube.CardIdentity("Fact or Fiction", ""));
cubeCards.add(new DraftCube.CardIdentity("Gifts Ungiven", ""));
cubeCards.add(new DraftCube.CardIdentity("Turnabout", ""));
cubeCards.add(new DraftCube.CardIdentity("Force of Will", ""));
cubeCards.add(new DraftCube.CardIdentity("Gush", ""));
cubeCards.add(new DraftCube.CardIdentity("Mystic Confluence", ""));
cubeCards.add(new DraftCube.CardIdentity("Repeal", ""));
cubeCards.add(new DraftCube.CardIdentity("Nexus of Fate", ""));
cubeCards.add(new DraftCube.CardIdentity("Dig Through Time", ""));
cubeCards.add(new DraftCube.CardIdentity("Ancestral Vision", ""));
cubeCards.add(new DraftCube.CardIdentity("Gitaxian Probe", ""));
cubeCards.add(new DraftCube.CardIdentity("Ponder", ""));
cubeCards.add(new DraftCube.CardIdentity("Preordain", ""));
cubeCards.add(new DraftCube.CardIdentity("Chart a Course", ""));
cubeCards.add(new DraftCube.CardIdentity("Time Walk", ""));
cubeCards.add(new DraftCube.CardIdentity("Compulsive Research", ""));
cubeCards.add(new DraftCube.CardIdentity("Show and Tell", ""));
cubeCards.add(new DraftCube.CardIdentity("Timetwister", ""));
cubeCards.add(new DraftCube.CardIdentity("Tinker", ""));
cubeCards.add(new DraftCube.CardIdentity("Bribery", ""));
cubeCards.add(new DraftCube.CardIdentity("Mind's Desire", ""));
cubeCards.add(new DraftCube.CardIdentity("Time Spiral", ""));
cubeCards.add(new DraftCube.CardIdentity("Upheaval", ""));
cubeCards.add(new DraftCube.CardIdentity("Treasure Cruise", ""));
cubeCards.add(new DraftCube.CardIdentity("Search for Azcanta", ""));
cubeCards.add(new DraftCube.CardIdentity("Control Magic", ""));
cubeCards.add(new DraftCube.CardIdentity("Opposition", ""));
cubeCards.add(new DraftCube.CardIdentity("Treachery", ""));
cubeCards.add(new DraftCube.CardIdentity("Shelldock Isle", ""));
cubeCards.add(new DraftCube.CardIdentity("Tolarian Academy", ""));
cubeCards.add(new DraftCube.CardIdentity("Putrid Imp", ""));
cubeCards.add(new DraftCube.CardIdentity("Brain Maggot", ""));
cubeCards.add(new DraftCube.CardIdentity("Dark Confidant", ""));
cubeCards.add(new DraftCube.CardIdentity("Kitesail Freebooter", ""));
cubeCards.add(new DraftCube.CardIdentity("Mesmeric Fiend", ""));
cubeCards.add(new DraftCube.CardIdentity("Oona's Prowler", ""));
cubeCards.add(new DraftCube.CardIdentity("Pack Rat", ""));
cubeCards.add(new DraftCube.CardIdentity("Scrapheap Scrounger", ""));
cubeCards.add(new DraftCube.CardIdentity("Vampire Hexmage", ""));
cubeCards.add(new DraftCube.CardIdentity("Bone Shredder", ""));
cubeCards.add(new DraftCube.CardIdentity("Hypnotic Specter", ""));
cubeCards.add(new DraftCube.CardIdentity("Ophiomancer", ""));
cubeCards.add(new DraftCube.CardIdentity("Vampire Nighthawk", ""));
cubeCards.add(new DraftCube.CardIdentity("Gonti, Lord of Luxury", ""));
cubeCards.add(new DraftCube.CardIdentity("Nekrataal", ""));
cubeCards.add(new DraftCube.CardIdentity("Ravenous Chupacabra", ""));
cubeCards.add(new DraftCube.CardIdentity("Doom Whisperer", ""));
cubeCards.add(new DraftCube.CardIdentity("Puppeteer Clique", ""));
cubeCards.add(new DraftCube.CardIdentity("Shriekmaw", ""));
cubeCards.add(new DraftCube.CardIdentity("Demonlord Belzenlok", ""));
cubeCards.add(new DraftCube.CardIdentity("Grave Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Massacre Wurm", ""));
cubeCards.add(new DraftCube.CardIdentity("Tasigur, the Golden Fang", ""));
cubeCards.add(new DraftCube.CardIdentity("Sheoldred, Whispering One", ""));
cubeCards.add(new DraftCube.CardIdentity("Griselbrand", ""));
cubeCards.add(new DraftCube.CardIdentity("Liliana of the Veil", ""));
cubeCards.add(new DraftCube.CardIdentity("Liliana, Death's Majesty", ""));
cubeCards.add(new DraftCube.CardIdentity("Dark Ritual", ""));
cubeCards.add(new DraftCube.CardIdentity("Entomb", ""));
cubeCards.add(new DraftCube.CardIdentity("Fatal Push", ""));
cubeCards.add(new DraftCube.CardIdentity("Vampiric Tutor", ""));
cubeCards.add(new DraftCube.CardIdentity("Cabal Ritual", ""));
cubeCards.add(new DraftCube.CardIdentity("Cast Down", ""));
cubeCards.add(new DraftCube.CardIdentity("Go for the Throat", ""));
cubeCards.add(new DraftCube.CardIdentity("Shallow Grave", ""));
cubeCards.add(new DraftCube.CardIdentity("Ultimate Price", ""));
cubeCards.add(new DraftCube.CardIdentity("Corpse Dance", ""));
cubeCards.add(new DraftCube.CardIdentity("Dismember", ""));
cubeCards.add(new DraftCube.CardIdentity("Hero's Downfall", ""));
cubeCards.add(new DraftCube.CardIdentity("Makeshift Mannequin", ""));
cubeCards.add(new DraftCube.CardIdentity("Vraska's Contempt", ""));
cubeCards.add(new DraftCube.CardIdentity("Duress", ""));
cubeCards.add(new DraftCube.CardIdentity("Imperial Seal", ""));
cubeCards.add(new DraftCube.CardIdentity("Inquisition of Kozilek", ""));
cubeCards.add(new DraftCube.CardIdentity("Reanimate", ""));
cubeCards.add(new DraftCube.CardIdentity("Thoughtseize", ""));
cubeCards.add(new DraftCube.CardIdentity("Collective Brutality", ""));
cubeCards.add(new DraftCube.CardIdentity("Demonic Tutor", ""));
cubeCards.add(new DraftCube.CardIdentity("Exhume", ""));
cubeCards.add(new DraftCube.CardIdentity("Hymn to Tourach", ""));
cubeCards.add(new DraftCube.CardIdentity("Night's Whisper", ""));
cubeCards.add(new DraftCube.CardIdentity("Buried Alive", ""));
cubeCards.add(new DraftCube.CardIdentity("Grim Tutor", ""));
cubeCards.add(new DraftCube.CardIdentity("Toxic Deluge", ""));
cubeCards.add(new DraftCube.CardIdentity("Yawgmoth's Will", ""));
cubeCards.add(new DraftCube.CardIdentity("Damnation", ""));
cubeCards.add(new DraftCube.CardIdentity("Languish", ""));
cubeCards.add(new DraftCube.CardIdentity("Tendrils of Agony", ""));
cubeCards.add(new DraftCube.CardIdentity("Dark Petition", ""));
cubeCards.add(new DraftCube.CardIdentity("Living Death", ""));
cubeCards.add(new DraftCube.CardIdentity("Unburial Rites", ""));
cubeCards.add(new DraftCube.CardIdentity("Mind Twist", ""));
cubeCards.add(new DraftCube.CardIdentity("Animate Dead", ""));
cubeCards.add(new DraftCube.CardIdentity("Arguel's Blood Fast", ""));
cubeCards.add(new DraftCube.CardIdentity("Bitterblossom", ""));
cubeCards.add(new DraftCube.CardIdentity("Necromancy", ""));
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Arena", ""));
cubeCards.add(new DraftCube.CardIdentity("Recurring Nightmare", ""));
cubeCards.add(new DraftCube.CardIdentity("Yawgmoth's Bargain", ""));
cubeCards.add(new DraftCube.CardIdentity("Urborg, Tomb of Yawgmoth", ""));
cubeCards.add(new DraftCube.CardIdentity("Firedrinker Satyr", ""));
cubeCards.add(new DraftCube.CardIdentity("Goblin Guide", ""));
cubeCards.add(new DraftCube.CardIdentity("Goblin Welder", ""));
cubeCards.add(new DraftCube.CardIdentity("Grim Lavamancer", ""));
cubeCards.add(new DraftCube.CardIdentity("Jackal Pup", ""));
cubeCards.add(new DraftCube.CardIdentity("Monastery Swiftspear", ""));
cubeCards.add(new DraftCube.CardIdentity("Zurgo Bellstriker", ""));
cubeCards.add(new DraftCube.CardIdentity("Abbot of Keral Keep", ""));
cubeCards.add(new DraftCube.CardIdentity("Dire Fleet Daredevil", ""));
cubeCards.add(new DraftCube.CardIdentity("Eidolon of the Great Revel", ""));
cubeCards.add(new DraftCube.CardIdentity("Runaway Steam-Kin", ""));
cubeCards.add(new DraftCube.CardIdentity("Young Pyromancer", ""));
cubeCards.add(new DraftCube.CardIdentity("Goblin Rabblemaster", ""));
cubeCards.add(new DraftCube.CardIdentity("Imperial Recruiter", ""));
cubeCards.add(new DraftCube.CardIdentity("Magus of the Moon", ""));
cubeCards.add(new DraftCube.CardIdentity("Manic Vandal", ""));
cubeCards.add(new DraftCube.CardIdentity("Pia Nalaar", ""));
cubeCards.add(new DraftCube.CardIdentity("Avalanche Riders", ""));
cubeCards.add(new DraftCube.CardIdentity("Flametongue Kavu", ""));
cubeCards.add(new DraftCube.CardIdentity("Hazoret the Fervent", ""));
cubeCards.add(new DraftCube.CardIdentity("Hellrider", ""));
cubeCards.add(new DraftCube.CardIdentity("Pia and Kiran Nalaar", ""));
cubeCards.add(new DraftCube.CardIdentity("Rekindling Phoenix", ""));
cubeCards.add(new DraftCube.CardIdentity("Glorybringer", ""));
cubeCards.add(new DraftCube.CardIdentity("Goblin Dark-Dwellers", ""));
cubeCards.add(new DraftCube.CardIdentity("Kiki-Jiki, Mirror Breaker", ""));
cubeCards.add(new DraftCube.CardIdentity("Siege-Gang Commander", ""));
cubeCards.add(new DraftCube.CardIdentity("Thundermaw Hellkite", ""));
cubeCards.add(new DraftCube.CardIdentity("Zealous Conscripts", ""));
cubeCards.add(new DraftCube.CardIdentity("Inferno Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Chandra, Torch of Defiance", ""));
cubeCards.add(new DraftCube.CardIdentity("Daretti, Scrap Savant", ""));
cubeCards.add(new DraftCube.CardIdentity("Koth of the Hammer", ""));
cubeCards.add(new DraftCube.CardIdentity("Chandra, Flamecaller", ""));
cubeCards.add(new DraftCube.CardIdentity("Burst Lightning", ""));
cubeCards.add(new DraftCube.CardIdentity("Lightning Bolt", ""));
cubeCards.add(new DraftCube.CardIdentity("Abrade", ""));
cubeCards.add(new DraftCube.CardIdentity("Ancient Grudge", ""));
cubeCards.add(new DraftCube.CardIdentity("Desperate Ritual", ""));
cubeCards.add(new DraftCube.CardIdentity("Incinerate", ""));
cubeCards.add(new DraftCube.CardIdentity("Lightning Strike", ""));
cubeCards.add(new DraftCube.CardIdentity("Magma Jet", ""));
cubeCards.add(new DraftCube.CardIdentity("Pyretic Ritual", ""));
cubeCards.add(new DraftCube.CardIdentity("Char", ""));
cubeCards.add(new DraftCube.CardIdentity("Seething Song", ""));
cubeCards.add(new DraftCube.CardIdentity("Through the Breach", ""));
cubeCards.add(new DraftCube.CardIdentity("Fireblast", ""));
cubeCards.add(new DraftCube.CardIdentity("Chain Lightning", ""));
cubeCards.add(new DraftCube.CardIdentity("Faithless Looting", ""));
cubeCards.add(new DraftCube.CardIdentity("Firebolt", ""));
cubeCards.add(new DraftCube.CardIdentity("Flame Slash", ""));
cubeCards.add(new DraftCube.CardIdentity("Mizzium Mortars", ""));
cubeCards.add(new DraftCube.CardIdentity("Pyroclasm", ""));
cubeCards.add(new DraftCube.CardIdentity("Collective Defiance", ""));
cubeCards.add(new DraftCube.CardIdentity("Sweltering Suns", ""));
cubeCards.add(new DraftCube.CardIdentity("Wheel of Fortune", ""));
cubeCards.add(new DraftCube.CardIdentity("Empty the Warrens", ""));
cubeCards.add(new DraftCube.CardIdentity("Fiery Confluence", ""));
cubeCards.add(new DraftCube.CardIdentity("Burning of Xinye", ""));
cubeCards.add(new DraftCube.CardIdentity("Wildfire", ""));
cubeCards.add(new DraftCube.CardIdentity("Bonfire of the Damned", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Flare", ""));
cubeCards.add(new DraftCube.CardIdentity("Sulfuric Vortex", ""));
cubeCards.add(new DraftCube.CardIdentity("Experimental Frenzy", ""));
cubeCards.add(new DraftCube.CardIdentity("Sneak Attack", ""));
cubeCards.add(new DraftCube.CardIdentity("Splinter Twin", ""));
cubeCards.add(new DraftCube.CardIdentity("Arbor Elf", ""));
cubeCards.add(new DraftCube.CardIdentity("Avacyn's Pilgrim", ""));
cubeCards.add(new DraftCube.CardIdentity("Birds of Paradise", ""));
cubeCards.add(new DraftCube.CardIdentity("Elves of Deep Shadow", ""));
cubeCards.add(new DraftCube.CardIdentity("Elvish Mystic", ""));
cubeCards.add(new DraftCube.CardIdentity("Fyndhorn Elves", ""));
cubeCards.add(new DraftCube.CardIdentity("Joraga Treespeaker", ""));
cubeCards.add(new DraftCube.CardIdentity("Llanowar Elves", ""));
cubeCards.add(new DraftCube.CardIdentity("Noble Hierarch", ""));
cubeCards.add(new DraftCube.CardIdentity("Devoted Druid", ""));
cubeCards.add(new DraftCube.CardIdentity("Fauna Shaman", ""));
cubeCards.add(new DraftCube.CardIdentity("Lotus Cobra", ""));
cubeCards.add(new DraftCube.CardIdentity("Rofellos, Llanowar Emissary", ""));
cubeCards.add(new DraftCube.CardIdentity("Sakura-Tribe Elder", ""));
cubeCards.add(new DraftCube.CardIdentity("Scavenging Ooze", ""));
cubeCards.add(new DraftCube.CardIdentity("Sylvan Caryatid", ""));
cubeCards.add(new DraftCube.CardIdentity("Wall of Blossoms", ""));
cubeCards.add(new DraftCube.CardIdentity("Wall of Roots", ""));
cubeCards.add(new DraftCube.CardIdentity("Courser of Kruphix", ""));
cubeCards.add(new DraftCube.CardIdentity("Eternal Witness", ""));
cubeCards.add(new DraftCube.CardIdentity("Manglehorn", ""));
cubeCards.add(new DraftCube.CardIdentity("Nissa, Vastwood Seer", ""));
cubeCards.add(new DraftCube.CardIdentity("Ramunap Excavator", ""));
cubeCards.add(new DraftCube.CardIdentity("Reclamation Sage", ""));
cubeCards.add(new DraftCube.CardIdentity("Tireless Tracker", ""));
cubeCards.add(new DraftCube.CardIdentity("Yavimaya Elder", ""));
cubeCards.add(new DraftCube.CardIdentity("Master of the Wild Hunt", ""));
cubeCards.add(new DraftCube.CardIdentity("Obstinate Baloth", ""));
cubeCards.add(new DraftCube.CardIdentity("Oracle of Mul Daya", ""));
cubeCards.add(new DraftCube.CardIdentity("Polukranos, World Eater", ""));
cubeCards.add(new DraftCube.CardIdentity("Thrun, the Last Troll", ""));
cubeCards.add(new DraftCube.CardIdentity("Acidic Slime", ""));
cubeCards.add(new DraftCube.CardIdentity("Deranged Hermit", ""));
cubeCards.add(new DraftCube.CardIdentity("Thragtusk", ""));
cubeCards.add(new DraftCube.CardIdentity("Whisperwood Elemental", ""));
cubeCards.add(new DraftCube.CardIdentity("Carnage Tyrant", ""));
cubeCards.add(new DraftCube.CardIdentity("Primeval Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Avenger of Zendikar", ""));
cubeCards.add(new DraftCube.CardIdentity("Craterhoof Behemoth", ""));
cubeCards.add(new DraftCube.CardIdentity("Terastodon", ""));
cubeCards.add(new DraftCube.CardIdentity("Woodfall Primus", ""));
cubeCards.add(new DraftCube.CardIdentity("Nissa, Voice of Zendikar", ""));
cubeCards.add(new DraftCube.CardIdentity("Garruk Relentless", ""));
cubeCards.add(new DraftCube.CardIdentity("Garruk Wildspeaker", ""));
cubeCards.add(new DraftCube.CardIdentity("Garruk, Primal Hunter", ""));
cubeCards.add(new DraftCube.CardIdentity("Nissa, Worldwaker", ""));
cubeCards.add(new DraftCube.CardIdentity("Vivien Reid", ""));
cubeCards.add(new DraftCube.CardIdentity("Verdurous Gearhulk", ""));
cubeCards.add(new DraftCube.CardIdentity("Nature's Claim", ""));
cubeCards.add(new DraftCube.CardIdentity("Beast Within", ""));
cubeCards.add(new DraftCube.CardIdentity("Channel", ""));
cubeCards.add(new DraftCube.CardIdentity("Regrowth", ""));
cubeCards.add(new DraftCube.CardIdentity("Kodama's Reach", ""));
cubeCards.add(new DraftCube.CardIdentity("Search for Tomorrow", ""));
cubeCards.add(new DraftCube.CardIdentity("Eureka", ""));
cubeCards.add(new DraftCube.CardIdentity("Harmonize", ""));
cubeCards.add(new DraftCube.CardIdentity("Natural Order", ""));
cubeCards.add(new DraftCube.CardIdentity("Plow Under", ""));
cubeCards.add(new DraftCube.CardIdentity("Primal Command", ""));
cubeCards.add(new DraftCube.CardIdentity("Green Sun's Zenith", ""));
cubeCards.add(new DraftCube.CardIdentity("Tooth and Nail", ""));
cubeCards.add(new DraftCube.CardIdentity("Genesis Wave", ""));
cubeCards.add(new DraftCube.CardIdentity("Fastbond", ""));
cubeCards.add(new DraftCube.CardIdentity("Oath of Druids", ""));
cubeCards.add(new DraftCube.CardIdentity("Survival of the Fittest", ""));
cubeCards.add(new DraftCube.CardIdentity("Sylvan Library", ""));
cubeCards.add(new DraftCube.CardIdentity("Heartbeat of Spring", ""));
cubeCards.add(new DraftCube.CardIdentity("Gaea's Cradle", ""));
cubeCards.add(new DraftCube.CardIdentity("Geist of Saint Traft", ""));
cubeCards.add(new DraftCube.CardIdentity("Spell Queller", ""));
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Ojutai", ""));
cubeCards.add(new DraftCube.CardIdentity("Teferi, Hero of Dominaria", ""));
cubeCards.add(new DraftCube.CardIdentity("Sphinx's Revelation", ""));
cubeCards.add(new DraftCube.CardIdentity("Celestial Colonnade", ""));
cubeCards.add(new DraftCube.CardIdentity("Flooded Strand", ""));
cubeCards.add(new DraftCube.CardIdentity("Hallowed Fountain", ""));
cubeCards.add(new DraftCube.CardIdentity("Seachrome Coast", ""));
cubeCards.add(new DraftCube.CardIdentity("Tundra", ""));
cubeCards.add(new DraftCube.CardIdentity("Thief of Sanity", ""));
cubeCards.add(new DraftCube.CardIdentity("Hostage Taker", ""));
cubeCards.add(new DraftCube.CardIdentity("The Scarab God", ""));
cubeCards.add(new DraftCube.CardIdentity("Ashiok, Nightmare Weaver", ""));
cubeCards.add(new DraftCube.CardIdentity("Baleful Strix", ""));
cubeCards.add(new DraftCube.CardIdentity("Creeping Tar Pit", ""));
cubeCards.add(new DraftCube.CardIdentity("Darkslick Shores", ""));
cubeCards.add(new DraftCube.CardIdentity("Polluted Delta", ""));
cubeCards.add(new DraftCube.CardIdentity("Underground Sea", ""));
cubeCards.add(new DraftCube.CardIdentity("Watery Grave", ""));
cubeCards.add(new DraftCube.CardIdentity("Daretti, Ingenious Iconoclast", ""));
cubeCards.add(new DraftCube.CardIdentity("Terminate", ""));
cubeCards.add(new DraftCube.CardIdentity("Kolaghan's Command", ""));
cubeCards.add(new DraftCube.CardIdentity("Dreadbore", ""));
cubeCards.add(new DraftCube.CardIdentity("Rakdos's Return", ""));
cubeCards.add(new DraftCube.CardIdentity("Badlands", ""));
cubeCards.add(new DraftCube.CardIdentity("Blackcleave Cliffs", ""));
cubeCards.add(new DraftCube.CardIdentity("Blood Crypt", ""));
cubeCards.add(new DraftCube.CardIdentity("Bloodstained Mire", ""));
cubeCards.add(new DraftCube.CardIdentity("Lavaclaw Reaches", ""));
cubeCards.add(new DraftCube.CardIdentity("Bloodbraid Elf", ""));
cubeCards.add(new DraftCube.CardIdentity("Huntmaster of the Fells", ""));
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Atarka", ""));
cubeCards.add(new DraftCube.CardIdentity("Xenagos, the Reveler", ""));
cubeCards.add(new DraftCube.CardIdentity("Manamorphose", ""));
cubeCards.add(new DraftCube.CardIdentity("Copperline Gorge", ""));
cubeCards.add(new DraftCube.CardIdentity("Raging Ravine", ""));
cubeCards.add(new DraftCube.CardIdentity("Stomping Ground", ""));
cubeCards.add(new DraftCube.CardIdentity("Taiga", ""));
cubeCards.add(new DraftCube.CardIdentity("Wooded Foothills", ""));
cubeCards.add(new DraftCube.CardIdentity("Kitchen Finks", ""));
cubeCards.add(new DraftCube.CardIdentity("Knight of Autumn", ""));
cubeCards.add(new DraftCube.CardIdentity("Knight of the Reliquary", ""));
cubeCards.add(new DraftCube.CardIdentity("Trostani Discordant", ""));
cubeCards.add(new DraftCube.CardIdentity("Mirari's Wake", ""));
cubeCards.add(new DraftCube.CardIdentity("Razorverge Thicket", ""));
cubeCards.add(new DraftCube.CardIdentity("Savannah", ""));
cubeCards.add(new DraftCube.CardIdentity("Stirring Wildwood", ""));
cubeCards.add(new DraftCube.CardIdentity("Temple Garden", ""));
cubeCards.add(new DraftCube.CardIdentity("Windswept Heath", ""));
cubeCards.add(new DraftCube.CardIdentity("Tidehollow Sculler", ""));
cubeCards.add(new DraftCube.CardIdentity("Anguished Unmaking", ""));
cubeCards.add(new DraftCube.CardIdentity("Vindicate", ""));
cubeCards.add(new DraftCube.CardIdentity("Concealed Courtyard", ""));
cubeCards.add(new DraftCube.CardIdentity("Godless Shrine", ""));
cubeCards.add(new DraftCube.CardIdentity("Marsh Flats", ""));
cubeCards.add(new DraftCube.CardIdentity("Scrubland", ""));
cubeCards.add(new DraftCube.CardIdentity("Shambling Vent", ""));
cubeCards.add(new DraftCube.CardIdentity("Vraska, Relic Seeker", ""));
cubeCards.add(new DraftCube.CardIdentity("Garruk, Apex Predator", ""));
cubeCards.add(new DraftCube.CardIdentity("Abrupt Decay", ""));
cubeCards.add(new DraftCube.CardIdentity("Assassin's Trophy", ""));
cubeCards.add(new DraftCube.CardIdentity("Maelstrom Pulse", ""));
cubeCards.add(new DraftCube.CardIdentity("Bayou", ""));
cubeCards.add(new DraftCube.CardIdentity("Blooming Marsh", ""));
cubeCards.add(new DraftCube.CardIdentity("Hissing Quagmire", ""));
cubeCards.add(new DraftCube.CardIdentity("Overgrown Tomb", ""));
cubeCards.add(new DraftCube.CardIdentity("Verdant Catacombs", ""));
cubeCards.add(new DraftCube.CardIdentity("Edric, Spymaster of Trest", ""));
cubeCards.add(new DraftCube.CardIdentity("Trygon Predator", ""));
cubeCards.add(new DraftCube.CardIdentity("Mystic Snake", ""));
cubeCards.add(new DraftCube.CardIdentity("Kiora, the Crashing Wave", ""));
cubeCards.add(new DraftCube.CardIdentity("Shardless Agent", ""));
cubeCards.add(new DraftCube.CardIdentity("Botanical Sanctum", ""));
cubeCards.add(new DraftCube.CardIdentity("Breeding Pool", ""));
cubeCards.add(new DraftCube.CardIdentity("Lumbering Falls", ""));
cubeCards.add(new DraftCube.CardIdentity("Misty Rainforest", ""));
cubeCards.add(new DraftCube.CardIdentity("Tropical Island", ""));
cubeCards.add(new DraftCube.CardIdentity("Goblin Electromancer", ""));
cubeCards.add(new DraftCube.CardIdentity("Dack Fayden", ""));
cubeCards.add(new DraftCube.CardIdentity("Expansion // Explosion", ""));
cubeCards.add(new DraftCube.CardIdentity("Izzet Charm", ""));
cubeCards.add(new DraftCube.CardIdentity("Thousand-Year Storm", ""));
cubeCards.add(new DraftCube.CardIdentity("Scalding Tarn", ""));
cubeCards.add(new DraftCube.CardIdentity("Spirebluff Canal", ""));
cubeCards.add(new DraftCube.CardIdentity("Steam Vents", ""));
cubeCards.add(new DraftCube.CardIdentity("Volcanic Island", ""));
cubeCards.add(new DraftCube.CardIdentity("Wandering Fumarole", ""));
cubeCards.add(new DraftCube.CardIdentity("Figure of Destiny", ""));
cubeCards.add(new DraftCube.CardIdentity("Aurelia, Exemplar of Justice", ""));
cubeCards.add(new DraftCube.CardIdentity("Ajani Vengeant", ""));
cubeCards.add(new DraftCube.CardIdentity("Nahiri, the Harbinger", ""));
cubeCards.add(new DraftCube.CardIdentity("Lightning Helix", ""));
cubeCards.add(new DraftCube.CardIdentity("Arid Mesa", ""));
cubeCards.add(new DraftCube.CardIdentity("Inspiring Vantage", ""));
cubeCards.add(new DraftCube.CardIdentity("Needle Spires", ""));
cubeCards.add(new DraftCube.CardIdentity("Plateau", ""));
cubeCards.add(new DraftCube.CardIdentity("Sacred Foundry", ""));
cubeCards.add(new DraftCube.CardIdentity("Sphinx of the Steel Wind", ""));
cubeCards.add(new DraftCube.CardIdentity("Nicol Bolas, Planeswalker", ""));
cubeCards.add(new DraftCube.CardIdentity("Leovold, Emissary of Trest", ""));
cubeCards.add(new DraftCube.CardIdentity("Progenitus", ""));
cubeCards.add(new DraftCube.CardIdentity("Kozilek, Butcher of Truth", ""));
cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Ceaseless Hunger", ""));
cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Infinite Gyre", ""));
cubeCards.add(new DraftCube.CardIdentity("Emrakul, the Promised End", ""));
cubeCards.add(new DraftCube.CardIdentity("Emrakul, the Aeons Torn", ""));
cubeCards.add(new DraftCube.CardIdentity("Karn, Scion of Urza", ""));
cubeCards.add(new DraftCube.CardIdentity("Karn Liberated", ""));
cubeCards.add(new DraftCube.CardIdentity("Ugin, the Spirit Dragon", ""));
cubeCards.add(new DraftCube.CardIdentity("Hangarback Walker", ""));
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Revoker", ""));
cubeCards.add(new DraftCube.CardIdentity("Metalworker", ""));
cubeCards.add(new DraftCube.CardIdentity("Lodestone Golem", ""));
cubeCards.add(new DraftCube.CardIdentity("Solemn Simulacrum", ""));
cubeCards.add(new DraftCube.CardIdentity("Kuldotha Forgemaster", ""));
cubeCards.add(new DraftCube.CardIdentity("Duplicant", ""));
cubeCards.add(new DraftCube.CardIdentity("Wurmcoil Engine", ""));
cubeCards.add(new DraftCube.CardIdentity("Myr Battlesphere", ""));
cubeCards.add(new DraftCube.CardIdentity("Sundering Titan", ""));
cubeCards.add(new DraftCube.CardIdentity("Walking Ballista", ""));
cubeCards.add(new DraftCube.CardIdentity("Blightsteel Colossus", ""));
cubeCards.add(new DraftCube.CardIdentity("Black Lotus", ""));
cubeCards.add(new DraftCube.CardIdentity("Chrome Mox", ""));
cubeCards.add(new DraftCube.CardIdentity("Everflowing Chalice", ""));
cubeCards.add(new DraftCube.CardIdentity("Lion's Eye Diamond", ""));
cubeCards.add(new DraftCube.CardIdentity("Lotus Bloom", ""));
cubeCards.add(new DraftCube.CardIdentity("Lotus Petal", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Crypt", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Diamond", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Emerald", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Jet", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Pearl", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Ruby", ""));
cubeCards.add(new DraftCube.CardIdentity("Mox Sapphire", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Vault", ""));
cubeCards.add(new DraftCube.CardIdentity("Relic of Progenitus", ""));
cubeCards.add(new DraftCube.CardIdentity("Sensei's Divining Top", ""));
cubeCards.add(new DraftCube.CardIdentity("Skullclamp", ""));
cubeCards.add(new DraftCube.CardIdentity("Sol Ring", ""));
cubeCards.add(new DraftCube.CardIdentity("Azorius Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Boros Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Dimir Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Golgari Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Grim Monolith", ""));
cubeCards.add(new DraftCube.CardIdentity("Gruul Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Izzet Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Lightning Greaves", ""));
cubeCards.add(new DraftCube.CardIdentity("Orzhov Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Pentad Prism", ""));
cubeCards.add(new DraftCube.CardIdentity("Rakdos Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Selesnya Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Shrine of Burning Rage", ""));
cubeCards.add(new DraftCube.CardIdentity("Simic Signet", ""));
cubeCards.add(new DraftCube.CardIdentity("Smuggler's Copter", ""));
cubeCards.add(new DraftCube.CardIdentity("Sorcerous Spyglass", ""));
cubeCards.add(new DraftCube.CardIdentity("Umezawa's Jitte", ""));
cubeCards.add(new DraftCube.CardIdentity("Winter Orb", ""));
cubeCards.add(new DraftCube.CardIdentity("Basalt Monolith", ""));
cubeCards.add(new DraftCube.CardIdentity("Coalition Relic", ""));
cubeCards.add(new DraftCube.CardIdentity("Crucible of Worlds", ""));
cubeCards.add(new DraftCube.CardIdentity("Oblivion Stone", ""));
cubeCards.add(new DraftCube.CardIdentity("Sword of Body and Mind", ""));
cubeCards.add(new DraftCube.CardIdentity("Sword of Feast and Famine", ""));
cubeCards.add(new DraftCube.CardIdentity("Sword of Fire and Ice", ""));
cubeCards.add(new DraftCube.CardIdentity("Sword of Light and Shadow", ""));
cubeCards.add(new DraftCube.CardIdentity("Sword of War and Peace", ""));
cubeCards.add(new DraftCube.CardIdentity("Tangle Wire", ""));
cubeCards.add(new DraftCube.CardIdentity("Vedalken Shackles", ""));
cubeCards.add(new DraftCube.CardIdentity("Worn Powerstone", ""));
cubeCards.add(new DraftCube.CardIdentity("Coercive Portal", ""));
cubeCards.add(new DraftCube.CardIdentity("Smokestack", ""));
cubeCards.add(new DraftCube.CardIdentity("Thran Dynamo", ""));
cubeCards.add(new DraftCube.CardIdentity("Batterskull", ""));
cubeCards.add(new DraftCube.CardIdentity("Gilded Lotus", ""));
cubeCards.add(new DraftCube.CardIdentity("Memory Jar", ""));
cubeCards.add(new DraftCube.CardIdentity("Mindslaver", ""));
cubeCards.add(new DraftCube.CardIdentity("Academy Ruins", ""));
cubeCards.add(new DraftCube.CardIdentity("Ancient Tomb", ""));
cubeCards.add(new DraftCube.CardIdentity("Bazaar of Baghdad", ""));
cubeCards.add(new DraftCube.CardIdentity("Field of Ruin", ""));
cubeCards.add(new DraftCube.CardIdentity("Library of Alexandria", ""));
cubeCards.add(new DraftCube.CardIdentity("Mana Confluence", ""));
cubeCards.add(new DraftCube.CardIdentity("Maze of Ith", ""));
cubeCards.add(new DraftCube.CardIdentity("Mishra's Factory", ""));
cubeCards.add(new DraftCube.CardIdentity("Mishra's Workshop", ""));
cubeCards.add(new DraftCube.CardIdentity("Mutavault", ""));
cubeCards.add(new DraftCube.CardIdentity("Nykthos, Shrine to Nyx", ""));
cubeCards.add(new DraftCube.CardIdentity("Rishadan Port", ""));
cubeCards.add(new DraftCube.CardIdentity("Strip Mine", ""));
cubeCards.add(new DraftCube.CardIdentity("Wasteland", ""));
}
}

View file

@ -134,6 +134,7 @@
<draftCube name="MTGO Vintage Cube June 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2017"/> <draftCube name="MTGO Vintage Cube June 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2017"/>
<draftCube name="MTGO Vintage Cube December 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeDecember2017"/> <draftCube name="MTGO Vintage Cube December 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeDecember2017"/>
<draftCube name="MTGO Vintage Cube June 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2018"/> <draftCube name="MTGO Vintage Cube June 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2018"/>
<draftCube name="MTGO Vintage Cube December 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeDecember2018"/>
<draftCube name="The Peasant's Toolbox" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.PeasantsToolboxCube"/> <draftCube name="The Peasant's Toolbox" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.PeasantsToolboxCube"/>
<draftCube name="www.MTGCube.com" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGCube"/> <draftCube name="www.MTGCube.com" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGCube"/>
<draftCube name="Cube From Deck" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.CubeFromDeck"/> <draftCube name="Cube From Deck" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.CubeFromDeck"/>

View file

@ -128,6 +128,7 @@
<draftCube name="MTGO Vintage Cube June 2017" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2017"/> <draftCube name="MTGO Vintage Cube June 2017" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2017"/>
<draftCube name="MTGO Vintage Cube December 2017" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeDecember2017"/> <draftCube name="MTGO Vintage Cube December 2017" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeDecember2017"/>
<draftCube name="MTGO Vintage Cube June 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2018"/> <draftCube name="MTGO Vintage Cube June 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeJune2018"/>
<draftCube name="MTGO Vintage Cube December 2018" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCubeDecember2018"/>
<draftCube name="The Peasant's Toolbox" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.PeasantsToolboxCube"/> <draftCube name="The Peasant's Toolbox" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.PeasantsToolboxCube"/>
<draftCube name="www.MTGCube.com" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGCube"/> <draftCube name="www.MTGCube.com" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGCube"/>
<draftCube name="Cube From Deck" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.CubeFromDeck"/> <draftCube name="Cube From Deck" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.CubeFromDeck"/>

View file

@ -48,7 +48,8 @@ public class DraftSession {
if (user.isPresent()) { if (user.isPresent()) {
if (futureTimeout != null && !futureTimeout.isDone()) { if (futureTimeout != null && !futureTimeout.isDone()) {
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_INIT, draft.getId(), new DraftClientMessage(getDraftPickView(remaining)))); user.get().fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_INIT, draft.getId(),
new DraftClientMessage(getDraftView(), getDraftPickView(remaining))));
} }
return true; return true;
} }
@ -60,8 +61,8 @@ public class DraftSession {
if (!killed) { if (!killed) {
UserManager.instance UserManager.instance
.getUser(userId). .getUser(userId).
ifPresent(user -> user.fireCallback( ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_UPDATE, draft.getId(),
new ClientCallback(ClientCallbackMethod.DRAFT_UPDATE, draft.getId(), getDraftView()))); new DraftClientMessage(getDraftView(), null))));
} }
} }
@ -70,7 +71,6 @@ public class DraftSession {
UserManager.instance UserManager.instance
.getUser(userId) .getUser(userId)
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_OVER, draft.getId()))); .ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_OVER, draft.getId())));
} }
} }
@ -79,7 +79,8 @@ public class DraftSession {
setupTimeout(timeout); setupTimeout(timeout);
UserManager.instance UserManager.instance
.getUser(userId) .getUser(userId)
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_PICK, draft.getId(), new DraftClientMessage(getDraftPickView(timeout))))); .ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_PICK, draft.getId(),
new DraftClientMessage(getDraftView(), getDraftPickView(timeout)))));
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
@ -21,8 +19,9 @@ import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.UUID;
/** /**
*
* @author Styxo * @author Styxo
*/ */
public final class AAT1 extends CardImpl { public final class AAT1 extends CardImpl {
@ -74,7 +73,8 @@ public final class AAT1 extends CardImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Card card = game.getCard(event.getTargetId()); Card card = game.getCard(event.getTargetId());
if (event.getPlayerId().equals(game.getControllerId(sourceId)) if (card != null
&& event.getPlayerId().equals(game.getControllerId(sourceId))
&& card.isCreature() && card.isCreature()
&& game.getState().getZone(card.getId()) == Zone.GRAVEYARD && game.getState().getZone(card.getId()) == Zone.GRAVEYARD
&& event.getData().equals("repair")) { && event.getData().equals("repair")) {

View file

@ -120,6 +120,7 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
AbandonedSarcophagusWatcher watcher = (AbandonedSarcophagusWatcher) game.getState().getWatchers().get(AbandonedSarcophagusWatcher.class.getSimpleName()); AbandonedSarcophagusWatcher watcher = (AbandonedSarcophagusWatcher) game.getState().getWatchers().get(AbandonedSarcophagusWatcher.class.getSimpleName());
Card card = game.getCard(event.getTargetId()); Card card = game.getCard(event.getTargetId());
if (card != null if (card != null
&& controller != null
&& watcher != null && watcher != null
&& card.isOwnedBy(controller.getId())) { && card.isOwnedBy(controller.getId())) {
for (Ability ability : card.getAbilities()) { for (Ability ability : card.getAbilities()) {

View file

@ -78,6 +78,9 @@ class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
if (source.getFirstTarget() != null && source.getFirstTarget().equals(event.getPlayerId())) { if (source.getFirstTarget() != null && source.getFirstTarget().equals(event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId()); MageObject object = game.getObject(event.getSourceId());
if(object == null){
return false;
}
if (event.getType() == GameEvent.EventType.CAST_SPELL) { if (event.getType() == GameEvent.EventType.CAST_SPELL) {
if (object.isInstant() || object.isSorcery()) { if (object.isInstant() || object.isSorcery()) {
return true; return true;

View file

@ -26,8 +26,8 @@ public final class Abrade extends CardImpl {
// Destroy target artifact. // Destroy target artifact.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DestroyTargetEffect()); mode.addEffect(new DestroyTargetEffect());
mode.getTargets().add(new TargetArtifactPermanent()); mode.addTarget(new TargetArtifactPermanent());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -29,8 +29,8 @@ public final class AbunasChant extends CardImpl {
this.getSpellAbility().addEffect(new GainLifeEffect(5)); this.getSpellAbility().addEffect(new GainLifeEffect(5));
//or prevent the next 5 damage that would be dealt to target creature this turn. //or prevent the next 5 damage that would be dealt to target creature this turn.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new PreventDamageToTargetEffect(Duration.EndOfTurn, 5)); mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, 5));
mode.getTargets().add(new TargetCreaturePermanent()); mode.addTarget(new TargetCreaturePermanent());
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// Entwine {2} // Entwine {2}
this.addAbility(new EntwineAbility("{2}")); this.addAbility(new EntwineAbility("{2}"));

View file

@ -39,14 +39,14 @@ public final class AbzanCharm extends CardImpl {
// *You draw two cards and you lose 2 life // *You draw two cards and you lose 2 life
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DrawCardSourceControllerEffect(2)); mode.addEffect(new DrawCardSourceControllerEffect(2));
mode.getEffects().add(new LoseLifeSourceControllerEffect(2)); mode.addEffect(new LoseLifeSourceControllerEffect(2));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// *Distribute two +1/+1 counters among one or two target creatures. // *Distribute two +1/+1 counters among one or two target creatures.
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new DistributeCountersEffect(CounterType.P1P1, 2, false, "one or two target creatures")); mode.addEffect(new DistributeCountersEffect(CounterType.P1P1, 2, false, "one or two target creatures"));
mode.getTargets().add(new TargetCreaturePermanentAmount(2)); mode.addTarget(new TargetCreaturePermanentAmount(2));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -98,19 +98,19 @@ class AcolytesRewardEffect extends PreventionEffectImpl {
result = true; result = true;
} }
if (toPrevent > 0) { if (toPrevent > 0) {
game.informPlayers(new StringBuilder("Acolyte's Reward ").append("prevented ").append(toPrevent).append(" to ").append(targetCreature.getName()).toString()); game.informPlayers("Acolyte's Reward prevented " + toPrevent + " to " + targetCreature.getName());
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE,
source.getControllerId(), source.getSourceId(), source.getControllerId(), toPrevent)); source.getControllerId(), source.getSourceId(), source.getControllerId(), toPrevent));
Player targetPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget()); Player targetPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget());
if (targetPlayer != null) { if (targetPlayer != null) {
targetPlayer.damage(toPrevent, source.getSourceId(), game, false, true); targetPlayer.damage(toPrevent, source.getSourceId(), game, false, true);
game.informPlayers(new StringBuilder("Acolyte's Reward ").append("deals ").append(toPrevent).append(" damage to ").append(targetPlayer.getLogName()).toString()); game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetPlayer.getLogName());
} else { } else {
Permanent targetDamageCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); Permanent targetDamageCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (targetDamageCreature != null) { if (targetDamageCreature != null) {
targetDamageCreature.damage(toPrevent, source.getSourceId(), game, false, true); targetDamageCreature.damage(toPrevent, source.getSourceId(), game, false, true);
game.informPlayers(new StringBuilder("Acolyte's Reward ").append("deals ").append(toPrevent).append(" damage to ").append(targetDamageCreature.getName()).toString()); game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetDamageCreature.getName());
} }
} }
} }

View file

@ -38,8 +38,8 @@ public final class ActiveVolcano extends CardImpl {
// or return target Island to its owner's hand. // or return target Island to its owner's hand.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new ReturnToHandTargetEffect()); mode.addEffect(new ReturnToHandTargetEffect());
mode.getTargets().add(new TargetPermanent(filterIsland)); mode.addTarget(new TargetPermanent(filterIsland));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -64,7 +64,7 @@ class AdviceFromTheFaeEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getObject(source.getSourceId()); MageObject mageObject = game.getObject(source.getSourceId());
if (controller != null) { if (controller != null && mageObject != null) {
Set<Card> topCards = controller.getLibrary().getTopCards(game, 5); Set<Card> topCards = controller.getLibrary().getTopCards(game, 5);
Cards cardsFromLibrary = new CardsImpl(); Cards cardsFromLibrary = new CardsImpl();
for (Card card : topCards) { for (Card card : topCards) {

View file

@ -0,0 +1,45 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.keyword.AdaptEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Aeromunculus extends CardImpl {
public Aeromunculus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");
this.subtype.add(SubType.HOMUNCULUS);
this.subtype.add(SubType.MUTANT);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {2}{G}{U}: Adapt 1.
this.addAbility(new SimpleActivatedAbility(
new AdaptEffect(1), new ManaCostsImpl("{2}{G}{U}")
));
}
public Aeromunculus(final Aeromunculus card) {
super(card);
}
@Override
public Aeromunculus copy() {
return new Aeromunculus(this);
}
}

View file

@ -33,7 +33,7 @@ public final class AetherShockwave extends CardImpl {
this.getSpellAbility().addEffect(new TapAllEffect(filterSpirit)); this.getSpellAbility().addEffect(new TapAllEffect(filterSpirit));
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new TapAllEffect(filterNonSpirit)); mode.addEffect(new TapAllEffect(filterNonSpirit));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -31,8 +31,8 @@ public final class Afterburn extends CardImpl {
// Remove target creature from combat. // Remove target creature from combat.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new RemoveFromCombatTargetEffect()); mode.addEffect(new RemoveFromCombatTargetEffect());
mode.getTargets().add(new TargetCreaturePermanent()); mode.addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -36,7 +36,7 @@ public final class AinokGuide extends CardImpl {
// * Search your library for a basic land card, reveal it, then shuffle your library and put that card on top of it. // * Search your library for a basic land card, reveal it, then shuffle your library and put that card on top of it.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new SearchLibraryPutOnLibraryEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true)); mode.addEffect(new SearchLibraryPutOnLibraryEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true));
ability.addMode(mode); ability.addMode(mode);
this.addAbility(ability); this.addAbility(ability);

View file

@ -26,8 +26,8 @@ public final class AlabasterPotion extends CardImpl {
this.getSpellAbility().addEffect(new GainLifeTargetEffect(new ManacostVariableValue())); this.getSpellAbility().addEffect(new GainLifeTargetEffect(new ManacostVariableValue()));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue())); mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue()));
mode.getTargets().add(new TargetAnyTarget()); mode.addTarget(new TargetAnyTarget());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -65,8 +65,8 @@ class WellEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
int life = 2 * game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
if (player != null) { if (player != null) {
int life = 2 * game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
player.gainLife(life, game, source); player.gainLife(life, game, source);
} }
return true; return true;

View file

@ -27,8 +27,8 @@ public final class AlleyEvasion extends CardImpl {
// Return target creature you control to its owner's hand. // Return target creature you control to its owner's hand.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new ReturnToHandTargetEffect()); mode.addEffect(new ReturnToHandTargetEffect());
mode.getTargets().add(new TargetControlledCreaturePermanent()); mode.addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -100,7 +100,7 @@ class AllianceOfArmsEffect extends OneShotEffect {
payed = true; payed = true;
} }
} }
game.informPlayers(new StringBuilder(player.getLogName()).append(" pays {").append(xValue).append("}.").toString()); game.informPlayers(player.getLogName() + " pays {" + xValue + "}.");
return xValue; return xValue;
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.SourceIsSpellCondition; import mage.abilities.condition.common.SourceIsSpellCondition;
@ -17,29 +15,31 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.UUID;
/** /**
* 10/4/2004 The mana cost of the creatures being cast is still the stated cost on the card, * 10/4/2004 The mana cost of the creatures being cast is still the stated cost on the card,
* even though you did not pay the cost. * even though you did not pay the cost.
* 10/4/2004 Aluren checks the actual printed cost on the creature card, and is not affected * 10/4/2004 Aluren checks the actual printed cost on the creature card, and is not affected
* by things which allow you to cast the spell for less. * by things which allow you to cast the spell for less.
* 10/4/2004 You can't choose to cast a creature as though it had flash via Aluren and still pay the mana cost. * 10/4/2004 You can't choose to cast a creature as though it had flash via Aluren and still pay the mana cost.
* You either cast the creature normally, or via Aluren without paying the mana cost. * You either cast the creature normally, or via Aluren without paying the mana cost.
* 10/4/2004 You can't use Aluren when casting a creature using another alternate means, * 10/4/2004 You can't use Aluren when casting a creature using another alternate means,
* such as the Morph ability. * such as the Morph ability.
* 8/1/2008 If creature with X in its cost is cast this way, X can only be 0. * 8/1/2008 If creature with X in its cost is cast this way, X can only be 0.
* *
* @author emerald000 * @author emerald000
*/ */
public final class Aluren extends CardImpl { public final class Aluren extends CardImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 3 or less"); private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 3 or less");
static { static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
} }
public Aluren(UUID ownerId, CardSetInfo setInfo) { public Aluren(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}{G}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}");
// Any player may play creature cards with converted mana cost 3 or less without paying their mana cost // Any player may play creature cards with converted mana cost 3 or less without paying their mana cost
@ -63,15 +63,15 @@ public final class Aluren extends CardImpl {
} }
class AlurenRuleEffect extends ContinuousEffectImpl { class AlurenRuleEffect extends ContinuousEffectImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 3 or less"); private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 3 or less");
static { static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
} }
private static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(null, SourceIsSpellCondition.instance, null, filter, true); private static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(null, SourceIsSpellCondition.instance, null, filter, true);
public AlurenRuleEffect() { public AlurenRuleEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment); super(Duration.WhileOnBattlefield, Outcome.Detriment);
staticText = "Any player may cast creature cards with converted mana cost 3 or less without paying their mana cost"; staticText = "Any player may cast creature cards with converted mana cost 3 or less without paying their mana cost";
@ -90,12 +90,12 @@ class AlurenRuleEffect extends ContinuousEffectImpl {
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
for (UUID playerId: game.getState().getPlayersInRange(controller.getId(), game)){ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
player.getAlternativeSourceCosts().add(alternativeCastingCostAbility); player.getAlternativeSourceCosts().add(alternativeCastingCostAbility);
} }
} }
return true; return true;
} }
return false; return false;
@ -110,47 +110,4 @@ class AlurenRuleEffect extends ContinuousEffectImpl {
public boolean hasLayer(Layer layer) { public boolean hasLayer(Layer layer) {
return layer == Layer.RulesEffects; return layer == Layer.RulesEffects;
} }
} }
//class AlurenEffect extends CostModificationEffectImpl {
//
// AlurenEffect() {
// super(Duration.WhileOnBattlefield, Outcome.PlayForFree, CostModificationType.SET_COST);
// this.staticText = "Any player may play creature cards with converted mana cost 3 or less without paying their mana cost";
// }
//
// AlurenEffect(final AlurenEffect effect) {
// super(effect);
// }
//
// @Override
// public boolean apply(Game game, Ability source, Ability abilityToModify) {
// SpellAbility spellAbility = (SpellAbility) abilityToModify;
// spellAbility.getManaCostsToPay().clear();
// return true;
// }
//
// @Override
// public boolean applies(Ability abilityToModify, Ability source, Game game) {
// if (abilityToModify instanceof SpellAbility) {
// Card sourceCard = game.getCard(abilityToModify.getSourceId());
// StackObject stackObject = game.getStack().getStackObject(abilityToModify.getSourceId());
// if (stackObject != null && stackObject instanceof Spell) {
// if (sourceCard != null && sourceCard.isCreature() && sourceCard.getConvertedManaCost() <= 3) {
// Player player = game.getPlayer(stackObject.getControllerId());
// String message = "Cast " + sourceCard.getName() + " without paying its mana costs?";
// if (player != null &&
// (CardUtil.isCheckPlayableMode(abilityToModify) || player.chooseUse(outcome, message, game))) {
// return true;
// }
// }
// }
// }
// return false;
// }
//
// @Override
// public AlurenEffect copy() {
// return new AlurenEffect(this);
// }
//}

View file

@ -1,6 +1,7 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
@ -15,7 +16,6 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class AncestorDragon extends CardImpl { public final class AncestorDragon extends CardImpl {
@ -46,8 +46,6 @@ public final class AncestorDragon extends CardImpl {
class AncestorDragonEffect extends OneShotEffect { class AncestorDragonEffect extends OneShotEffect {
private int attackers;
public AncestorDragonEffect() { public AncestorDragonEffect() {
super(Outcome.GainLife); super(Outcome.GainLife);
staticText = "you gain 1 life for each attacking creature"; staticText = "you gain 1 life for each attacking creature";
@ -65,10 +63,9 @@ class AncestorDragonEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId()); Player you = game.getPlayer(source.getControllerId());
attackers = game.getCombat().getAttackers().size();
if (you != null) { if (you != null) {
int attackers = game.getCombat().getAttackers().size();
you.gainLife(attackers, game, source); you.gainLife(attackers, game, source);
attackers = 0;
return true; return true;
} }
return false; return false;

View file

@ -64,8 +64,8 @@ class AngelsTrumpetTapEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId()); Player player = game.getPlayer(game.getActivePlayerId());
int count = 0;
if (player != null) { if (player != null) {
int count = 0;
for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game)) { for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game)) {
// Untapped creatures are safe. // Untapped creatures are safe.
if (creature.isTapped()) { if (creature.isTapped()) {

View file

@ -1,9 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -20,8 +16,11 @@ import mage.game.stack.Spell;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.players.Player; import mage.players.Player;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class ArcaneAdaptation extends CardImpl { public final class ArcaneAdaptation extends CardImpl {
@ -70,14 +69,14 @@ class ConspyEffect extends ContinuousEffectImpl {
// in graveyard // in graveyard
for (UUID cardId : controller.getGraveyard()) { for (UUID cardId : controller.getGraveyard()) {
Card card = game.getCard(cardId); Card card = game.getCard(cardId);
if (card.isCreature() && !card.hasSubtype(subType, game)) { if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) {
game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType); game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType);
} }
} }
// on Hand // on Hand
for (UUID cardId : controller.getHand()) { for (UUID cardId : controller.getHand()) {
Card card = game.getCard(cardId); Card card = game.getCard(cardId);
if (card.isCreature() && !card.hasSubtype(subType, game)) { if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) {
game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType); game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType);
} }
} }
@ -97,13 +96,13 @@ class ConspyEffect extends ContinuousEffectImpl {
for (UUID commanderId : controller.getCommandersIds()) { for (UUID commanderId : controller.getCommandersIds()) {
if (game.getState().getZone(commanderId) == Zone.COMMAND) { if (game.getState().getZone(commanderId) == Zone.COMMAND) {
Card card = game.getCard(commanderId); Card card = game.getCard(commanderId);
if (card.isCreature() && !card.hasSubtype(subType, game)) { if (card != null && card.isCreature() && !card.hasSubtype(subType, game)) {
game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType); game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType);
} }
} }
} }
// creature spells you control // creature spells you control
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) { for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext(); ) {
StackObject stackObject = iterator.next(); StackObject stackObject = iterator.next();
if (stackObject instanceof Spell if (stackObject instanceof Spell
&& stackObject.isControlledBy(source.getControllerId()) && stackObject.isControlledBy(source.getControllerId())

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import mage.MageInt; import mage.MageInt;
@ -97,26 +96,29 @@ class ArcaneArtisanCreateTokenEffect extends OneShotEffect {
return false; return false;
} }
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
player.moveCards(card, Zone.EXILED, source, game); if (!player.moveCards(card, Zone.EXILED, source, game)) {
if (!card.isCreature()) {
return false; return false;
} }
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(player.getId());
effect.setTargetPointer(new FixedTarget(card.getId(), game)); if (card.isCreature()) {
effect.apply(game, source); CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(player.getId());
Object object = game.getState().getValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game)); effect.setTargetPointer(new FixedTarget(card.getId(), game));
Set<UUID> tokensCreated; effect.apply(game, source);
if (object != null) { Object object = game.getState().getValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game));
tokensCreated = (Set<UUID>) object; Set<UUID> tokensCreated;
} else { if (object != null) {
tokensCreated = new HashSet<>(); tokensCreated = (Set<UUID>) object;
} } else {
for (Permanent perm : effect.getAddedPermanent()) { tokensCreated = new HashSet<>();
if (perm != null) {
tokensCreated.add(perm.getId());
} }
for (Permanent perm : effect.getAddedPermanent()) {
if (perm != null) {
tokensCreated.add(perm.getId());
}
}
game.getState().setValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game), tokensCreated);
} }
game.getState().setValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game), tokensCreated);
return true; return true;
} }
} }

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
@ -26,24 +25,32 @@ import mage.watchers.Watcher;
* *
* @author stravant * @author stravant
* *
* Note, this card is pretty hacky in its implementation due to the fact that the alternative cost system doesn't * Note, this card is pretty hacky in its implementation due to the fact that
* really support "once each turn" alternative costs in an obvious way, but it should work in all scenarios as far * the alternative cost system doesn't really support "once each turn"
* as I can see. * alternative costs in an obvious way, but it should work in all scenarios as
* far as I can see.
*/ */
public final class AsForetold extends CardImpl { public final class AsForetold extends CardImpl {
public AsForetold(UUID ownerId, CardSetInfo setInfo) { public AsForetold(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
// At the beginning of your upkeep, put a time counter on As Foretold. // At the beginning of your upkeep, put a time counter on As Foretold.
addAbility( addAbility(
new BeginningOfUpkeepTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(
new AddCountersSourceEffect(CounterType.TIME.createInstance(), new StaticValue(1), true), new AddCountersSourceEffect(
CounterType.TIME.createInstance(),
new StaticValue(1),
true),
TargetController.YOU, TargetController.YOU,
/* optional = */false)); /* optional = */ false));
// Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on As Foretold. // Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on As Foretold.
addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AsForetoldAddAltCostEffect()), new AsForetoldAltCostUsedWatcher()); addAbility(new SimpleStaticAbility(
Zone.BATTLEFIELD,
new AsForetoldAddAltCostEffect()),
new AsForetoldAltCostUsedWatcher());
} }
public AsForetold(final AsForetold card) { public AsForetold(final AsForetold card) {
@ -60,6 +67,7 @@ public final class AsForetold extends CardImpl {
* Used to determine what cast objects to apply the alternative cost to * Used to determine what cast objects to apply the alternative cost to
*/ */
class SpellWithManaCostLessThanOrEqualToCondition implements Condition { class SpellWithManaCostLessThanOrEqualToCondition implements Condition {
private int counters; private int counters;
public SpellWithManaCostLessThanOrEqualToCondition(int counters) { public SpellWithManaCostLessThanOrEqualToCondition(int counters) {
@ -69,17 +77,21 @@ class SpellWithManaCostLessThanOrEqualToCondition implements Condition {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source.getSourceId()); MageObject object = game.getObject(source.getSourceId());
return object != null && !object.isLand() && object.getConvertedManaCost() <= counters; return object != null
&& !object.isLand()
&& object.getConvertedManaCost() <= counters;
} }
} }
/** /**
* Special AlternativeCostSourceAbility implementation. We wrap the call to askToActivateAlternativeCosts in order to * Special AlternativeCostSourceAbility implementation. We wrap the call to
* tell when the alternative cost is used, and mark it as having been used this turn in the watcher * askToActivateAlternativeCosts in order to tell when the alternative cost is
* used, and mark it as having been used this turn in the watcher
*/ */
class AsForetoldAlternativeCost extends AlternativeCostSourceAbility { class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
private UUID sourceAsForetold; private UUID sourceAsForetold;
boolean activated;
AsForetoldAlternativeCost(UUID sourceAsForetold, int timeCounters) { AsForetoldAlternativeCost(UUID sourceAsForetold, int timeCounters) {
super(new ManaCostsImpl("{0}"), new SpellWithManaCostLessThanOrEqualToCondition(timeCounters)); super(new ManaCostsImpl("{0}"), new SpellWithManaCostLessThanOrEqualToCondition(timeCounters));
@ -89,6 +101,7 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) { AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) {
super(ability); super(ability);
this.sourceAsForetold = ability.sourceAsForetold; this.sourceAsForetold = ability.sourceAsForetold;
this.activated = ability.activated;
} }
@Override @Override
@ -98,24 +111,34 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
@Override @Override
public boolean askToActivateAlternativeCosts(Ability ability, Game game) { public boolean askToActivateAlternativeCosts(Ability ability, Game game) {
boolean activated = super.askToActivateAlternativeCosts(ability, game); Player controller = game.getPlayer(ability.getControllerId());
if (activated) { Permanent asForetold = game.getPermanent(sourceAsForetold);
// Get the watcher if (controller != null
AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher = && asForetold != null) {
(AsForetoldAltCostUsedWatcher)game.getState().getWatchers() if (controller.chooseUse(Outcome.Neutral, "Do you wish to use " + asForetold.getLogName() + " to pay the alternative cost ?", ability, game)) {
.get("asForetoldAltCostUsedWatcher", sourceAsForetold); activated = super.askToActivateAlternativeCosts(ability, game);
if (activated) {
// Get the watcher
AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher
= (AsForetoldAltCostUsedWatcher) game.getState().getWatchers()
.get("asForetoldAltCostUsedWatcher", sourceAsForetold);
// Mark as used // Mark as used
asForetoldAltCostUsedWatcher.markUsedThisTurn(); asForetoldAltCostUsedWatcher.markUsedThisTurn();
}
}
} }
return activated; return activated;
} }
} }
/** /**
* The continuous effect that adds the option to pay the alternative cost if we haven't used it yet this turn * The continuous effect that adds the option to pay the alternative cost if we
* haven't used it yet this turn
*/ */
class AsForetoldAddAltCostEffect extends ContinuousEffectImpl { class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
public AsForetoldAddAltCostEffect() { public AsForetoldAddAltCostEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit); super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on {this}."; staticText = "Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on {this}.";
@ -137,8 +160,8 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) { if (sourcePermanent != null) {
// Get the watcher // Get the watcher
AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher = AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher
(AsForetoldAltCostUsedWatcher)game.getState().getWatchers() = (AsForetoldAltCostUsedWatcher) game.getState().getWatchers()
.get("asForetoldAltCostUsedWatcher", sourcePermanent.getId()); .get("asForetoldAltCostUsedWatcher", sourcePermanent.getId());
// If we haven't used it yet this turn, give the option of using the zero alternative cost // If we haven't used it yet this turn, give the option of using the zero alternative cost
@ -166,13 +189,15 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
} }
/** /**
* Watcher used as extra storage to record whether a given As Foretold has been used this turn. * Watcher used as extra storage to record whether a given As Foretold has been
* Technically speaking this watcher doesn't *watch* any GameEvents, but it does "watch" the * used this turn. Technically speaking this watcher doesn't *watch* any
* alternative cost being used. That just isn't possible to watch through a game event. It's still * GameEvents, but it does "watch" the alternative cost being used. That just
* helpfull to co-op the Watcher system for this since it automatically handles ZoneChangeCounter * isn't possible to watch through a game event. It's still helpful to co-op the
* Watcher system for this since it automatically handles ZoneChangeCounter
* stuff and resetting the condition at the end of the turn. * stuff and resetting the condition at the end of the turn.
*/ */
class AsForetoldAltCostUsedWatcher extends Watcher { class AsForetoldAltCostUsedWatcher extends Watcher {
public AsForetoldAltCostUsedWatcher() { public AsForetoldAltCostUsedWatcher() {
super("asForetoldAltCostUsedWatcher", WatcherScope.CARD); super("asForetoldAltCostUsedWatcher", WatcherScope.CARD);
} }
@ -198,4 +223,4 @@ class AsForetoldAltCostUsedWatcher extends Watcher {
public AsForetoldAltCostUsedWatcher copy() { public AsForetoldAltCostUsedWatcher copy() {
return new AsForetoldAltCostUsedWatcher(this); return new AsForetoldAltCostUsedWatcher(this);
} }
} }

View file

@ -1,6 +1,7 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
@ -21,7 +22,6 @@ import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class AssassinsTrophy extends CardImpl { public final class AssassinsTrophy extends CardImpl {
@ -74,17 +74,19 @@ class AssassinsTrophyEffect extends OneShotEffect {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
if (permanent != null) { if (permanent != null) {
Player controller = game.getPlayer(permanent.getControllerId()); Player controller = game.getPlayer(permanent.getControllerId());
if (controller.chooseUse(Outcome.PutLandInPlay, "Do you wish to search for a basic land, put it onto the battlefield and then shuffle your library?", source, game)) { if (controller != null) {
TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); if (controller.chooseUse(Outcome.PutLandInPlay, "Do you wish to search for a basic land, put it onto the battlefield and then shuffle your library?", source, game)) {
if (controller.searchLibrary(target, game)) { TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND);
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); if (controller.searchLibrary(target, game)) {
if (card != null) { Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
controller.moveCards(card, Zone.BATTLEFIELD, source, game); if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
} }
controller.shuffleLibrary(source, game);
} }
controller.shuffleLibrary(source, game); return true;
} }
return true;
} }
return false; return false;
} }

View file

@ -55,7 +55,7 @@ public final class AtalyaSamiteMaster extends CardImpl {
// or you gain X life // or you gain X life
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new GainLifeEffect(new ManacostVariableValue()).setText("You gain X life. Spend only white mana on X.")); mode.addEffect(new GainLifeEffect(new ManacostVariableValue()).setText("You gain X life. Spend only white mana on X."));
ability.addMode(mode); ability.addMode(mode);
this.addAbility(ability); this.addAbility(ability);

View file

@ -35,22 +35,22 @@ public final class AtarkasCommand extends CardImpl {
// or Atarka's Command deals 3 damage to each opponent; // or Atarka's Command deals 3 damage to each opponent;
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DamagePlayersEffect(3, TargetController.OPPONENT)); mode.addEffect(new DamagePlayersEffect(3, TargetController.OPPONENT));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// or You may put a land card from your hand onto the battlefield; // or You may put a land card from your hand onto the battlefield;
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A)); mode.addEffect(new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// or Creatures you control get +1/+1 and gain reach until the end of turn. // or Creatures you control get +1/+1 and gain reach until the end of turn.
mode = new Mode(); mode = new Mode();
Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn); Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn);
effect.setText("Creatures you control get +1/+1"); effect.setText("Creatures you control get +1/+1");
mode.getEffects().add(effect); mode.addEffect(effect);
effect = new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn); effect = new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and gain reach until the end of turn"); effect.setText("and gain reach until the end of turn");
mode.getEffects().add(effect); mode.addEffect(effect);
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -99,7 +99,7 @@ class AthreosGodOfPassageReturnEffect extends OneShotEffect {
if (opponent != null) { if (opponent != null) {
Cost cost = new PayLifeCost(3); Cost cost = new PayLifeCost(3);
if (cost.canPay(source, source.getSourceId(), opponent.getId(), game) if (cost.canPay(source, source.getSourceId(), opponent.getId(), game)
&& opponent.chooseUse(outcome, new StringBuilder("Pay 3 live to prevent that ").append(creature.getLogName()).append(" returns to ").append(controller.getLogName()).append("'s hand?").toString(), source, game)) { && opponent.chooseUse(outcome, "Pay 3 life to prevent that " + creature.getLogName() + " returns to " + controller.getLogName() + "'s hand?", source, game)) {
if (cost.pay(source, game, source.getSourceId(), opponent.getId(), false, null)) { if (cost.pay(source, game, source.getSourceId(), opponent.getId(), false, null)) {
paid = true; paid = true;
} }

View file

@ -37,15 +37,15 @@ public final class AustereCommand extends CardImpl {
this.getSpellAbility().addEffect(new DestroyAllEffect(new FilterArtifactPermanent("artifacts"))); this.getSpellAbility().addEffect(new DestroyAllEffect(new FilterArtifactPermanent("artifacts")));
// or destroy all enchantments; // or destroy all enchantments;
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DestroyAllEffect(new FilterEnchantmentPermanent("enchantments"))); mode.addEffect(new DestroyAllEffect(new FilterEnchantmentPermanent("enchantments")));
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// or destroy all creatures with converted mana cost 3 or less; // or destroy all creatures with converted mana cost 3 or less;
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new DestroyAllEffect(filter3orLess)); mode.addEffect(new DestroyAllEffect(filter3orLess));
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// or destroy all creatures with converted mana cost 4 or greater. // or destroy all creatures with converted mana cost 4 or greater.
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new DestroyAllEffect(filter4orMore)); mode.addEffect(new DestroyAllEffect(filter4orMore));
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
} }

View file

@ -91,9 +91,7 @@ class AvenEffect extends ContinuousEffectImpl {
@Override @Override
public String getText(Mode mode) { public String getText(Mode mode) {
StringBuilder sb = new StringBuilder(); return "If you do, that creature has base power and toughness 3/1 and has flying for as long as it has a feather counter on it";
sb.append("If you do, that creature has base power and toughness 3/1 and has flying for as long as it has a feather counter on it");
return sb.toString();
} }
} }

View file

@ -67,7 +67,7 @@ class AvenShrineTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId()); Spell spell = game.getStack().getSpell(event.getTargetId());
MageObject mageObject = game.getObject(sourceId); MageObject mageObject = game.getObject(sourceId);
if (spell != null) { if (spell != null && mageObject != null) {
game.getState().setValue("avenShrine" + mageObject, spell); game.getState().setValue("avenShrine" + mageObject, spell);
return true; return true;
} }
@ -91,21 +91,23 @@ class AvenShrineEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
int count = 0; int count = 0;
MageObject mageObject = game.getObject(source.getSourceId()); MageObject mageObject = game.getObject(source.getSourceId());
Spell spell = (Spell) game.getState().getValue("avenShrine" + mageObject); if(mageObject != null) {
if (spell != null) { Spell spell = (Spell) game.getState().getValue("avenShrine" + mageObject);
Player controller = game.getPlayer(spell.getControllerId()); if (spell != null) {
if (controller != null) { Player controller = game.getPlayer(spell.getControllerId());
String name = spell.getName(); if (controller != null) {
FilterCard filterCardName = new FilterCard(); String name = spell.getName();
filterCardName.add(new NamePredicate(name)); FilterCard filterCardName = new FilterCard();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { filterCardName.add(new NamePredicate(name));
Player player = game.getPlayer(playerId); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
if (player != null) { Player player = game.getPlayer(playerId);
count += player.getGraveyard().count(filterCardName, game); if (player != null) {
count += player.getGraveyard().count(filterCardName, game);
}
} }
controller.gainLife(count, game, source);
return true;
} }
controller.gainLife(count, game, source);
return true;
} }
} }
return false; return false;

View file

@ -38,8 +38,8 @@ public final class AvenSurveyor extends CardImpl {
// * Return target creature to its owner's hand // * Return target creature to its owner's hand
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new ReturnToHandTargetEffect()); mode.addEffect(new ReturnToHandTargetEffect());
mode.getTargets().add(new TargetCreaturePermanent()); mode.addTarget(new TargetCreaturePermanent());
ability.addMode(mode); ability.addMode(mode);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -78,6 +78,9 @@ class AyliEternalPilgrimCondition implements Condition {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
return player.getLife() >= game.getLife() + 10; if(player != null) {
return player.getLife() >= game.getLife() + 10;
}
return false;
} }
} }

View file

@ -29,13 +29,13 @@ public final class AzoriusCharm extends CardImpl {
// or draw a card; // or draw a card;
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DrawCardSourceControllerEffect(1)); mode.addEffect(new DrawCardSourceControllerEffect(1));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// or put target attacking or blocking creature on top of its owner's library. // or put target attacking or blocking creature on top of its owner's library.
mode = new Mode(); mode = new Mode();
mode.getTargets().add(new TargetAttackingOrBlockingCreature()); mode.addTarget(new TargetAttackingOrBlockingCreature());
mode.getEffects().add(new PutOnLibraryTargetEffect(true)); mode.addEffect(new PutOnLibraryTargetEffect(true));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -106,7 +106,7 @@ class BalaGedThiefEffect extends OneShotEffect {
Card card = revealedCards.get(targetInHand.getFirstTarget(), game); Card card = revealedCards.get(targetInHand.getFirstTarget(), game);
if (card != null) { if (card != null) {
targetPlayer.discard(card, source, game); targetPlayer.discard(card, source, game);
game.informPlayers(new StringBuilder("Bala Ged Thief: ").append(targetPlayer.getLogName()).append(" discarded ").append(card.getName()).toString()); game.informPlayers("Bala Ged Thief: " + targetPlayer.getLogName() + " discarded " + card.getName());
} }
} }
return true; return true;

View file

@ -33,8 +33,8 @@ public final class BalmOfRestoration extends CardImpl {
// or prevent the next 2 damage that would be dealt to any target this turn. // or prevent the next 2 damage that would be dealt to any target this turn.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new PreventDamageToTargetEffect(Duration.EndOfTurn, 2)); mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, 2));
mode.getTargets().add(new TargetAnyTarget()); mode.addTarget(new TargetAnyTarget());
ability.addMode(mode); ability.addMode(mode);
this.addAbility(ability); this.addAbility(ability);

View file

@ -112,7 +112,7 @@ class BaneAlleyBrokerDrawExileEffect extends OneShotEffect {
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
MageObject sourceObject = game.getObject(source.getSourceId()); MageObject sourceObject = game.getObject(source.getSourceId());
if (card != null && sourceObject != null) { if (card != null && sourceObject != null) {
if (card.moveToExile(CardUtil.getCardExileZoneId(game, source), new StringBuilder(sourceObject.getName()).toString(), source.getSourceId(), game)) { if (card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceObject.getName(), source.getSourceId(), game)) {
card.setFaceDown(true, game); card.setFaceDown(true, game);
return true; return true;
} }

View file

@ -36,13 +36,13 @@ public final class BantCharm extends CardImpl {
this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addTarget(new TargetArtifactPermanent());
// or put target creature on the bottom of its owner's library; // or put target creature on the bottom of its owner's library;
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new PutOnLibraryTargetEffect(false)); mode.addEffect(new PutOnLibraryTargetEffect(false));
mode.getTargets().add(new TargetCreaturePermanent()); mode.addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// or counter target instant spell. // or counter target instant spell.
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new CounterTargetEffect()); mode.addEffect(new CounterTargetEffect());
mode.getTargets().add(new TargetSpell(filter)); mode.addTarget(new TargetSpell(filter));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -26,8 +26,8 @@ public final class BarbedLightning extends CardImpl {
// or Barbed Lightning deals 3 damage to target player. // or Barbed Lightning deals 3 damage to target player.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new DamageTargetEffect(3)); mode.addEffect(new DamageTargetEffect(3));
mode.getTargets().add(new TargetPlayerOrPlaneswalker()); mode.addTarget(new TargetPlayerOrPlaneswalker());
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// Entwine {2} // Entwine {2}

View file

@ -67,16 +67,18 @@ class BarrinsSpiteEffect extends OneShotEffect {
Permanent creature = game.getPermanent(targetId); Permanent creature = game.getPermanent(targetId);
if (creature != null) { if (creature != null) {
Player controllerOfCreature = game.getPlayer(creature.getControllerId()); Player controllerOfCreature = game.getPlayer(creature.getControllerId());
if ((count == 0 if(controllerOfCreature != null) {
&& controllerOfCreature.chooseUse(Outcome.Sacrifice, "Sacrifice " + creature.getLogName() + '?', source, game)) if ((count == 0
|| (count == 1 && controllerOfCreature.chooseUse(Outcome.Sacrifice, "Sacrifice " + creature.getLogName() + '?', source, game))
&& !sacrificeDone)) { || (count == 1
creature.sacrifice(source.getId(), game); && !sacrificeDone)) {
sacrificeDone = true; creature.sacrifice(source.getId(), game);
} else { sacrificeDone = true;
creature.moveToZone(Zone.HAND, source.getId(), game, false); } else {
creature.moveToZone(Zone.HAND, source.getId(), game, false);
}
count++;
} }
count++;
} }
} }
return true; return true;

View file

@ -2,6 +2,7 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -17,13 +18,12 @@ import mage.game.events.GameEvent.EventType;
import mage.players.Player; import mage.players.Player;
/** /**
*
* @author emerald000 * @author emerald000
*/ */
public final class BattletideAlchemist extends CardImpl { public final class BattletideAlchemist extends CardImpl {
public BattletideAlchemist(UUID ownerId, CardSetInfo setInfo) { public BattletideAlchemist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.subtype.add(SubType.KITHKIN, SubType.CLERIC); this.subtype.add(SubType.KITHKIN, SubType.CLERIC);
this.power = new MageInt(3); this.power = new MageInt(3);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
@ -63,7 +63,7 @@ class BattletideAlchemistEffect extends PreventionEffectImpl {
boolean result = false; boolean result = false;
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(event.getTargetId()); Player targetPlayer = game.getPlayer(event.getTargetId());
if (controller != null) { if (controller != null && targetPlayer != null) {
int numberOfClericsControlled = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent(SubType.CLERIC, "Clerics")).calculate(game, source, this); int numberOfClericsControlled = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent(SubType.CLERIC, "Clerics")).calculate(game, source, this);
int toPrevent = Math.min(numberOfClericsControlled, event.getAmount()); int toPrevent = Math.min(numberOfClericsControlled, event.getAmount());
if (toPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + toPrevent + " damage to " + targetPlayer.getName() + '?', source, game)) { if (toPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + toPrevent + " damage to " + targetPlayer.getName() + '?', source, game)) {
@ -71,20 +71,18 @@ class BattletideAlchemistEffect extends PreventionEffectImpl {
if (!game.replaceEvent(preventEvent)) { if (!game.replaceEvent(preventEvent)) {
if (event.getAmount() >= toPrevent) { if (event.getAmount() >= toPrevent) {
event.setAmount(event.getAmount() - toPrevent); event.setAmount(event.getAmount() - toPrevent);
} } else {
else {
event.setAmount(0); event.setAmount(0);
result = true; result = true;
} }
if (toPrevent > 0) { game.informPlayers("Battletide Alchemist prevented " + toPrevent + " damage to " + targetPlayer.getName());
game.informPlayers("Battletide Alchemist prevented " + toPrevent + " damage to " + targetPlayer.getName()); game.fireEvent(GameEvent.getEvent(
game.fireEvent(GameEvent.getEvent( GameEvent.EventType.PREVENTED_DAMAGE,
GameEvent.EventType.PREVENTED_DAMAGE, targetPlayer.getId(),
targetPlayer.getId(), source.getSourceId(),
source.getSourceId(), source.getControllerId(),
source.getControllerId(), toPrevent));
toPrevent));
}
} }
} }
} }

View file

@ -6,7 +6,7 @@ import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.game.permanent.token.BeckonApparitionToken; import mage.game.permanent.token.WhiteBlackSpiritToken;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyard;
import java.util.UUID; import java.util.UUID;
@ -22,7 +22,7 @@ public final class BeckonApparition extends CardImpl {
// Exile target card from a graveyard. Create a 1/1 white and black Spirit creature token with flying. // Exile target card from a graveyard. Create a 1/1 white and black Spirit creature token with flying.
this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard()); this.getSpellAbility().addTarget(new TargetCardInGraveyard());
this.getSpellAbility().addEffect(new CreateTokenEffect(new BeckonApparitionToken(), 1)); this.getSpellAbility().addEffect(new CreateTokenEffect(new WhiteBlackSpiritToken(), 1));
} }
public BeckonApparition(final BeckonApparition card) { public BeckonApparition(final BeckonApparition card) {

View file

@ -0,0 +1,45 @@
package mage.cards.b;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Bedevil extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifact, creature, or planeswalker");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.PLANESWALKER)
));
}
public Bedevil(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}{R}");
// Destroy target artifact, creature, or planeswalker.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetPermanent(filter));
}
public Bedevil(final Bedevil card) {
super(card);
}
@Override
public Bedevil copy() {
return new Bedevil(this);
}
}

View file

@ -34,8 +34,8 @@ public final class BetrayalOfFlesh extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// or return target creature card from your graveyard to the battlefield. // or return target creature card from your graveyard to the battlefield.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new ReturnFromGraveyardToBattlefieldTargetEffect()); mode.addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
mode.getTargets().add(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); mode.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// Entwine-Sacrifice three lands. // Entwine-Sacrifice three lands.
this.addAbility(new EntwineAbility(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, new FilterControlledLandPermanent("three lands"), true)))); this.addAbility(new EntwineAbility(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, new FilterControlledLandPermanent("three lands"), true))));

View file

@ -105,6 +105,6 @@ class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public String getRule() { public String getRule() {
return new StringBuilder("Whenever an instant or sorcery spell you control deals damage, ").append(super.getRule()).toString(); return "Whenever an instant or sorcery spell you control deals damage, " + super.getRule();
} }
} }

View file

@ -75,13 +75,15 @@ class BlazingHopeTarget extends TargetCreaturePermanent {
int count = 0; int count = 0;
Player controller = game.getPlayer(sourceControllerId); Player controller = game.getPlayer(sourceControllerId);
MageObject targetSource = game.getObject(sourceId); MageObject targetSource = game.getObject(sourceId);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if(targetSource != null) {
if (!targets.containsKey(permanent.getId())) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId())) {
if (controller != null && permanent.getPower().getValue() >= controller.getLife()) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) {
count++; if (controller != null && permanent.getPower().getValue() >= controller.getLife()) {
if (count >= remainingTargets) { count++;
return true; if (count >= remainingTargets) {
return true;
}
} }
} }
} }

View file

@ -54,14 +54,14 @@ public final class BlessedAlliance extends CardImpl {
Mode mode = new Mode(); Mode mode = new Mode();
effect = new UntapTargetEffect(); effect = new UntapTargetEffect();
effect.setText("Untap up to two target creatures"); effect.setText("Untap up to two target creatures");
mode.getEffects().add(effect); mode.addEffect(effect);
mode.getTargets().add(new TargetCreaturePermanent(0, 2, filterCreature, false)); mode.addTarget(new TargetCreaturePermanent(0, 2, filterCreature, false));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// Target opponent sacrifices an attacking creature. // Target opponent sacrifices an attacking creature.
mode = new Mode(); mode = new Mode();
mode.getEffects().add(new SacrificeEffect(new FilterAttackingCreature(), 1, "Target opponent")); mode.addEffect(new SacrificeEffect(new FilterAttackingCreature(), 1, "Target opponent"));
mode.getTargets().add(new TargetPlayer(1, 1, false, filterSacrifice)); mode.addTarget(new TargetPlayer(1, 1, false, filterSacrifice));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -42,8 +42,8 @@ public final class BlindingBeam extends CardImpl {
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2,2)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2,2));
// or creatures don't untap during target player's next untap step. // or creatures don't untap during target player's next untap step.
Mode mode = new Mode(); Mode mode = new Mode();
mode.getEffects().add(new BlindingBeamEffect()); mode.addEffect(new BlindingBeamEffect());
mode.getTargets().add(new TargetPlayer()); mode.addTarget(new TargetPlayer());
this.getSpellAbility().getModes().addMode(mode); this.getSpellAbility().getModes().addMode(mode);
// Entwine {1} // Entwine {1}

Some files were not shown because too many files have changed in this diff Show more