Merge pull request #1 from magefree/master
Implement "Pure Reflection" from Invasion.
4
.gitignore
vendored
|
@ -4,7 +4,7 @@ syntax: glob
|
|||
Mage.Client/*.dck
|
||||
Mage.Client/db
|
||||
Mage.Client/gamelogs
|
||||
Mage.Client/mageclient.log
|
||||
Mage.Client/*.log
|
||||
Mage.Client/plugins/images
|
||||
Mage.Client/plugins/plugin.data
|
||||
Mage.Client/target
|
||||
|
@ -44,6 +44,7 @@ Mage.Server.Plugins/Mage.Game.CommanderDuel/target
|
|||
Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/
|
||||
Mage.Server.Plugins/Mage.Game.FreeForAll/target
|
||||
Mage.Server.Plugins/Mage.Game.MomirDuel/target
|
||||
Mage.Server.Plugins/Mage.Game.MomirGame/target/
|
||||
Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target
|
||||
Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target
|
||||
Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target
|
||||
|
@ -132,3 +133,4 @@ Mage.Client/serverlist.txt
|
|||
client_secrets.json
|
||||
|
||||
dependency-reduced-pom.xml
|
||||
mage-bundle
|
||||
|
|
|
@ -141,6 +141,18 @@
|
|||
<artifactId>balloontip</artifactId>
|
||||
<version>1.2.4.1</version>
|
||||
</dependency>
|
||||
<!-- svg support start -->
|
||||
<dependency>
|
||||
<groupId>batik</groupId>
|
||||
<artifactId>batik-transcoder</artifactId>
|
||||
<version>1.6-1</version>
|
||||
</dependency>
|
||||
<!-- svg support end -->
|
||||
<dependency>
|
||||
<groupId>org.ocpsoft.prettytime</groupId>
|
||||
<artifactId>prettytime</artifactId>
|
||||
<version>3.2.7.Final</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
XMage.de 1 (Europe/Germany) fast :xmage.de:17171
|
||||
woogerworks (North America/USA) :xmage.woogerworks.com:17171
|
||||
xmage.lukeskywalk.com (North America) :xmage.lukeskywalk.com:17171
|
||||
play.xmage.net (North America/Canada) :play.xmage.net:17171
|
||||
XMageBr. (South America/Brazil) :magic.ncs3sistemas.com.br:17171
|
||||
XMage.tahiti :xmage.tahiti.one:443
|
||||
|
|
|
@ -50,6 +50,7 @@ import mage.client.chat.ChatPanelBasic;
|
|||
import mage.client.components.*;
|
||||
import mage.client.components.ext.dlg.DialogManager;
|
||||
import mage.client.components.tray.MageTray;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.constants.Constants.DeckEditorMode;
|
||||
import mage.client.deckeditor.DeckEditorPane;
|
||||
import mage.client.deckeditor.collection.viewer.CollectionViewerPane;
|
||||
|
@ -237,10 +238,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
SessionHandler.startSession(this);
|
||||
callbackClient = new CallbackClientImpl(this);
|
||||
connectDialog = new ConnectDialog();
|
||||
desktopPane.add(connectDialog, JLayeredPane.POPUP_LAYER);
|
||||
desktopPane.add(connectDialog, JLayeredPane.MODAL_LAYER);
|
||||
errorDialog = new ErrorDialog();
|
||||
errorDialog.setLocation(100, 100);
|
||||
desktopPane.add(errorDialog, JLayeredPane.POPUP_LAYER);
|
||||
desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER);
|
||||
UI.addComponent(MageComponents.DESKTOP_PANE, desktopPane);
|
||||
|
||||
PING_TASK_EXECUTOR.scheduleAtFixedRate(() -> SessionHandler.ping(), 60, 60, TimeUnit.SECONDS);
|
||||
|
@ -283,6 +284,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
balloonTip.setPositioner(new LeftAbovePositioner(0, 0));
|
||||
balloonTip.setVisible(false);
|
||||
|
||||
// tooltips delay in ms
|
||||
ToolTipManager.sharedInstance().setDismissDelay(Constants.TOOLTIPS_DELAY_MS);
|
||||
|
||||
mageToolbar.add(createSwitchPanelsButton(), 0);
|
||||
mageToolbar.add(new javax.swing.JToolBar.Separator(), 1);
|
||||
|
||||
|
@ -427,17 +431,46 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isChrismasTime(Date currentTime){
|
||||
// from december 15 to january 15
|
||||
Calendar cal = new GregorianCalendar();
|
||||
cal.setTime(currentTime);
|
||||
|
||||
int currentYear = cal.get(Calendar.YEAR);
|
||||
if (cal.get(Calendar.MONTH) == Calendar.JANUARY){
|
||||
currentYear = currentYear - 1;
|
||||
}
|
||||
|
||||
Date chrisFrom = new GregorianCalendar(currentYear, Calendar.DECEMBER, 15).getTime();
|
||||
Date chrisTo = new GregorianCalendar(currentYear + 1, Calendar.JANUARY, 15 + 1).getTime(); // end of the 15 day
|
||||
|
||||
return ((currentTime.equals(chrisFrom) || currentTime.after(chrisFrom))
|
||||
&& currentTime.before(chrisTo));
|
||||
}
|
||||
|
||||
private void addMageLabel() {
|
||||
if (liteMode || grayMode) {
|
||||
return;
|
||||
}
|
||||
String filename = "/label-xmage.png";
|
||||
|
||||
String filename;
|
||||
float ratio;
|
||||
if (isChrismasTime(Calendar.getInstance().getTime())){
|
||||
// chrismass logo
|
||||
LOGGER.info("Yo Ho Ho, Merry Christmas and a Happy New Year");
|
||||
filename = "/label-xmage-christmas.png";
|
||||
ratio = 539.0f / 318.0f;
|
||||
}else{
|
||||
// standard logo
|
||||
filename = "/label-xmage.png";
|
||||
ratio = 509.0f / 288.0f;
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream is = this.getClass().getResourceAsStream(filename);
|
||||
|
||||
float ratio = 1179.0f / 678.0f;
|
||||
titleRectangle = new Rectangle(540, (int) (640 / ratio));
|
||||
if (is != null) {
|
||||
titleRectangle = new Rectangle(540, (int) (640 / ratio));
|
||||
|
||||
BufferedImage image = ImageIO.read(is);
|
||||
//ImageIcon resized = new ImageIcon(image.getScaledInstance(titleRectangle.width, titleRectangle.height, java.awt.Image.SCALE_SMOOTH));
|
||||
title = new JLabel();
|
||||
|
@ -919,7 +952,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}//GEN-LAST:event_btnConnectActionPerformed
|
||||
|
||||
public void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed
|
||||
JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.POPUP_LAYER);
|
||||
JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.MODAL_LAYER);
|
||||
for (JInternalFrame window : windows) {
|
||||
if (window instanceof AboutDialog) {
|
||||
// don't open the window twice.
|
||||
|
@ -927,7 +960,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
}
|
||||
AboutDialog aboutDialog = new AboutDialog();
|
||||
desktopPane.add(aboutDialog, JLayeredPane.POPUP_LAYER);
|
||||
desktopPane.add(aboutDialog, JLayeredPane.MODAL_LAYER);
|
||||
aboutDialog.showDialog(VERSION);
|
||||
}//GEN-LAST:event_btnAboutActionPerformed
|
||||
|
||||
|
@ -1070,7 +1103,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
public void showUserRequestDialog(final UserRequestMessage userRequestMessage) {
|
||||
final UserRequestDialog userRequestDialog = new UserRequestDialog();
|
||||
userRequestDialog.setLocation(100, 100);
|
||||
desktopPane.add(userRequestDialog, JLayeredPane.POPUP_LAYER);
|
||||
desktopPane.add(userRequestDialog, JLayeredPane.MODAL_LAYER);
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
userRequestDialog.showDialog(userRequestMessage);
|
||||
} else {
|
||||
|
|
|
@ -562,7 +562,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setTextOffset(int yOffset) {
|
||||
public void setCardCaptionTopOffset(int yOffsetPercent) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public class CardArea extends JPanel implements MouseListener {
|
|||
private boolean reloaded = false;
|
||||
private final javax.swing.JLayeredPane cardArea;
|
||||
private final javax.swing.JScrollPane scrollPane;
|
||||
private int yTextOffset;
|
||||
private int yCardCaptionOffsetPercent = 0; // card caption offset (use for moving card caption view center, below mana icons -- for more good UI)
|
||||
private Dimension cardDimension;
|
||||
private int verticalCardOffset;
|
||||
|
||||
|
@ -68,8 +68,6 @@ public class CardArea extends JPanel implements MouseListener {
|
|||
setGUISize();
|
||||
cardArea = new JLayeredPane();
|
||||
scrollPane.setViewportView(cardArea);
|
||||
yTextOffset = 10;
|
||||
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
|
@ -103,10 +101,10 @@ public class CardArea extends JPanel implements MouseListener {
|
|||
this.reloaded = true;
|
||||
cardArea.removeAll();
|
||||
if (showCards != null && showCards.size() < 10) {
|
||||
yTextOffset = 10;
|
||||
yCardCaptionOffsetPercent = 8; // TODO: need to test
|
||||
loadCardsFew(showCards, bigCard, gameId);
|
||||
} else {
|
||||
yTextOffset = 0;
|
||||
yCardCaptionOffsetPercent = 0;
|
||||
loadCardsMany(showCards, bigCard, gameId);
|
||||
}
|
||||
cardArea.revalidate();
|
||||
|
@ -118,8 +116,10 @@ public class CardArea extends JPanel implements MouseListener {
|
|||
public void loadCardsNarrow(CardsView showCards, BigCard bigCard, UUID gameId) {
|
||||
this.reloaded = true;
|
||||
cardArea.removeAll();
|
||||
yTextOffset = 0;
|
||||
|
||||
yCardCaptionOffsetPercent = 0; // TODO: need to test
|
||||
loadCardsMany(showCards, bigCard, gameId);
|
||||
|
||||
cardArea.revalidate();
|
||||
|
||||
this.revalidate();
|
||||
|
@ -152,7 +152,10 @@ public class CardArea extends JPanel implements MouseListener {
|
|||
cardArea.moveToFront(cardPanel);
|
||||
cardPanel.update(card);
|
||||
cardPanel.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
|
||||
cardPanel.setTextOffset(yTextOffset);
|
||||
|
||||
// new card have same settings as current view
|
||||
cardPanel.setCardCaptionTopOffset(yCardCaptionOffsetPercent);
|
||||
|
||||
cardPanel.showCardTitle();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import mage.view.CardView;
|
|||
import mage.view.CardsView;
|
||||
import mage.view.SimpleCardView;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
import org.mage.card.arcane.ManaSymbolsCellRenderer;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
|
@ -164,6 +165,9 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
mainTable.getColumnModel().getColumn(6).setPreferredWidth(15);
|
||||
mainTable.getColumnModel().getColumn(7).setPreferredWidth(15);
|
||||
|
||||
// new mana render (svg support)
|
||||
mainTable.getColumnModel().getColumn(mainModel.COLUMN_INDEX_COST).setCellRenderer(new ManaSymbolsCellRenderer());
|
||||
|
||||
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView").equals("listView")) {
|
||||
jToggleListView.setSelected(true);
|
||||
panelCardArea.setViewportView(mainTable);
|
||||
|
|
|
@ -1726,7 +1726,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
|
|||
// Create the card view
|
||||
final MageCard cardPanel = Plugins.instance.getMageCard(card, lastBigCard, new Dimension(getCardWidth(), getCardHeight()), null, true, true);
|
||||
cardPanel.update(card);
|
||||
cardPanel.setTextOffset(0);
|
||||
cardPanel.setCardCaptionTopOffset(0);
|
||||
|
||||
// Remove mouse wheel listeners so that scrolling works
|
||||
// Scrolling works on all areas without cards or by using the scroll bar, that's enough
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.client.constants;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.border.Border;
|
||||
|
@ -68,22 +69,52 @@ public final class Constants {
|
|||
public static final int POWBOX_TEXT_MAX_LEFT = 212;
|
||||
public static final int DAMAGE_MAX_LEFT = 180;
|
||||
|
||||
// tooltip hints delay in ms (need more time to display long hints withour hiding)
|
||||
public static final int TOOLTIPS_DELAY_MS = 60 * 1000;
|
||||
|
||||
public static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(2, 2, 2, 2);
|
||||
|
||||
public static final double SCALE_FACTOR = 0.5;
|
||||
|
||||
public static final String PLUGINS_DIRECTORY = "plugins/";
|
||||
// cards render
|
||||
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
|
||||
public static final Rectangle THUMBNAIL_SIZE_FULL = new Rectangle(102, 146);
|
||||
|
||||
public static final String RESOURCE_PATH_MANA_LARGE = IO.imageBaseDir + "symbols" + File.separator + "large";
|
||||
public static final String RESOURCE_PATH_MANA_MEDIUM = IO.imageBaseDir + "symbols" + File.separator + "medium";
|
||||
public static final String RESOURCE_PATH_SET = IO.imageBaseDir + "sets" + File.separator;
|
||||
public static final String RESOURCE_PATH_SET_SMALL = RESOURCE_PATH_SET + File.separator + "small" + File.separator;
|
||||
public static final String BASE_SOUND_PATH = "sounds" + File.separator;
|
||||
// resources - default images
|
||||
public static final String RESOURCE_PATH_DEFAUL_IMAGES = File.separator + "default";
|
||||
|
||||
// resources - symbols
|
||||
public static final String RESOURCE_PATH_SYMBOLS = File.separator + "symbols";
|
||||
public static final String RESOURCE_SYMBOL_FOLDER_SMALL = "small";
|
||||
public static final String RESOURCE_SYMBOL_FOLDER_MEDIUM = "medium";
|
||||
public static final String RESOURCE_SYMBOL_FOLDER_LARGE = "large";
|
||||
public static final String RESOURCE_SYMBOL_FOLDER_SVG = "svg";
|
||||
public static final String RESOURCE_SYMBOL_FOLDER_PNG = "png";
|
||||
public enum ResourceSymbolSize {
|
||||
SMALL,
|
||||
MEDIUM,
|
||||
LARGE,
|
||||
SVG,
|
||||
PNG
|
||||
}
|
||||
|
||||
// resources - sets
|
||||
public static final String RESOURCE_PATH_SETS = File.separator + "sets";
|
||||
public static final String RESOURCE_SET_FOLDER_SMALL = "small";
|
||||
public static final String RESOURCE_SET_FOLDER_MEDIUM = ""; // empty, medium images laydown in "sets" folder, TODO: delete that and auto gen, use png for html, not gif
|
||||
public static final String RESOURCE_SET_FOLDER_SVG = "svg";
|
||||
public enum ResourceSetSize {
|
||||
SMALL,
|
||||
MEDIUM,
|
||||
SVG
|
||||
}
|
||||
|
||||
// sound
|
||||
public static final String BASE_SOUND_PATH = "sounds" + File.separator; // TODO: check path with File.separator
|
||||
public static final String BASE_MUSICS_PATH = "music" + File.separator;
|
||||
|
||||
public interface IO {
|
||||
|
||||
String imageBaseDir = "plugins" + File.separator + "images" + File.separator;
|
||||
String DEFAULT_IMAGES_DIR = "plugins" + File.separator + "images" + File.separator;
|
||||
String IMAGE_PROPERTIES_FILE = "image.url.properties";
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import mage.cards.decks.Deck;
|
|||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.gui.ColorsChooser;
|
||||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
|
||||
/**
|
||||
|
@ -106,21 +107,38 @@ public class DeckGeneratorDialog {
|
|||
c.weightx = 0.10;
|
||||
mainPanel.add(formatSetText, c);
|
||||
|
||||
// Format/set dropdown
|
||||
// Format/set dropdown with search button
|
||||
JPanel setPanel = new JPanel();
|
||||
setPanel.setLayout(new javax.swing.BoxLayout(setPanel, javax.swing.BoxLayout.LINE_AXIS));
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
c.ipadx = 30;
|
||||
c.insets = new Insets(5, 10, 0, 10);
|
||||
c.weightx = 0.90;
|
||||
c.weightx = 0.80;
|
||||
mainPanel.add(setPanel, c);
|
||||
|
||||
cbSets = new JComboBox<>(ConstructedFormats.getTypes());
|
||||
cbSets.setSelectedIndex(0);
|
||||
mainPanel.add(cbSets, c);
|
||||
cbSets.setAlignmentX(0.0F);
|
||||
setPanel.add(cbSets);
|
||||
|
||||
String prefSet = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_SET, null);
|
||||
if (prefSet != null) {
|
||||
cbSets.setSelectedItem(prefSet);
|
||||
}
|
||||
|
||||
JButton btn = new JButton();
|
||||
btn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_32.png")));
|
||||
btn.setToolTipText(FastSearchUtil.DEFAULT_EXPANSION_TOOLTIP_MESSAGE);
|
||||
btn.setAlignmentX(1.0F);
|
||||
btn.setPreferredSize(new java.awt.Dimension(32, 32));
|
||||
btn.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
FastSearchUtil.showFastSearchForStringComboBox(cbSets, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
|
||||
}
|
||||
});
|
||||
//setPanel.add(btn, c); // TODO: can't show pickdialog here... need to replace standard modal dialog (JOptionPane) to internal mage dialog
|
||||
|
||||
// Deck size label
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
|
|
@ -204,6 +204,24 @@
|
|||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnExpansionSearch">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/search_32.png"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Fast search set or expansion"/>
|
||||
<Property name="alignmentX" type="float" value="1.0"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[23, 23]"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnExpansionSearchActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToolBar$Separator" name="jSeparator2">
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkPennyDreadful">
|
||||
|
@ -482,6 +500,109 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleCardViewActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToolBar$Separator" name="jSeparator5">
|
||||
</Component>
|
||||
<Container class="javax.swing.JToolBar" name="tbRarities">
|
||||
<Properties>
|
||||
<Property name="floatable" type="boolean" value="false"/>
|
||||
<Property name="rollover" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Hold the ALT-key while clicking to deselect all other card rarities or hold the CTRL-key to only select all other card rarities."/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JToggleButton" name="tbCommon">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/rarity_common_20.png"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><strong>Common</strong><br/>" 
+ tbRarities.getToolTipText()" type="code"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" value="Common"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tbCommonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToggleButton" name="tbUncommon">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/rarity_uncommon_20.png"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><strong>Uncommon</strong><br/>" 
+ tbUncommon.getToolTipText()" type="code"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" value="Uncommon"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tbUncommonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToggleButton" name="tbRare">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/rarity_rare_20.png"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><strong>Rare</strong><br/>" 
+ tbRarities.getToolTipText()" type="code"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" value="Rare"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tbRareActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToggleButton" name="tbMythic">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/rarity_mythic_20.png"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><strong>Mythic</strong><br/>" 
+ tbRarities.getToolTipText()" type="code"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" value="Mythic"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tbMythicActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JToggleButton" name="tbSpecial">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/buttons/rarity_special_20.png"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code=""<html><strong>Special</strong><br/>" 
+ tbRarities.getToolTipText()" type="code"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" value="Special"/>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tbSpecialActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="cardSelectorScrollPane">
|
||||
|
|
|
@ -52,8 +52,10 @@ import mage.client.cards.*;
|
|||
import mage.client.constants.Constants.SortBy;
|
||||
import mage.client.deckeditor.table.TableModel;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
@ -64,6 +66,7 @@ import mage.filter.predicate.other.CardTextPredicate;
|
|||
import mage.filter.predicate.other.ExpansionSetPredicate;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CardsView;
|
||||
import org.mage.card.arcane.ManaSymbolsCellRenderer;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -133,6 +136,9 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
mainTable.getColumnModel().getColumn(6).setPreferredWidth(15);
|
||||
mainTable.getColumnModel().getColumn(7).setPreferredWidth(15);
|
||||
|
||||
// new mana render (svg support)
|
||||
mainTable.getColumnModel().getColumn(mainModel.COLUMN_INDEX_COST).setCellRenderer(new ManaSymbolsCellRenderer());
|
||||
|
||||
// mainTable.setToolTipText(cardSelectorScrollPane.getToolTipText());
|
||||
cardSelectorScrollPane.setViewportView(mainTable);
|
||||
mainTable.setOpaque(false);
|
||||
|
@ -202,6 +208,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
this.btnBooster.setVisible(false);
|
||||
this.btnClear.setVisible(false);
|
||||
this.cbExpansionSet.setVisible(false);
|
||||
this.btnExpansionSearch.setVisible(false);
|
||||
this.limited = true;
|
||||
this.cards.clear();
|
||||
for (Card card : sideboard) {
|
||||
|
@ -215,6 +222,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
this.btnBooster.setVisible(true);
|
||||
this.btnClear.setVisible(true);
|
||||
this.cbExpansionSet.setVisible(true);
|
||||
this.btnExpansionSearch.setVisible(true);
|
||||
// cbExpansionSet.setModel(new DefaultComboBoxModel<>(ConstructedFormats.getTypes()));
|
||||
// Action event on Expansion set triggers loadCards method
|
||||
cbExpansionSet.setSelectedIndex(0);
|
||||
|
@ -321,6 +329,24 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
// criteria.types(CardType.TRIBAL);
|
||||
// criteria.types(CardType.CONSPIRACY);
|
||||
|
||||
if (this.tbCommon.isSelected()) {
|
||||
criteria.rarities(Rarity.COMMON);
|
||||
criteria.rarities(Rarity.LAND);
|
||||
}
|
||||
if (this.tbUncommon.isSelected()) {
|
||||
criteria.rarities(Rarity.UNCOMMON);
|
||||
}
|
||||
if (this.tbRare.isSelected()) {
|
||||
criteria.rarities(Rarity.RARE);
|
||||
}
|
||||
if (this.tbMythic.isSelected()) {
|
||||
criteria.rarities(Rarity.MYTHIC);
|
||||
}
|
||||
if (this.tbSpecial.isSelected()) {
|
||||
criteria.rarities(Rarity.SPECIAL);
|
||||
criteria.rarities(Rarity.BONUS);
|
||||
}
|
||||
|
||||
if (this.cbExpansionSet.isVisible()) {
|
||||
String expansionSelection = this.cbExpansionSet.getSelectedItem().toString();
|
||||
if (!expansionSelection.equals("- All Sets")) {
|
||||
|
@ -369,6 +395,19 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
filterCards();
|
||||
}
|
||||
|
||||
private void filterCardsRarity(int modifiers, String actionCommand) {
|
||||
// ALT or CTRL button was pushed
|
||||
if ((modifiers & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK || (modifiers & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) {
|
||||
boolean invert = (modifiers & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK;
|
||||
tbCommon.setSelected(inverter(invert, tbCommon.getActionCommand(), actionCommand));
|
||||
tbUncommon.setSelected(inverter(invert, tbUncommon.getActionCommand(), actionCommand));
|
||||
tbRare.setSelected(inverter(invert, tbRare.getActionCommand(), actionCommand));
|
||||
tbMythic.setSelected(inverter(invert, tbMythic.getActionCommand(), actionCommand));
|
||||
tbSpecial.setSelected(inverter(invert, tbSpecial.getActionCommand(), actionCommand));
|
||||
}
|
||||
filterCards();
|
||||
}
|
||||
|
||||
private void filterCards() {
|
||||
FilterCard filter = buildFilter();
|
||||
try {
|
||||
|
@ -467,6 +506,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
tbColorless = new javax.swing.JToggleButton();
|
||||
jSeparator1 = new javax.swing.JToolBar.Separator();
|
||||
cbExpansionSet = new javax.swing.JComboBox<>();
|
||||
btnExpansionSearch = new javax.swing.JButton();
|
||||
jSeparator2 = new javax.swing.JToolBar.Separator();
|
||||
chkPennyDreadful = new javax.swing.JCheckBox();
|
||||
btnBooster = new javax.swing.JButton();
|
||||
|
@ -486,6 +526,13 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
jSeparator4 = new javax.swing.JToolBar.Separator();
|
||||
jToggleListView = new javax.swing.JToggleButton();
|
||||
jToggleCardView = new javax.swing.JToggleButton();
|
||||
jSeparator5 = new javax.swing.JToolBar.Separator();
|
||||
tbRarities = new javax.swing.JToolBar();
|
||||
tbCommon = new javax.swing.JToggleButton();
|
||||
tbUncommon = new javax.swing.JToggleButton();
|
||||
tbRare = new javax.swing.JToggleButton();
|
||||
tbMythic = new javax.swing.JToggleButton();
|
||||
tbSpecial = new javax.swing.JToggleButton();
|
||||
cardSelectorScrollPane = new javax.swing.JScrollPane();
|
||||
cardSelectorBottomPanel = new javax.swing.JPanel();
|
||||
jButtonAddToMain = new javax.swing.JButton();
|
||||
|
@ -611,10 +658,23 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
}
|
||||
});
|
||||
tbColor.add(cbExpansionSet);
|
||||
|
||||
btnExpansionSearch.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_32.png"))); // NOI18N
|
||||
btnExpansionSearch.setToolTipText("Fast search set or expansion");
|
||||
btnExpansionSearch.setAlignmentX(1.0F);
|
||||
btnExpansionSearch.setFocusable(false);
|
||||
btnExpansionSearch.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
btnExpansionSearch.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnExpansionSearch.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
btnExpansionSearch.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnExpansionSearchActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbColor.add(btnExpansionSearch);
|
||||
tbColor.add(jSeparator2);
|
||||
|
||||
|
||||
chkPennyDreadful.setText("Penny Dreadful");
|
||||
chkPennyDreadful.setText("Penny Dreadful Only");
|
||||
chkPennyDreadful.setToolTipText("Will only allow Penny Dreadful legal cards to be shown.");
|
||||
chkPennyDreadful.setFocusable(false);
|
||||
chkPennyDreadful.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
|
||||
|
@ -624,15 +684,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
chkPilesActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
JPopupMenu filterByFormatPopup = new JPopupMenu();
|
||||
filterByFormatPopup.add(chkPennyDreadful);
|
||||
filterByFormatPopup.setLayout(new GridBagLayout());
|
||||
|
||||
ButtonGroup selectByTypeModeGroup = new ButtonGroup();
|
||||
JButton filterByFormatButton = new JButton ("Filter by Format");
|
||||
makeButtonPopup(filterByFormatButton, filterByFormatPopup);
|
||||
tbColor.add(filterByFormatButton);
|
||||
tbColor.add(chkPennyDreadful);
|
||||
|
||||
btnBooster.setText("Open Booster");
|
||||
btnBooster.setToolTipText("(CURRENTLY NOT WORKING) Generates a booster of the selected set and adds the cards to the card selector.");
|
||||
|
@ -828,6 +880,88 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
}
|
||||
});
|
||||
tbTypes.add(jToggleCardView);
|
||||
tbTypes.add(jSeparator5);
|
||||
|
||||
tbRarities.setFloatable(false);
|
||||
tbRarities.setRollover(true);
|
||||
tbRarities.setToolTipText("Hold the ALT-key while clicking to deselect all other card rarities or hold the CTRL-key to only select all other card rarities.");
|
||||
|
||||
tbCommon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/rarity_common_20.png"))); // NOI18N
|
||||
tbCommon.setSelected(true);
|
||||
tbCommon.setToolTipText("<html><strong>Common</strong><br/>"
|
||||
+ tbRarities.getToolTipText());
|
||||
tbCommon.setActionCommand("Common");
|
||||
tbCommon.setFocusable(false);
|
||||
tbCommon.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tbCommon.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tbCommon.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tbCommonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbRarities.add(tbCommon);
|
||||
|
||||
tbUncommon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/rarity_uncommon_20.png"))); // NOI18N
|
||||
tbUncommon.setSelected(true);
|
||||
tbUncommon.setToolTipText("<html><strong>Uncommon</strong><br/>"
|
||||
+ tbUncommon.getToolTipText());
|
||||
tbUncommon.setActionCommand("Uncommon");
|
||||
tbUncommon.setFocusable(false);
|
||||
tbUncommon.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tbUncommon.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tbUncommon.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tbUncommonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbRarities.add(tbUncommon);
|
||||
|
||||
tbRare.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/rarity_rare_20.png"))); // NOI18N
|
||||
tbRare.setSelected(true);
|
||||
tbRare.setToolTipText("<html><strong>Rare</strong><br/>"
|
||||
+ tbRarities.getToolTipText());
|
||||
tbRare.setActionCommand("Rare");
|
||||
tbRare.setFocusable(false);
|
||||
tbRare.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tbRare.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tbRare.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tbRareActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbRarities.add(tbRare);
|
||||
|
||||
tbMythic.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/rarity_mythic_20.png"))); // NOI18N
|
||||
tbMythic.setSelected(true);
|
||||
tbMythic.setToolTipText("<html><strong>Mythic</strong><br/>"
|
||||
+ tbRarities.getToolTipText());
|
||||
tbMythic.setActionCommand("Mythic");
|
||||
tbMythic.setFocusable(false);
|
||||
tbMythic.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tbMythic.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tbMythic.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tbMythicActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbRarities.add(tbMythic);
|
||||
|
||||
tbSpecial.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/rarity_special_20.png"))); // NOI18N
|
||||
tbSpecial.setSelected(true);
|
||||
tbSpecial.setToolTipText("<html><strong>Special</strong><br/>"
|
||||
+ tbRarities.getToolTipText());
|
||||
tbSpecial.setActionCommand("Special");
|
||||
tbSpecial.setFocusable(false);
|
||||
tbSpecial.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tbSpecial.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tbSpecial.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tbSpecialActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
tbRarities.add(tbSpecial);
|
||||
|
||||
tbTypes.add(tbRarities);
|
||||
|
||||
cardSelectorScrollPane.setToolTipText("<HTML>Double click to add the card to the main deck.<br/>\nALT + Double click to add the card to the sideboard.");
|
||||
|
||||
|
@ -1207,6 +1341,30 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkRulesActionPerformed
|
||||
|
||||
private void btnExpansionSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExpansionSearchActionPerformed
|
||||
FastSearchUtil.showFastSearchForStringComboBox(cbExpansionSet, "Select set or expansion");
|
||||
}//GEN-LAST:event_btnExpansionSearchActionPerformed
|
||||
|
||||
private void tbCommonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbCommonActionPerformed
|
||||
filterCardsRarity(evt.getModifiers(), evt.getActionCommand());
|
||||
}//GEN-LAST:event_tbCommonActionPerformed
|
||||
|
||||
private void tbUncommonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbUncommonActionPerformed
|
||||
filterCardsRarity(evt.getModifiers(), evt.getActionCommand());
|
||||
}//GEN-LAST:event_tbUncommonActionPerformed
|
||||
|
||||
private void tbRareActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbRareActionPerformed
|
||||
filterCardsRarity(evt.getModifiers(), evt.getActionCommand());
|
||||
}//GEN-LAST:event_tbRareActionPerformed
|
||||
|
||||
private void tbMythicActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbMythicActionPerformed
|
||||
filterCardsRarity(evt.getModifiers(), evt.getActionCommand());
|
||||
}//GEN-LAST:event_tbMythicActionPerformed
|
||||
|
||||
private void tbSpecialActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tbSpecialActionPerformed
|
||||
filterCardsRarity(evt.getModifiers(), evt.getActionCommand());
|
||||
}//GEN-LAST:event_tbSpecialActionPerformed
|
||||
|
||||
private void toggleViewMode() {
|
||||
if (currentView instanceof CardGrid) {
|
||||
jToggleListView.setSelected(true);
|
||||
|
@ -1249,6 +1407,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
private javax.swing.ButtonGroup bgView;
|
||||
private javax.swing.JButton btnBooster;
|
||||
private javax.swing.JButton btnClear;
|
||||
private javax.swing.JButton btnExpansionSearch;
|
||||
private javax.swing.JLabel cardCount;
|
||||
private javax.swing.JLabel cardCountLabel;
|
||||
private javax.swing.JPanel cardSelectorBottomPanel;
|
||||
|
@ -1270,6 +1429,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
private javax.swing.JToolBar.Separator jSeparator2;
|
||||
private javax.swing.JToolBar.Separator jSeparator3;
|
||||
private javax.swing.JToolBar.Separator jSeparator4;
|
||||
private javax.swing.JToolBar.Separator jSeparator5;
|
||||
private javax.swing.JToolBar.Separator jSeparator6;
|
||||
private javax.swing.JTextField jTextFieldSearch;
|
||||
private javax.swing.JToggleButton jToggleCardView;
|
||||
|
@ -1279,15 +1439,21 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
private javax.swing.JToggleButton tbBlue;
|
||||
private javax.swing.JToolBar tbColor;
|
||||
private javax.swing.JToggleButton tbColorless;
|
||||
private javax.swing.JToggleButton tbCommon;
|
||||
private javax.swing.JToggleButton tbCreatures;
|
||||
private javax.swing.JToggleButton tbEnchantments;
|
||||
private javax.swing.JToggleButton tbGreen;
|
||||
private javax.swing.JToggleButton tbInstants;
|
||||
private javax.swing.JToggleButton tbLand;
|
||||
private javax.swing.JToggleButton tbMythic;
|
||||
private javax.swing.JToggleButton tbPlaneswalkers;
|
||||
private javax.swing.JToggleButton tbRare;
|
||||
private javax.swing.JToolBar tbRarities;
|
||||
private javax.swing.JToggleButton tbRed;
|
||||
private javax.swing.JToggleButton tbSorceries;
|
||||
private javax.swing.JToggleButton tbSpecial;
|
||||
private javax.swing.JToolBar tbTypes;
|
||||
private javax.swing.JToggleButton tbUncommon;
|
||||
private javax.swing.JToggleButton tbWhite;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
|
|
@ -691,8 +691,10 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
break;
|
||||
case 1:
|
||||
btnImportFromClipboardActionPerformed(evt);
|
||||
break;
|
||||
case 2:
|
||||
btnImportFromClipboardActionWAppendPerformed(evt);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -803,6 +805,14 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
.addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE));
|
||||
}
|
||||
|
||||
private void processAndShowImportErrors(StringBuilder errorMessages){
|
||||
// show up errors list
|
||||
if (errorMessages.length() > 0){
|
||||
String mes = "Founded problems with deck: \n\n" + errorMessages.toString();
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), mes.substring(0, Math.min(1000, mes.length())), "Errors while loading deck", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param evt ActionEvent
|
||||
*/
|
||||
|
@ -814,11 +824,23 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
dialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
Deck newDeck = null;
|
||||
StringBuilder errorMessages = new StringBuilder();
|
||||
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
deck = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath()), true, true);
|
||||
refreshDeck();
|
||||
newDeck = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true);
|
||||
processAndShowImportErrors(errorMessages);
|
||||
|
||||
if (newDeck != null) {
|
||||
deck = newDeck;
|
||||
refreshDeck();
|
||||
}
|
||||
|
||||
} catch (GameException e1) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
|
||||
}finally {
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -836,16 +858,22 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
Deck deckToAppend = null;
|
||||
StringBuilder errorMessages = new StringBuilder();
|
||||
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
deckToAppend = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath()), true, true);
|
||||
deckToAppend = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true);
|
||||
processAndShowImportErrors(errorMessages);
|
||||
|
||||
if (deckToAppend != null) {
|
||||
deck = Deck.append(deckToAppend, deck);
|
||||
refreshDeck();
|
||||
}
|
||||
} catch (GameException e1) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
|
||||
}finally {
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -875,20 +903,31 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
deck = Deck.load(DeckImporterUtil.importDeck(file.getPath()), true, true);
|
||||
Deck newDeck = null;
|
||||
StringBuilder errorMessages = new StringBuilder();
|
||||
|
||||
newDeck = Deck.load(DeckImporterUtil.importDeck(file.getPath(), errorMessages), true, true);
|
||||
processAndShowImportErrors(errorMessages);
|
||||
|
||||
if (newDeck != null) {
|
||||
deck = newDeck;
|
||||
refreshDeck(true);
|
||||
}
|
||||
|
||||
// save last deck history
|
||||
try {
|
||||
MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath());
|
||||
} catch (IOException ex) {
|
||||
logger.error("Error on save last load deck folder: " + ex.getMessage());
|
||||
}
|
||||
|
||||
} catch (GameException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
|
||||
} finally {
|
||||
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
refreshDeck(true);
|
||||
try {
|
||||
if (file != null) {
|
||||
MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}
|
||||
fcSelectDeck.setSelectedFile(null);
|
||||
|
@ -924,7 +963,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
if (!fileName.endsWith(".dck")) {
|
||||
fileName += ".dck";
|
||||
}
|
||||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
DeckCardLists cardLists = deck.getDeckCardLists();
|
||||
cardLists.setCardLayout(deckArea.getCardLayout());
|
||||
cardLists.setSideboardLayout(deckArea.getSideboardLayout());
|
||||
|
@ -932,7 +971,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
} catch (FileNotFoundException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage() + "\nTry ensuring that the selected directory is writable.", "Error saving deck", JOptionPane.ERROR_MESSAGE);
|
||||
} finally {
|
||||
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
try {
|
||||
MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath());
|
||||
|
@ -967,29 +1006,36 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
int ret = fcImportDeck.showOpenDialog(this);
|
||||
if (ret == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fcImportDeck.getSelectedFile();
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
DeckImporter importer = DeckImporterUtil.getDeckImporter(file.getPath());
|
||||
|
||||
if (importer != null) {
|
||||
deck = Deck.load(importer.importDeck(file.getPath()));
|
||||
String errors = importer.getErrors();
|
||||
if (!errors.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), errors, "Error importing deck", JOptionPane.ERROR_MESSAGE);
|
||||
StringBuilder errorMessages = new StringBuilder();
|
||||
Deck newDeck = null;
|
||||
|
||||
newDeck = Deck.load(importer.importDeck(file.getPath(), errorMessages));
|
||||
processAndShowImportErrors(errorMessages);
|
||||
|
||||
if (newDeck != null) {
|
||||
deck = newDeck;
|
||||
refreshDeck();
|
||||
}
|
||||
|
||||
// save last deck import folder
|
||||
try {
|
||||
MageFrame.getPreferences().put("lastImportFolder", file.getCanonicalPath());
|
||||
} catch (IOException ex) {
|
||||
logger.error("Error on save last used import folder: " + ex.getMessage());
|
||||
}
|
||||
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Unknown deck format", "Error importing deck", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.fatal(ex);
|
||||
} finally {
|
||||
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
refreshDeck();
|
||||
try {
|
||||
if (file != null) {
|
||||
MageFrame.getPreferences().put("lastImportFolder", file.getCanonicalPath());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}
|
||||
fcImportDeck.setSelectedFile(null);
|
||||
|
@ -1031,7 +1077,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
|
||||
private void btnGenDeckActionPerformed(ActionEvent evt) {
|
||||
try {
|
||||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
String path = DeckGenerator.generateDeck();
|
||||
deck = Deck.load(DeckImporterUtil.importDeck(path), true, true);
|
||||
} catch (GameException ex) {
|
||||
|
@ -1039,7 +1085,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
} catch (DeckGeneratorException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Generator error", JOptionPane.ERROR_MESSAGE);
|
||||
} finally {
|
||||
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
refreshDeck();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import mage.client.MageFrame;
|
|||
import mage.client.cards.BigCard;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -76,31 +77,56 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
}
|
||||
|
||||
public void initComponents() {
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
jPanel1.setOpaque(false);
|
||||
buttonsPanel = new javax.swing.JPanel();
|
||||
buttonsPanel.setOpaque(false);
|
||||
bigCard = new BigCard();
|
||||
BoxLayout boxlayout = new BoxLayout(jPanel1, BoxLayout.PAGE_AXIS);
|
||||
jPanel1.setLayout(boxlayout);
|
||||
BoxLayout boxlayout = new BoxLayout(buttonsPanel, BoxLayout.PAGE_AXIS);
|
||||
buttonsPanel.setLayout(boxlayout);
|
||||
btnExit = new javax.swing.JButton();
|
||||
btnExit.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
jPanel1.add(btnExit);
|
||||
buttonsPanel.add(btnExit);
|
||||
|
||||
JLabel label1 = new JLabel("Choose format:");
|
||||
label1.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label1.setForeground(Color.white);
|
||||
jPanel1.add(label1);
|
||||
buttonsPanel.add(label1);
|
||||
|
||||
// SELECT SET
|
||||
// panel
|
||||
setPanel = new JPanel();
|
||||
setPanel.setLayout(new javax.swing.BoxLayout(setPanel, javax.swing.BoxLayout.LINE_AXIS));
|
||||
setPanel.setOpaque(false);
|
||||
setPanel.setPreferredSize(new Dimension(200, 25));
|
||||
setPanel.setMaximumSize(new Dimension(200, 25));
|
||||
setPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
buttonsPanel.add(setPanel);
|
||||
// combo set
|
||||
formats = new JComboBox<>(ConstructedFormats.getTypes());
|
||||
formats.setSelectedItem(ConstructedFormats.getDefault());
|
||||
formats.setPreferredSize(new Dimension(250, 25));
|
||||
formats.setMaximumSize(new Dimension(250, 25));
|
||||
formats.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
jPanel1.add(formats);
|
||||
formats.setAlignmentX(0.0F);
|
||||
formats.setMinimumSize(new Dimension(50, 25));
|
||||
formats.setPreferredSize(new Dimension(50, 25));
|
||||
formats.setMaximumSize(new Dimension(Integer.MAX_VALUE, 25));
|
||||
setPanel.add(formats);
|
||||
// search button
|
||||
btnSetFastSearch = new JButton();
|
||||
btnSetFastSearch.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png")));
|
||||
btnSetFastSearch.setToolTipText(FastSearchUtil.DEFAULT_EXPANSION_TOOLTIP_MESSAGE);
|
||||
btnSetFastSearch.setAlignmentX(1.0F);
|
||||
btnSetFastSearch.setMinimumSize(new java.awt.Dimension(24, 24));
|
||||
btnSetFastSearch.setPreferredSize(new java.awt.Dimension(32, 32));
|
||||
btnSetFastSearch.setMaximumSize(new java.awt.Dimension(32, 32));
|
||||
btnSetFastSearch.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
FastSearchUtil.showFastSearchForStringComboBox(formats, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
|
||||
}
|
||||
});
|
||||
setPanel.add(btnSetFastSearch);
|
||||
|
||||
JLabel label2 = new JLabel("Choose size:");
|
||||
label2.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label2.setForeground(Color.white);
|
||||
jPanel1.add(label2);
|
||||
buttonsPanel.add(label2);
|
||||
|
||||
small3x3 = new JRadioButton("3x3");
|
||||
small3x3.setForeground(Color.white);
|
||||
|
@ -111,7 +137,7 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
mageBook.updateSize(MageBook.LAYOUT_3x3);
|
||||
MageFrame.getPreferences().put(LAYOYT_CONFIG_KEY, MageBook.LAYOUT_3x3);
|
||||
});
|
||||
jPanel1.add(small3x3);
|
||||
buttonsPanel.add(small3x3);
|
||||
|
||||
big4x4 = new JRadioButton("4x4");
|
||||
big4x4.setForeground(Color.white);
|
||||
|
@ -121,19 +147,19 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
mageBook.updateSize(MageBook.LAYOUT_4x4);
|
||||
MageFrame.getPreferences().put(LAYOYT_CONFIG_KEY, MageBook.LAYOUT_4x4);
|
||||
});
|
||||
jPanel1.add(big4x4);
|
||||
buttonsPanel.add(big4x4);
|
||||
|
||||
JLabel label3 = new JLabel("Switch tabs:");
|
||||
label3.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label3.setForeground(Color.white);
|
||||
jPanel1.add(label3);
|
||||
buttonsPanel.add(label3);
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setPreferredSize(new Dimension(200, 100));
|
||||
buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 100));
|
||||
buttonPanel.setOpaque(false);
|
||||
buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
jPanel1.add(buttonPanel);
|
||||
buttonsPanel.add(buttonPanel);
|
||||
|
||||
JButton prev = new JButton("Prev");
|
||||
prev.addActionListener(e -> mageBook.prev());
|
||||
|
@ -146,13 +172,13 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
JLabel label4 = new JLabel("Show cards or tokens:");
|
||||
label3.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label3.setForeground(Color.white);
|
||||
jPanel1.add(label4);
|
||||
buttonsPanel.add(label4);
|
||||
|
||||
JCheckBox cardsOrTokens = new JCheckBox("Display Cards");
|
||||
cardsOrTokens.setSelected(true);
|
||||
cardsOrTokens.setToolTipText("Select to show Cards or Tokens(and emblems) for the chosen set");
|
||||
cardsOrTokens.addActionListener(e -> mageBook.cardsOrTokens(cardsOrTokens.isSelected()));
|
||||
jPanel1.add(cardsOrTokens);
|
||||
buttonsPanel.add(cardsOrTokens);
|
||||
|
||||
formats.addActionListener(e -> {
|
||||
if (mageBook != null) {
|
||||
|
@ -162,12 +188,12 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
}
|
||||
});
|
||||
|
||||
jPanel1.add(Box.createVerticalGlue());
|
||||
buttonsPanel.add(Box.createVerticalGlue());
|
||||
|
||||
bigCard.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
|
||||
bigCard.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
bigCard.setAlignmentY(Component.BOTTOM_ALIGNMENT);
|
||||
jPanel1.add(bigCard);
|
||||
buttonsPanel.add(bigCard);
|
||||
|
||||
jPanel2 = new MageBookContainer();
|
||||
jPanel2.setOpaque(false);
|
||||
|
@ -177,13 +203,13 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(buttonsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 604, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(buttonsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
|
@ -241,8 +267,10 @@ public final class CollectionViewerPanel extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel buttonsPanel;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JPanel setPanel;
|
||||
private javax.swing.JButton btnSetFastSearch;
|
||||
private mage.client.cards.BigCard bigCard;
|
||||
private javax.swing.JButton btnExit;
|
||||
private JComboBox formats;
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
*/
|
||||
package mage.client.deckeditor.collection.viewer;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardDimensions;
|
||||
import mage.cards.MageCard;
|
||||
import mage.cards.*;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
|
@ -38,9 +36,7 @@ import mage.client.MageFrame;
|
|||
import mage.client.cards.BigCard;
|
||||
import mage.client.components.HoverButton;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.Config;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.NaturalOrderCardNumberComparator;
|
||||
import mage.client.util.*;
|
||||
import mage.client.util.audio.AudioManager;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.components.ImagePanel;
|
||||
|
@ -48,7 +44,6 @@ import mage.components.ImagePanelStyle;
|
|||
import mage.constants.Rarity;
|
||||
import mage.view.CardView;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.GlowText;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
@ -59,17 +54,17 @@ import java.io.FileNotFoundException;
|
|||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import mage.client.util.CardsViewUtil;
|
||||
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.view.EmblemView;
|
||||
import mage.view.PermanentView;
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static org.mage.plugins.card.images.DownloadPictures.getTokenCardUrls;
|
||||
|
||||
/**
|
||||
|
@ -115,6 +110,7 @@ public class MageBook extends JComponent {
|
|||
|
||||
Image image = ImageHelper.loadImage(LEFT_PAGE_BUTTON_IMAGE_PATH);
|
||||
pageLeft = new HoverButton(null, image, image, image, new Rectangle(64, 64));
|
||||
//pageLeft.setBorder(BorderFactory.createLineBorder(new Color(180, 50, 0), 3, true)); //debug
|
||||
pageLeft.setBounds(0, 0, 64, 64);
|
||||
pageLeft.setVisible(false);
|
||||
pageLeft.setObserver(() -> {
|
||||
|
@ -146,12 +142,46 @@ public class MageBook extends JComponent {
|
|||
add(jPanelCenter, BorderLayout.CENTER);
|
||||
add(jPanelRight, BorderLayout.LINE_END);
|
||||
|
||||
cardDimensions = new CardDimensions(0.45d);
|
||||
}
|
||||
int captionHeight = Math.max(30, pageLeft.getHeight()); // caption size = next-prev images
|
||||
|
||||
private void addLeftRightPageButtons() {
|
||||
jLayeredPane.add(pageLeft, JLayeredPane.DEFAULT_LAYER, 0);
|
||||
jLayeredPane.add(pageRight, JLayeredPane.DEFAULT_LAYER, 1);
|
||||
|
||||
// Top Panel (left page + (caption / stats) + right page
|
||||
jPanelTop = new JPanel();
|
||||
jPanelTop.setLayout(new BorderLayout());
|
||||
// jPanelTop.setBorder(BorderFactory.createLineBorder(new Color(180, 50, 150), 3, true)); // debug
|
||||
jPanelTop.setPreferredSize(new Dimension(captionHeight, captionHeight));
|
||||
jPanelCenter.add(jPanelTop, BorderLayout.NORTH);
|
||||
|
||||
// page left
|
||||
pageRight.setPreferredSize(new Dimension(pageRight.getWidth(), pageRight.getHeight()));
|
||||
jPanelTop.add(pageRight, BorderLayout.EAST);
|
||||
// page right
|
||||
pageLeft.setPreferredSize(new Dimension(pageLeft.getWidth(), pageLeft.getHeight()));
|
||||
jPanelTop.add(pageLeft, BorderLayout.WEST);
|
||||
|
||||
// Caption Panel
|
||||
jPanelCaption = new JPanel();
|
||||
jPanelCaption.setLayout(new BorderLayout());
|
||||
jPanelCaption.setOpaque(false);
|
||||
jPanelTop.add(jPanelCaption, BorderLayout.CENTER);
|
||||
|
||||
// set's caption
|
||||
setCaption = new JLabel();
|
||||
setCaption.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
//setCaption.setBorder(BorderFactory.createLineBorder(new Color(180, 50, 150), 3, true)); // debug
|
||||
setCaption.setFont(jLayeredPane.getFont().deriveFont(25f));
|
||||
setCaption.setText("EMPTY CAPTION");
|
||||
jPanelCaption.add(setCaption, BorderLayout.NORTH);
|
||||
|
||||
// set's info
|
||||
setInfo = new JLabel();
|
||||
setInfo.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
//setCaption.setBorder(BorderFactory.createLineBorder(new Color(180, 50, 150), 3, true)); // debug
|
||||
setInfo.setFont(jLayeredPane.getFont().deriveFont(17f));
|
||||
setInfo.setText("EMPTY STATS");
|
||||
jPanelCaption.add(setInfo, BorderLayout.SOUTH);
|
||||
|
||||
cardDimensions = new CardDimensions(0.45d);
|
||||
}
|
||||
|
||||
private void addSetTabs() {
|
||||
|
@ -174,7 +204,7 @@ public class MageBook extends JComponent {
|
|||
if (setImage != null) {
|
||||
tab.setOverlayImage(setImage);
|
||||
} else {
|
||||
System.out.println("Couldn't find: " + "/plugins/images/sets/" + set + "-C.jpg");
|
||||
System.out.println("Couldn't find symbol image: " + set + "-C.jpg");
|
||||
}
|
||||
tab.setSet(set);
|
||||
tab.setBounds(0, y, 39, 120);
|
||||
|
@ -217,8 +247,10 @@ public class MageBook extends JComponent {
|
|||
private void showCardsOrTokens() {
|
||||
stateChanged = false;
|
||||
if (showCardsOrTokens) {
|
||||
updateCardStats(currentSet, true);
|
||||
showCards();
|
||||
} else {
|
||||
updateCardStats(currentSet, false);
|
||||
int numTokens = showTokens();
|
||||
showEmblems(numTokens);
|
||||
}
|
||||
|
@ -226,16 +258,19 @@ public class MageBook extends JComponent {
|
|||
|
||||
public void showCards() {
|
||||
jLayeredPane.removeAll();
|
||||
addLeftRightPageButtons();
|
||||
|
||||
// stats info
|
||||
updateCardStats(currentSet, true);
|
||||
|
||||
List<CardInfo> cards = getCards(currentPage, currentSet);
|
||||
int size = cards.size();
|
||||
|
||||
Rectangle rectangle = new Rectangle();
|
||||
rectangle.translate(OFFSET_X, OFFSET_Y);
|
||||
for (int i = 0; i < Math.min(conf.CARDS_PER_PAGE / 2, size); i++) {
|
||||
for (int i = 0; i < min(conf.CARDS_PER_PAGE / 2, size); i++) {
|
||||
Card card = cards.get(i).getMockCard();
|
||||
addCard(new CardView(card), bigCard, null, rectangle);
|
||||
|
||||
rectangle = CardPosition.translatePosition(i, rectangle, conf);
|
||||
}
|
||||
|
||||
|
@ -244,7 +279,7 @@ public class MageBook extends JComponent {
|
|||
- (cardDimensions.frameWidth + CardPosition.GAP_X) * conf.CARD_COLUMNS + CardPosition.GAP_X - OFFSET_X;
|
||||
|
||||
rectangle.setLocation(second_page_x, OFFSET_Y);
|
||||
for (int i = conf.CARDS_PER_PAGE / 2; i < Math.min(conf.CARDS_PER_PAGE, size); i++) {
|
||||
for (int i = conf.CARDS_PER_PAGE / 2; i < min(conf.CARDS_PER_PAGE, size); i++) {
|
||||
Card card = cards.get(i).getMockCard();
|
||||
addCard(new CardView(card), bigCard, null, rectangle);
|
||||
rectangle = CardPosition.translatePosition(i - conf.CARDS_PER_PAGE / 2, rectangle, conf);
|
||||
|
@ -255,7 +290,6 @@ public class MageBook extends JComponent {
|
|||
|
||||
public int showTokens() {
|
||||
jLayeredPane.removeAll();
|
||||
addLeftRightPageButtons();
|
||||
|
||||
List<Token> tokens = getTokens(currentPage, currentSet);
|
||||
int size = tokens.size();
|
||||
|
@ -263,7 +297,7 @@ public class MageBook extends JComponent {
|
|||
if (tokens != null && tokens.size() > 0) {
|
||||
Rectangle rectangle = new Rectangle();
|
||||
rectangle.translate(OFFSET_X, OFFSET_Y);
|
||||
for (int i = 0; i < Math.min(conf.CARDS_PER_PAGE / 2, size); i++) {
|
||||
for (int i = 0; i < min(conf.CARDS_PER_PAGE / 2, size); i++) {
|
||||
Token token = tokens.get(i);
|
||||
addToken(token, bigCard, null, rectangle);
|
||||
rectangle = CardPosition.translatePosition(i, rectangle, conf);
|
||||
|
@ -274,7 +308,7 @@ public class MageBook extends JComponent {
|
|||
- (cardDimensions.frameWidth + CardPosition.GAP_X) * conf.CARD_COLUMNS + CardPosition.GAP_X - OFFSET_X;
|
||||
|
||||
rectangle.setLocation(second_page_x, OFFSET_Y);
|
||||
for (int i = conf.CARDS_PER_PAGE / 2; i < Math.min(conf.CARDS_PER_PAGE, size); i++) {
|
||||
for (int i = conf.CARDS_PER_PAGE / 2; i < min(conf.CARDS_PER_PAGE, size); i++) {
|
||||
Token token = tokens.get(i);
|
||||
addToken(token, bigCard, null, rectangle);
|
||||
rectangle = CardPosition.translatePosition(i - conf.CARDS_PER_PAGE / 2, rectangle, conf);
|
||||
|
@ -341,14 +375,30 @@ public class MageBook extends JComponent {
|
|||
cardImg.update(card);
|
||||
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimensions.frameWidth, cardDimensions.frameHeight);
|
||||
|
||||
cardImg.setCardCaptionTopOffset(8); // card caption below real card caption to see full name even with mana icons
|
||||
|
||||
boolean implemented = card.getRarity() != Rarity.NA;
|
||||
|
||||
// implemented label
|
||||
// old code, nowadays app load only implemented cards (JayDi85, 23.11.2017)
|
||||
/*
|
||||
GlowText label = new GlowText();
|
||||
label.setGlow(implemented ? Color.green : NOT_IMPLEMENTED, 12, 0.0f);
|
||||
label.setText(implemented ? "Implemented" : "Not implemented");
|
||||
int dx = implemented ? 15 : 5;
|
||||
label.setBounds(rectangle.x + dx, rectangle.y + cardDimensions.frameHeight + 7, 110, 30);
|
||||
jLayeredPane.add(label);
|
||||
*/
|
||||
|
||||
// card number label
|
||||
JLabel cardNumber = new JLabel();
|
||||
int dy = -5; // image panel have empty space in bottom (bug?), need to move label up
|
||||
cardNumber.setBounds(rectangle.x, rectangle.y + cardImg.getHeight() + dy, cardDimensions.frameWidth, 20);
|
||||
cardNumber.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
//cardNumber.setBorder(BorderFactory.createLineBorder(new Color(180, 50, 150), 3, true));
|
||||
cardNumber.setFont(jLayeredPane.getFont().deriveFont(jLayeredPane.getFont().getStyle() | Font.BOLD));
|
||||
cardNumber.setText(card.getCardNumber());
|
||||
jLayeredPane.add(cardNumber);
|
||||
}
|
||||
|
||||
private void addToken(Token token, BigCard bigCard, UUID gameId, Rectangle rectangle) {
|
||||
|
@ -386,6 +436,66 @@ public class MageBook extends JComponent {
|
|||
return cards.subList(start, end);
|
||||
}
|
||||
|
||||
private void updateCardStats(String setCode, boolean isCardsShow){
|
||||
// sets do not have total cards number, it's a workaround
|
||||
|
||||
ExpansionSet set = Sets.findSet(setCode);
|
||||
if (set != null){
|
||||
setCaption.setText(set.getCode() + " - " + set.getName());
|
||||
}else{
|
||||
setCaption.setText("ERROR");
|
||||
setInfo.setText("ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCardsShow){
|
||||
// tokens or emblems, stats not need
|
||||
setInfo.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
// cards stats
|
||||
|
||||
int startNumber = 9999;
|
||||
int endNumber = 0;
|
||||
|
||||
List<ExpansionSet.SetCardInfo> cards = set.getSetCardInfo();
|
||||
|
||||
// first run for numbers list
|
||||
LinkedList<Integer> haveNumbers = new LinkedList<>();
|
||||
for (ExpansionSet.SetCardInfo card: cards){
|
||||
int cardNumber = card.getCardNumberAsInt();
|
||||
|
||||
// skip xmage special numbers for cards (TODO: replace full art cards numbers from 180+20 to 180b, 180c and vice versa like scryfall)
|
||||
if(cardNumber > 500){
|
||||
continue;
|
||||
}
|
||||
|
||||
startNumber = min(startNumber, cardNumber);
|
||||
endNumber = Math.max(endNumber, cardNumber);
|
||||
haveNumbers.add(cardNumber);
|
||||
}
|
||||
|
||||
// second run for empty numbers
|
||||
int countHave = haveNumbers.size();
|
||||
int countNotHave = 0;
|
||||
if (cards.size() > 0){
|
||||
for(int i = startNumber; i <= endNumber; i++){
|
||||
if(!haveNumbers.contains(i)){
|
||||
countNotHave++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// result
|
||||
setInfo.setText(String.format("Have %d cards of %d", countHave, countHave + countNotHave));
|
||||
if (countNotHave > 0) {
|
||||
setInfo.setForeground(new Color(150, 0, 0));
|
||||
}else{
|
||||
setInfo.setForeground(jLayeredPane.getForeground());
|
||||
}
|
||||
}
|
||||
|
||||
private List<Token> getTokens(int page, String set) {
|
||||
ArrayList<CardDownloadData> allTokens = getTokenCardUrls();
|
||||
ArrayList<Token> tokens = new ArrayList<>();
|
||||
|
@ -573,7 +683,6 @@ public class MageBook extends JComponent {
|
|||
setSize(conf.WIDTH, conf.HEIGHT);
|
||||
setPreferredSize(new Dimension(conf.WIDTH, conf.HEIGHT));
|
||||
setMinimumSize(new Dimension(conf.WIDTH, conf.HEIGHT));
|
||||
pageRight.setBounds(conf.WIDTH - 2 * LEFT_RIGHT_PAGES_WIDTH - 64, 0, 64, 64);
|
||||
addSetTabs();
|
||||
showCards();
|
||||
}
|
||||
|
@ -613,7 +722,7 @@ public class MageBook extends JComponent {
|
|||
|
||||
_3x3Configuration() {
|
||||
this.WIDTH = 950;
|
||||
this.HEIGHT = 650;
|
||||
this.HEIGHT = 650 + 50; // + for caption
|
||||
CARD_ROWS = 3;
|
||||
CARD_COLUMNS = 3;
|
||||
this.CARDS_PER_PAGE = 18;
|
||||
|
@ -626,7 +735,7 @@ public class MageBook extends JComponent {
|
|||
|
||||
_4x4Configuration() {
|
||||
this.WIDTH = 1250;
|
||||
this.HEIGHT = 850;
|
||||
this.HEIGHT = 850 + 50; // + for caption
|
||||
CARD_ROWS = 4;
|
||||
CARD_COLUMNS = 4;
|
||||
this.CARDS_PER_PAGE = 32;
|
||||
|
@ -635,6 +744,10 @@ public class MageBook extends JComponent {
|
|||
}
|
||||
}
|
||||
|
||||
private JPanel jPanelTop;
|
||||
private JPanel jPanelCaption;
|
||||
private JLabel setCaption;
|
||||
private JLabel setInfo;
|
||||
private JPanel jPanelLeft;
|
||||
private ImagePanel jPanelCenter;
|
||||
private JPanel jPanelRight;
|
||||
|
@ -645,6 +758,8 @@ public class MageBook extends JComponent {
|
|||
|
||||
private int currentPage = 0;
|
||||
private String currentSet = "RTR";
|
||||
private int currentCardsInSet = 0;
|
||||
private int currentCardsNotInSet = 0;
|
||||
|
||||
private static CardDimensions cardDimensions = new CardDimensions(1.2d);
|
||||
private static final Logger log = Logger.getLogger(MageBook.class);
|
||||
|
|
|
@ -79,6 +79,7 @@ public class TableModel extends AbstractTableModel implements ICardGrid {
|
|||
private UpdateCountsCallback updateCountsCallback;
|
||||
|
||||
private final String column[] = {"Qty", "Name", "Cost", "Color", "Type", "Stats", "Rarity", "Set", "#"};
|
||||
public final int COLUMN_INDEX_COST = 2;
|
||||
|
||||
private SortSetting sortSetting;
|
||||
private int recentSortedColumn;
|
||||
|
@ -239,6 +240,10 @@ public class TableModel extends AbstractTableModel implements ICardGrid {
|
|||
case 1:
|
||||
return c.getName();
|
||||
case 2:
|
||||
// new svg images version
|
||||
return ManaSymbols.getStringManaCost(c.getManaCost());
|
||||
/*
|
||||
// old html images version
|
||||
String manaCost = "";
|
||||
for (String m : c.getManaCost()) {
|
||||
manaCost += m;
|
||||
|
@ -246,6 +251,8 @@ public class TableModel extends AbstractTableModel implements ICardGrid {
|
|||
String castingCost = UI.getDisplayManaCost(manaCost);
|
||||
castingCost = ManaSymbols.replaceSymbolsWithHTML(castingCost, ManaSymbols.Type.TABLE);
|
||||
return "<html>" + castingCost + "</html>";
|
||||
return castingCost;
|
||||
*/
|
||||
case 3:
|
||||
return c.getColorText();
|
||||
case 4:
|
||||
|
|
|
@ -85,9 +85,8 @@ public class AboutDialog extends MageDialog {
|
|||
|
||||
jLabel2.setText("Courtesy: BetaSteward@googlemail.com. Site: http://XMage.de/");
|
||||
|
||||
jLabel3.setText("Devs: BetaSteward, Noxx, Eugen.Rivniy, North, LevelX2, Jeff, Plopman, dustinconrad, emerald000.,");
|
||||
|
||||
jLabel4.setText("fireshoes, lunaskyrise, mnapoleon, jgod, LoneFox, drmDev, spjspj.");
|
||||
jLabel3.setText("Devs: BetaSteward, Noxx, Eugen.Rivniy, North, LevelX2, Jeff, Plopman, dustinconrad, emerald000,");
|
||||
jLabel4.setText("fireshoes, lunaskyrise, mnapoleon, jgod, LoneFox, drmDev, spjspj, L_J, JayDi85.");
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
|
|
|
@ -32,52 +32,39 @@
|
|||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblIsland" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblMountain" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblForest" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblLandSet" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="spnMountain" pref="85" max="32767" attributes="0"/>
|
||||
<Component id="spnIsland" max="32767" attributes="0"/>
|
||||
<Component id="spnForest" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="cbLandSet" min="-2" pref="207" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblSwamp" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Component id="spnSwamp" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblPains" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="spnPlains" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="122" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblMountain" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblForest" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblLandSet" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblIsland" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPains" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblSwamp" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="btnAutoAdd" pref="122" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnAdd" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="btnAutoAdd" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="btnAdd" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="spnMountain" alignment="0" pref="85" max="32767" attributes="0"/>
|
||||
<Component id="spnIsland" alignment="0" pref="85" max="32767" attributes="0"/>
|
||||
<Component id="spnForest" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="spnSwamp" alignment="0" pref="85" max="32767" attributes="0"/>
|
||||
<Component id="spnPlains" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="panelSet" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -85,9 +72,9 @@
|
|||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="cbLandSet" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblLandSet" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblLandSet" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="panelSet" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
|
@ -128,19 +115,7 @@
|
|||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="lblLandSet">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Set"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cbLandSet">
|
||||
<Properties>
|
||||
<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="text" type="java.lang.String" value="Set:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblForest">
|
||||
|
@ -227,5 +202,41 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAutoAddActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="panelSet">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JComboBox" name="cbLandSet">
|
||||
<Properties>
|
||||
<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="[20, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnSetFastSearch">
|
||||
<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="Search for set"/>
|
||||
<Property name="alignmentX" type="float" value="1.0"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[23, 23]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSetFastSearchActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
@ -44,6 +44,7 @@ import mage.cards.repository.ExpansionInfo;
|
|||
import mage.cards.repository.ExpansionRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.constants.Constants.DeckEditorMode;
|
||||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.constants.Rarity;
|
||||
import mage.util.RandomUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
@ -113,7 +114,14 @@ public class AddLandDialog extends MageDialog {
|
|||
}
|
||||
cbLandSet.setModel(new DefaultComboBoxModel(landSetNames.toArray()));
|
||||
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
|
||||
// windows settings
|
||||
if (this.isModal()){
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
|
||||
}else{
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
}
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
|
@ -157,7 +165,6 @@ public class AddLandDialog extends MageDialog {
|
|||
|
||||
jButton2 = new javax.swing.JButton();
|
||||
lblLandSet = new javax.swing.JLabel();
|
||||
cbLandSet = new javax.swing.JComboBox();
|
||||
lblForest = new javax.swing.JLabel();
|
||||
spnForest = new javax.swing.JSpinner();
|
||||
lblIsland = new javax.swing.JLabel();
|
||||
|
@ -171,14 +178,15 @@ public class AddLandDialog extends MageDialog {
|
|||
btnAdd = new javax.swing.JButton();
|
||||
btnCancel = new javax.swing.JButton();
|
||||
btnAutoAdd = new javax.swing.JButton();
|
||||
panelSet = new javax.swing.JPanel();
|
||||
cbLandSet = new javax.swing.JComboBox();
|
||||
btnSetFastSearch = new javax.swing.JButton();
|
||||
|
||||
jButton2.setText("jButton2");
|
||||
|
||||
setTitle("Add Land");
|
||||
|
||||
lblLandSet.setText("Set");
|
||||
|
||||
cbLandSet.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
lblLandSet.setText("Set:");
|
||||
|
||||
lblForest.setText("Forest");
|
||||
|
||||
|
@ -201,13 +209,42 @@ public class AddLandDialog extends MageDialog {
|
|||
spnSwamp.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
|
||||
|
||||
btnAdd.setText("Add");
|
||||
btnAdd.addActionListener(evt -> btnAddActionPerformed(evt));
|
||||
btnAdd.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnAddActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnCancel.setText("Cancel");
|
||||
btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt));
|
||||
btnCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnCancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnAutoAdd.setText("Suggest");
|
||||
btnAutoAdd.addActionListener(evt -> btnAutoAddActionPerformed(evt));
|
||||
btnAutoAdd.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnAutoAddActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
panelSet.setLayout(new javax.swing.BoxLayout(panelSet, javax.swing.BoxLayout.LINE_AXIS));
|
||||
|
||||
cbLandSet.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
cbLandSet.setMinimumSize(new java.awt.Dimension(20, 20));
|
||||
panelSet.add(cbLandSet);
|
||||
|
||||
btnSetFastSearch.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png"))); // NOI18N
|
||||
btnSetFastSearch.setToolTipText("Search for set");
|
||||
btnSetFastSearch.setAlignmentX(1.0F);
|
||||
btnSetFastSearch.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnSetFastSearch.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnSetFastSearchActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
panelSet.add(btnSetFastSearch);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
|
@ -216,48 +253,40 @@ public class AddLandDialog extends MageDialog {
|
|||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblIsland)
|
||||
.addComponent(lblMountain)
|
||||
.addComponent(lblForest)
|
||||
.addComponent(lblLandSet))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(spnMountain, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
|
||||
.addComponent(spnIsland)
|
||||
.addComponent(spnForest))
|
||||
.addComponent(cbLandSet, javax.swing.GroupLayout.PREFERRED_SIZE, 207, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(lblSwamp)
|
||||
.addGap(14, 14, 14)
|
||||
.addComponent(spnSwamp))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(lblPains)
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(spnPlains)))
|
||||
.addGap(122, 122, 122)))
|
||||
.addContainerGap())
|
||||
.addComponent(lblMountain)
|
||||
.addComponent(lblForest, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblLandSet, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblIsland, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblPains, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblSwamp, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnCancel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(btnAutoAdd)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(btnAutoAdd, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnAdd)
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(spnMountain, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
|
||||
.addComponent(spnIsland, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
|
||||
.addComponent(spnForest, javax.swing.GroupLayout.Alignment.LEADING))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(spnSwamp, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
|
||||
.addComponent(spnPlains, javax.swing.GroupLayout.Alignment.LEADING)))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(panelSet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cbLandSet, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblLandSet))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblLandSet)
|
||||
.addComponent(panelSet, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblForest)
|
||||
|
@ -312,6 +341,10 @@ public class AddLandDialog extends MageDialog {
|
|||
autoAddLands();
|
||||
}//GEN-LAST:event_btnAutoAddActionPerformed
|
||||
|
||||
private void btnSetFastSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetFastSearchActionPerformed
|
||||
FastSearchUtil.showFastSearchForStringComboBox(cbLandSet, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
|
||||
}//GEN-LAST:event_btnSetFastSearchActionPerformed
|
||||
|
||||
private void autoAddLands() {
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
|
@ -356,6 +389,7 @@ public class AddLandDialog extends MageDialog {
|
|||
private javax.swing.JButton btnAdd;
|
||||
private javax.swing.JButton btnAutoAdd;
|
||||
private javax.swing.JButton btnCancel;
|
||||
private javax.swing.JButton btnSetFastSearch;
|
||||
private javax.swing.JComboBox cbLandSet;
|
||||
private javax.swing.JButton jButton2;
|
||||
private javax.swing.JLabel lblForest;
|
||||
|
@ -364,6 +398,7 @@ public class AddLandDialog extends MageDialog {
|
|||
private javax.swing.JLabel lblMountain;
|
||||
private javax.swing.JLabel lblPains;
|
||||
private javax.swing.JLabel lblSwamp;
|
||||
private javax.swing.JPanel panelSet;
|
||||
private javax.swing.JSpinner spnForest;
|
||||
private javax.swing.JSpinner spnIsland;
|
||||
private javax.swing.JSpinner spnMountain;
|
||||
|
|
|
@ -26,68 +26,76 @@
|
|||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lblPort" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblServer" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblFlag" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblStatus" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="chkAutoConnect" alignment="0" pref="386" max="32767" attributes="0"/>
|
||||
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbFlag" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="txtServer" alignment="1" pref="286" max="32767" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="txtPort" min="-2" pref="71" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind1" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind3" min="-2" pref="42" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnFind2" min="-2" pref="42" max="-2" attributes="0"/>
|
||||
<EmptySpace min="69" pref="69" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||
<Component id="btnFind" pref="92" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblFlag" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="btnConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnForgotPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="btnConnect" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="btnRegister" max="32767" attributes="0"/>
|
||||
<Component id="btnForgotPassword" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" pref="77" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblStatus" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="chkAutoConnect" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="panelFlag" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="txtServer" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="txtPort" min="-2" pref="71" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="11" max="32767" attributes="0"/>
|
||||
<Component id="lblFastConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind1" min="-2" pref="70" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind3" min="-2" pref="70" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind2" min="-2" pref="40" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="btnFind" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblServer" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -101,39 +109,42 @@
|
|||
<Component id="btnFind1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnFind2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnFind3" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblFastConnect" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtPassword" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="lblFlag" max="32767" attributes="0"/>
|
||||
<Component id="cbFlag" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
<Component id="chkAutoConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="47" max="32767" attributes="0"/>
|
||||
<Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnConnect" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnForgotPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblUserName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="panelFlag" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="lblFlag" min="-2" pref="18" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="chkAutoConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="btnRegister" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnForgotPassword" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="btnConnect" max="32767" attributes="0"/>
|
||||
<Component id="btnCancel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -200,11 +211,6 @@
|
|||
<Property name="text" type="java.lang.String" value="User flag:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="mage.client.util.gui.countryBox.CountryComboBox" name="cbFlag">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkAutoConnect">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Automatically connect to this server next time"/>
|
||||
|
@ -233,7 +239,13 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnConnect">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Connect"/>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="11" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Connect to server"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnConnectActionPerformed"/>
|
||||
|
@ -242,6 +254,10 @@
|
|||
<Component class="javax.swing.JButton" name="btnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Cancel"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
|
||||
|
@ -251,8 +267,11 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnRegister">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Register new user"/>
|
||||
<Property name="text" type="java.lang.String" value="Register new user..."/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>XMage now supports user authentication.<br>Register your account before you log in.<html>"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRegisterActionPerformed"/>
|
||||
|
@ -260,8 +279,11 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnForgotPassword">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Forgot password"/>
|
||||
<Property name="text" type="java.lang.String" value="Forgot password..."/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>You can reset your password if you have registered<br>your account with an email address.</html>"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnForgotPasswordActionPerformed"/>
|
||||
|
@ -269,12 +291,16 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnFind1">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/flags/de.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="X"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de (Europe, most popular)"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value="connectXmageDe"/>
|
||||
<Property name="alignmentY" type="float" value="0.0"/>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[42, 23]"/>
|
||||
</Property>
|
||||
|
@ -293,11 +319,13 @@
|
|||
<Component class="javax.swing.JButton" name="btnFind2">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="L"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to localhost"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to localhost (local server)"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value="connectLocalhost"/>
|
||||
<Property name="alignmentY" type="float" value="0.0"/>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="connectLocalhostBtn" noResource="true"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[23, 23]"/>
|
||||
|
@ -309,12 +337,16 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnFind3">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/flags/us.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="W"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to woogerworks"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Connect to Woogerworks (USA)"/>
|
||||
<Property name="actionCommand" type="java.lang.String" value="connectWoogerworks"/>
|
||||
<Property name="alignmentY" type="float" value="0.0"/>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 2, 2, 2]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="connectWoogerworksBtn" noResource="true"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[23, 23]"/>
|
||||
|
@ -324,5 +356,69 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectWoogerworks"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblFastConnect">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="btnFind1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Fast connect to:"/>
|
||||
<Property name="name" type="java.lang.String" value="" noResource="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="panelFlag">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[189, 30]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="mage.client.util.gui.countryBox.CountryComboBox" name="cbFlag">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="maximumRowCount" type="int" value="16"/>
|
||||
<Property name="alignmentX" type="float" value="0.0"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[50, 18]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[278, 15]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</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="[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="[4, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalStrut"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnFlagSearch">
|
||||
<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="[23, 23]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFlagSearchActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
@ -51,14 +51,21 @@ import java.net.URL;
|
|||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingWorker;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.client.MageFrame;
|
||||
import static mage.client.dialog.PreferencesDialog.KEY_CONNECTION_URL_SERVER_LIST;
|
||||
import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_AUTO_CONNECT;
|
||||
|
@ -95,10 +102,10 @@ public class ConnectDialog extends MageDialog {
|
|||
this.txtPassword.addActionListener(connectAction);
|
||||
|
||||
registerUserDialog = new RegisterUserDialog(this);
|
||||
MageFrame.getDesktop().add(registerUserDialog, JLayeredPane.POPUP_LAYER);
|
||||
MageFrame.getDesktop().add(registerUserDialog, JLayeredPane.MODAL_LAYER);
|
||||
|
||||
resetPasswordDialog = new ResetPasswordDialog(this);
|
||||
MageFrame.getDesktop().add(resetPasswordDialog, JLayeredPane.POPUP_LAYER);
|
||||
MageFrame.getDesktop().add(resetPasswordDialog, JLayeredPane.MODAL_LAYER);
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
|
@ -152,7 +159,6 @@ public class ConnectDialog extends MageDialog {
|
|||
lblPassword = new javax.swing.JLabel();
|
||||
txtPassword = new javax.swing.JPasswordField();
|
||||
lblFlag = new javax.swing.JLabel();
|
||||
cbFlag = new mage.client.util.gui.countryBox.CountryComboBox();
|
||||
chkAutoConnect = new javax.swing.JCheckBox();
|
||||
chkForceUpdateDB = new javax.swing.JCheckBox();
|
||||
jProxySettingsButton = new javax.swing.JButton();
|
||||
|
@ -164,6 +170,11 @@ public class ConnectDialog extends MageDialog {
|
|||
btnFind1 = new javax.swing.JButton();
|
||||
btnFind2 = new javax.swing.JButton();
|
||||
btnFind3 = new javax.swing.JButton();
|
||||
lblFastConnect = new javax.swing.JLabel();
|
||||
panelFlag = new javax.swing.JPanel();
|
||||
cbFlag = new mage.client.util.gui.countryBox.CountryComboBox();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(4, 0), new java.awt.Dimension(5, 32767));
|
||||
btnFlagSearch = new javax.swing.JButton();
|
||||
|
||||
setTitle("Connect to server");
|
||||
setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307));
|
||||
|
@ -174,7 +185,11 @@ public class ConnectDialog extends MageDialog {
|
|||
btnFind.setText("Find...");
|
||||
btnFind.setToolTipText("Shows the list of public servers");
|
||||
btnFind.setName("findServerBtn"); // NOI18N
|
||||
btnFind.addActionListener(evt -> findPublicServerActionPerformed(evt));
|
||||
btnFind.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
findPublicServerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblPort.setLabelFor(txtPort);
|
||||
lblPort.setText("Port:");
|
||||
|
@ -194,119 +209,194 @@ public class ConnectDialog extends MageDialog {
|
|||
lblFlag.setLabelFor(txtUserName);
|
||||
lblFlag.setText("User flag:");
|
||||
|
||||
cbFlag.setEditable(true);
|
||||
|
||||
chkAutoConnect.setText("Automatically connect to this server next time");
|
||||
chkAutoConnect.setToolTipText("<HTML>If active this connect dialog will not be shown if you choose to connect.<br>\nInstead XMage tries to connect to the last server you were connected to.");
|
||||
chkAutoConnect.addActionListener(evt -> chkAutoConnectActionPerformed(evt));
|
||||
chkAutoConnect.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkAutoConnectActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
chkForceUpdateDB.setText("Force update of card database");
|
||||
chkForceUpdateDB.setToolTipText("<HTML>If active the comparison of the server cards database to the client database will be enforced.<br>If not, the comparison will only done if the database version of the client is lower than the version of the server.");
|
||||
chkForceUpdateDB.addActionListener(evt -> chkForceUpdateDBActionPerformed(evt));
|
||||
chkForceUpdateDB.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkForceUpdateDBActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jProxySettingsButton.setText("Proxy Settings...");
|
||||
jProxySettingsButton.addActionListener(evt -> jProxySettingsButtonActionPerformed(evt));
|
||||
jProxySettingsButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jProxySettingsButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnConnect.setText("Connect");
|
||||
btnConnect.addActionListener(evt -> btnConnectActionPerformed(evt));
|
||||
btnConnect.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
|
||||
btnConnect.setText("Connect to server");
|
||||
btnConnect.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnConnect.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnConnectActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnCancel.setText("Cancel");
|
||||
btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt));
|
||||
btnCancel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
btnCancel.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnCancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnRegister.setText("Register new user");
|
||||
btnRegister.setText("Register new user...");
|
||||
btnRegister.setToolTipText("<html>XMage now supports user authentication.<br>Register your account before you log in.<html>");
|
||||
btnRegister.addActionListener(evt -> btnRegisterActionPerformed(evt));
|
||||
btnRegister.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnRegister.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnRegisterActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnForgotPassword.setText("Forgot password");
|
||||
btnForgotPassword.setText("Forgot password...");
|
||||
btnForgotPassword.setToolTipText("<html>You can reset your password if you have registered<br>your account with an email address.</html>");
|
||||
btnForgotPassword.addActionListener(evt -> btnForgotPasswordActionPerformed(evt));
|
||||
btnForgotPassword.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnForgotPassword.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnForgotPasswordActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnFind1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N
|
||||
btnFind1.setText("X");
|
||||
btnFind1.setToolTipText("Connect to xmage.de");
|
||||
btnFind1.setToolTipText("Connect to xmage.de (Europe, most popular)");
|
||||
btnFind1.setActionCommand("connectXmageDe");
|
||||
btnFind1.setAlignmentY(0.0F);
|
||||
btnFind1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
btnFind1.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
btnFind1.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnFind1.setMaximumSize(new java.awt.Dimension(42, 23));
|
||||
btnFind1.setMinimumSize(new java.awt.Dimension(42, 23));
|
||||
btnFind1.setName("connectXmageDeBtn"); // NOI18N
|
||||
btnFind1.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnFind1.addActionListener(evt -> connectXmageDe(evt));
|
||||
btnFind1.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
connectXmageDe(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnFind2.setText("L");
|
||||
btnFind2.setToolTipText("Connect to localhost");
|
||||
btnFind2.setToolTipText("Connect to localhost (local server)");
|
||||
btnFind2.setActionCommand("connectLocalhost");
|
||||
btnFind2.setAlignmentY(0.0F);
|
||||
btnFind2.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
btnFind2.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
btnFind2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
btnFind2.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnFind2.setName("connectLocalhostBtn"); // NOI18N
|
||||
btnFind2.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnFind2.addActionListener(evt -> connectLocalhost(evt));
|
||||
btnFind2.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
connectLocalhost(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
|
||||
btnFind3.setText("W");
|
||||
btnFind3.setToolTipText("Connect to woogerworks");
|
||||
btnFind3.setToolTipText("Connect to Woogerworks (USA)");
|
||||
btnFind3.setActionCommand("connectWoogerworks");
|
||||
btnFind3.setAlignmentY(0.0F);
|
||||
btnFind3.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
btnFind3.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2));
|
||||
btnFind3.setName("connectWoogerworksBtn"); // NOI18N
|
||||
btnFind3.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnFind3.addActionListener(evt -> connectWoogerworks(evt));
|
||||
btnFind3.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
connectWoogerworks(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblFastConnect.setLabelFor(btnFind1);
|
||||
lblFastConnect.setText("Fast connect to:");
|
||||
lblFastConnect.setName(""); // NOI18N
|
||||
|
||||
panelFlag.setPreferredSize(new java.awt.Dimension(189, 30));
|
||||
panelFlag.setLayout(new javax.swing.BoxLayout(panelFlag, javax.swing.BoxLayout.LINE_AXIS));
|
||||
|
||||
cbFlag.setEditable(true);
|
||||
cbFlag.setMaximumRowCount(16);
|
||||
cbFlag.setAlignmentX(0.0F);
|
||||
cbFlag.setMinimumSize(new java.awt.Dimension(50, 18));
|
||||
cbFlag.setPreferredSize(new java.awt.Dimension(278, 15));
|
||||
panelFlag.add(cbFlag);
|
||||
panelFlag.add(filler1);
|
||||
|
||||
btnFlagSearch.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png"))); // NOI18N
|
||||
btnFlagSearch.setToolTipText("Fast search your flag");
|
||||
btnFlagSearch.setAlignmentX(1.0F);
|
||||
btnFlagSearch.setPreferredSize(new java.awt.Dimension(23, 23));
|
||||
btnFlagSearch.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnFlagSearchActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
panelFlag.add(btnFlagSearch);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(29, 29, 29)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblPort)
|
||||
.addComponent(lblServer)
|
||||
.addComponent(lblUserName)
|
||||
.addComponent(lblPassword))
|
||||
.addComponent(lblFlag, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblServer)))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblFlag)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 386, Short.MAX_VALUE)
|
||||
.addComponent(jProxySettingsButton)
|
||||
.addComponent(cbFlag, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(txtServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)
|
||||
.addComponent(txtUserName, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnFind1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(69, 69, 69)))
|
||||
.addGap(8, 8, 8)
|
||||
.addComponent(btnFind, javax.swing.GroupLayout.DEFAULT_SIZE, 92, Short.MAX_VALUE))))
|
||||
.addComponent(lblUserName)
|
||||
.addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING))))
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jProxySettingsButton)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(btnRegister)
|
||||
.addComponent(panelFlag, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(txtUserName, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnConnect)
|
||||
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
|
||||
.addComponent(lblFastConnect)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnForgotPassword)
|
||||
.addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel)))
|
||||
.addGap(26, 26, 26)))
|
||||
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(btnFind)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblServer)
|
||||
|
@ -318,35 +408,37 @@ public class ConnectDialog extends MageDialog {
|
|||
.addComponent(lblPort)
|
||||
.addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblFastConnect))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblUserName))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblPassword))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(cbFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(5, 5, 5)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(chkAutoConnect)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(chkForceUpdateDB)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jProxySettingsButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 47, Short.MAX_VALUE)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnConnect)
|
||||
.addComponent(btnCancel)
|
||||
.addComponent(btnForgotPassword))
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(btnRegister)
|
||||
.addContainerGap())
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(23, 23, 23))
|
||||
);
|
||||
|
||||
pack();
|
||||
|
@ -640,6 +732,45 @@ public class ConnectDialog extends MageDialog {
|
|||
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
|
||||
}//GEN-LAST:event_connectWoogerworks
|
||||
|
||||
private void btnFlagSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFlagSearchActionPerformed
|
||||
doFastFlagSearch();
|
||||
}//GEN-LAST:event_btnFlagSearchActionPerformed
|
||||
|
||||
private void doFastFlagSearch(){
|
||||
Choice choice = new ChoiceImpl(false);
|
||||
|
||||
// collect data from country combobox String[name][code]
|
||||
Map<String, String> choiceItems = new LinkedHashMap<>();
|
||||
DefaultComboBoxModel flagModel = (DefaultComboBoxModel)cbFlag.getModel();
|
||||
String[] flagItem;
|
||||
|
||||
for(int i = 0; i < flagModel.getSize(); i++){
|
||||
flagItem = (String[])flagModel.getElementAt(i);
|
||||
choiceItems.put(flagItem[1], flagItem[0]);
|
||||
}
|
||||
|
||||
choice.setKeyChoices(choiceItems);
|
||||
choice.setMessage("Select your country");
|
||||
|
||||
// current selection value restore
|
||||
String needSelectValue = null;
|
||||
flagItem = (String[])flagModel.getSelectedItem();
|
||||
if (flagItem != null){
|
||||
needSelectValue = flagItem[1];
|
||||
}
|
||||
|
||||
// ask for new value
|
||||
PickChoiceDialog dlg = new PickChoiceDialog();
|
||||
dlg.setWindowSize(300, 500);
|
||||
dlg.showDialog(choice, needSelectValue);
|
||||
if(choice.isChosen()){
|
||||
flagItem = new String[2];
|
||||
flagItem[0] = choice.getChoiceValue();
|
||||
flagItem[1] = choice.getChoiceKey();
|
||||
flagModel.setSelectedItem(flagItem);
|
||||
}
|
||||
}
|
||||
|
||||
public String getServer() {
|
||||
return this.txtServer.getText();
|
||||
}
|
||||
|
@ -655,18 +786,22 @@ public class ConnectDialog extends MageDialog {
|
|||
private javax.swing.JButton btnFind1;
|
||||
private javax.swing.JButton btnFind2;
|
||||
private javax.swing.JButton btnFind3;
|
||||
private javax.swing.JButton btnFlagSearch;
|
||||
private javax.swing.JButton btnForgotPassword;
|
||||
private javax.swing.JButton btnRegister;
|
||||
private mage.client.util.gui.countryBox.CountryComboBox cbFlag;
|
||||
private javax.swing.JCheckBox chkAutoConnect;
|
||||
private javax.swing.JCheckBox chkForceUpdateDB;
|
||||
private javax.swing.Box.Filler filler1;
|
||||
private javax.swing.JButton jProxySettingsButton;
|
||||
private javax.swing.JLabel lblFastConnect;
|
||||
private javax.swing.JLabel lblFlag;
|
||||
private javax.swing.JLabel lblPassword;
|
||||
private javax.swing.JLabel lblPort;
|
||||
private javax.swing.JLabel lblServer;
|
||||
private javax.swing.JLabel lblStatus;
|
||||
private javax.swing.JLabel lblUserName;
|
||||
private javax.swing.JPanel panelFlag;
|
||||
private javax.swing.JPasswordField txtPassword;
|
||||
private javax.swing.JTextField txtPort;
|
||||
private javax.swing.JTextField txtServer;
|
||||
|
|
|
@ -45,8 +45,8 @@ import java.awt.event.MouseEvent;
|
|||
import java.beans.PropertyVetoException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.*;
|
||||
|
||||
import mage.client.MageFrame;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -74,11 +74,34 @@ public class MageDialog extends javax.swing.JInternalFrame {
|
|||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
this.toFront();
|
||||
|
||||
// frames desktop ordering
|
||||
// more info https://docs.oracle.com/javase/7/docs/api/javax/swing/JLayeredPane.html
|
||||
// WARNING, use
|
||||
// - JLayeredPane.DEFAULT_LAYER: tables and games (tabs)
|
||||
// - JLayeredPane.PALETTE_LAYER: toolbars and info windows like cards list, not modal dialogs (not required user actions)
|
||||
// - JLayeredPane.MODAL_LAYER: all modal dialogs (user required actions - select cards in game, new game window, error windows)
|
||||
// - JLayeredPane.POPUP_LAYER: hints and other top level graphics
|
||||
// - JLayeredPane.DRAG_LAYER: top most layer for critical actions and user controls
|
||||
/*
|
||||
JInternalFrame[] frames = MageFrame.getDesktop().getAllFrames();
|
||||
System.out.println("---");
|
||||
for(JInternalFrame frame: frames){
|
||||
int zorder = -1;
|
||||
if (frame.getParent() != null){
|
||||
frame.getParent().getComponentZOrder(frame);
|
||||
}
|
||||
System.out.println(frame.getClass() + " (" + frame.getTitle() + ") : layer = " + frame.getLayer() + ", zorder = " + zorder);
|
||||
}
|
||||
*/
|
||||
|
||||
if (modal) {
|
||||
this.setClosable(false);
|
||||
}
|
||||
if (this.modal) {
|
||||
|
||||
this.toFront();
|
||||
|
||||
if (modal){
|
||||
startModal();
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +131,6 @@ public class MageDialog extends javax.swing.JInternalFrame {
|
|||
}
|
||||
|
||||
private synchronized void startModal() {
|
||||
|
||||
try {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
EventQueue theQueue = getToolkit().getSystemEventQueue();
|
||||
|
|
|
@ -47,6 +47,7 @@ import mage.cards.repository.ExpansionRepository;
|
|||
import mage.client.MageFrame;
|
||||
import mage.client.SessionHandler;
|
||||
import mage.client.table.TournamentPlayerPanel;
|
||||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.constants.MatchTimeLimit;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
|
@ -76,7 +77,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
private RandomPacksSelectorDialog randomPackSelector;
|
||||
private JTextArea txtRandomPacks;
|
||||
private final List<TournamentPlayerPanel> players = new ArrayList<>();
|
||||
private final List<JComboBox> packs = new ArrayList<>();
|
||||
private final List<JPanel> packPanels = new ArrayList<>();
|
||||
private static final int CONSTRUCTION_TIME_MIN = 6;
|
||||
private static final int CONSTRUCTION_TIME_MAX = 30;
|
||||
private boolean isRandom = false;
|
||||
|
@ -586,8 +587,13 @@ public class NewTournamentDialog extends MageDialog {
|
|||
tOptions.getLimitedOptions().getSetCodes().addAll(selected);
|
||||
}
|
||||
} else {
|
||||
for (JComboBox pack : packs) {
|
||||
tOptions.getLimitedOptions().getSetCodes().add(((ExpansionInfo) pack.getSelectedItem()).getCode());
|
||||
for (JPanel panel : packPanels) {
|
||||
JComboBox combo = findComboInComponent(panel);
|
||||
if(combo != null) {
|
||||
tOptions.getLimitedOptions().getSetCodes().add(((ExpansionInfo) combo.getSelectedItem()).getCode());
|
||||
}else{
|
||||
logger.error("Can't find combo component in " + panel.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
tOptions.getMatchOptions().setDeckType("Limited");
|
||||
|
@ -884,35 +890,89 @@ public class NewTournamentDialog extends MageDialog {
|
|||
}
|
||||
|
||||
private void createPacks(int numPacks) {
|
||||
while (packs.size() > numPacks) {
|
||||
pnlPacks.remove(packs.get(packs.size() - 1));
|
||||
packs.remove(packs.size() - 1);
|
||||
while (packPanels.size() > numPacks) {
|
||||
pnlPacks.remove(packPanels.get(packPanels.size() - 1));
|
||||
packPanels.remove(packPanels.size() - 1);
|
||||
}
|
||||
while (packs.size() < numPacks) {
|
||||
while (packPanels.size() < numPacks) {
|
||||
// SELECT PACK
|
||||
// panel
|
||||
JPanel setPanel = new JPanel();
|
||||
setPanel.setLayout(new javax.swing.BoxLayout(setPanel, javax.swing.BoxLayout.LINE_AXIS));
|
||||
setPanel.setOpaque(false);
|
||||
//setPanel.setPreferredSize(new Dimension(200, 25));
|
||||
//setPanel.setMaximumSize(new Dimension(200, 25));
|
||||
pnlPacks.add(setPanel);
|
||||
packPanels.add(setPanel); // for later access
|
||||
// combo set
|
||||
JComboBox pack = new JComboBox();
|
||||
pack = new JComboBox();
|
||||
pack.setModel(new DefaultComboBoxModel(ExpansionRepository.instance.getWithBoostersSortedByReleaseDate()));
|
||||
pnlPacks.add(pack);
|
||||
packs.add(pack);
|
||||
pack.addActionListener(evt -> packActionPerformed(evt));
|
||||
pack.setAlignmentX(0.0F);
|
||||
pack.setMinimumSize(new Dimension(50, 25));
|
||||
pack.setPreferredSize(new Dimension(50, 25));
|
||||
pack.setMaximumSize(new Dimension(Integer.MAX_VALUE, 25));
|
||||
setPanel.add(pack);
|
||||
// search button
|
||||
JButton searchButton = new JButton();
|
||||
searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png")));
|
||||
searchButton.setToolTipText("Search and select from list");
|
||||
searchButton.setAlignmentX(1.0F);
|
||||
searchButton.setMinimumSize(new java.awt.Dimension(24, 24));
|
||||
searchButton.setPreferredSize(new java.awt.Dimension(32, 32));
|
||||
searchButton.setMaximumSize(new java.awt.Dimension(32, 32));
|
||||
searchButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
||||
// search combo box near button (must be only one combo in panel)
|
||||
JButton button = (JButton)evt.getSource();
|
||||
JComboBox combo = findComboInComponent(button.getParent());
|
||||
|
||||
if (combo != null) {
|
||||
FastSearchUtil.showFastSearchForStringComboBox(combo, "Select value");
|
||||
}
|
||||
}
|
||||
});
|
||||
setPanel.add(searchButton);
|
||||
}
|
||||
this.pack();
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
private void packActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
boolean start = false;
|
||||
int selectedIndex = 0;
|
||||
for (JComboBox pack : packs) {
|
||||
if (!start) {
|
||||
if (evt.getSource().equals(pack)) {
|
||||
start = true;
|
||||
selectedIndex = pack.getSelectedIndex();
|
||||
}
|
||||
} else {
|
||||
pack.setSelectedIndex(selectedIndex);
|
||||
private JComboBox findComboInComponent(Container panel){
|
||||
// search combo box near button (must be only one combo in panel)
|
||||
JComboBox combo = null;
|
||||
for(Component comp: panel.getComponents()){
|
||||
if (comp instanceof JComboBox){
|
||||
combo = (JComboBox)comp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return combo;
|
||||
}
|
||||
|
||||
private void packActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
// fill all bottom combobox with same value
|
||||
JComboBox curentCombo = (JComboBox)evt.getSource();
|
||||
int newValue = curentCombo.getSelectedIndex();
|
||||
|
||||
// search start index
|
||||
int startIndex = 0;
|
||||
for(int i = 0; i < packPanels.size(); i++){
|
||||
JComboBox pack = findComboInComponent(packPanels.get(i));
|
||||
if (pack.equals(curentCombo)){
|
||||
startIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// change all from start index
|
||||
for(int i = startIndex; i < packPanels.size(); i++){
|
||||
JComboBox pack = findComboInComponent(packPanels.get(i));
|
||||
pack.setSelectedIndex(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void createPlayers(int numPlayers) {
|
||||
|
@ -1054,16 +1114,22 @@ public class NewTournamentDialog extends MageDialog {
|
|||
int packNumber = 0;
|
||||
for (String pack : packsArray) {
|
||||
packNumber++;
|
||||
if (this.packs.size() >= packNumber - 1) {
|
||||
JComboBox comboBox = this.packs.get(packNumber - 1);
|
||||
ComboBoxModel model = comboBox.getModel();
|
||||
int size = model.getSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
ExpansionInfo element = (ExpansionInfo) model.getElementAt(i);
|
||||
if (element.getCode().equals(pack.trim())) {
|
||||
comboBox.setSelectedIndex(i);
|
||||
break;
|
||||
if (this.packPanels.size() >= packNumber - 1) {
|
||||
JPanel panel = packPanels.get(packNumber - 1);
|
||||
JComboBox comboBox = findComboInComponent(panel);
|
||||
|
||||
if (comboBox != null) {
|
||||
ComboBoxModel model = comboBox.getModel();
|
||||
int size = model.getSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
ExpansionInfo element = (ExpansionInfo) model.getElementAt(i);
|
||||
if (element.getCode().equals(pack.trim())) {
|
||||
comboBox.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
logger.error("Can't find combo component in " + panel.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="resizable" type="boolean" value="true"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[280, 200]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="" noResource="true"/>
|
||||
</Properties>
|
||||
<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
</SyntheticProperties>
|
||||
|
@ -26,19 +19,13 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="0" pref="335" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnAutoSelect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnOk" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblMessage" alignment="0" pref="335" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="scrollList" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="panelCommands" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="panelHeader" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="panelSearch" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -47,74 +34,173 @@
|
|||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="lblMessage" min="-2" pref="37" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="panelHeader" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="158" max="32767" attributes="0"/>
|
||||
<Component id="panelSearch" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnOk" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnAutoSelect" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="scrollList" pref="246" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="panelCommands" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="btnAutoSelect">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Auto select"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="If you select an effect with "Auto select", this effect will be selected the next time automatically first."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAutoSelectActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Cancel"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnOk">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="OK"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOkActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
<Container class="javax.swing.JPanel" name="panelHeader">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="labelMessage" alignment="1" pref="210" max="32767" attributes="0"/>
|
||||
<Component id="labelSubMessage" alignment="1" pref="210" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="labelMessage" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="labelSubMessage" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="lstChoices">
|
||||
<Component class="javax.swing.JLabel" name="labelMessage">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="5">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
<StringItem index="4" value="Item 5"/>
|
||||
</StringArray>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="<html><div style='text-align: center;'>example long message example long message example long message example long message example long message</div></html>"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="labelSubMessage">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="labelSubMessage" italic="true" property="font" relativeSize="true" size="0"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="<html><div style='text-align: center;'>example long message example long</div></html>"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="lblMessage">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="message"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="panelSearch">
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="labelSearch" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="editSearch" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="labelSearch" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="editSearch" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="labelSearch">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Search:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="editSearch">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="sample search text"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="scrollList">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="listChoices">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="3">
|
||||
<StringItem index="0" value="item1"/>
|
||||
<StringItem index="1" value="item2"/>
|
||||
<StringItem index="2" value="item3"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value=""/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="panelCommands">
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="btOK" linkSize="3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btCancel" linkSize="3" min="-2" pref="70" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btOK" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="btOK">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Choose"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btOKActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_AddingCodePost" type="java.lang.String" value="getRootPane().setDefaultButton(btOK);"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Cancel"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btCancelActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
@ -1,43 +1,28 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PickNumberDialog.java
|
||||
*
|
||||
* Created on Feb 25, 2010, 12:03:39 PM
|
||||
* 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;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
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.client.MageFrame;
|
||||
import mage.client.util.SettingsManager;
|
||||
|
@ -46,38 +31,145 @@ import mage.client.util.gui.MageDialogState;
|
|||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author JayDi85
|
||||
*/
|
||||
|
||||
public class PickChoiceDialog extends MageDialog {
|
||||
|
||||
/** Creates new form PickNumberDialog */
|
||||
public PickChoiceDialog() {
|
||||
initComponents();
|
||||
this.setModal(true);
|
||||
}
|
||||
Choice choice;
|
||||
boolean autoSelect;
|
||||
ArrayList<KeyValueItem> allItems = new ArrayList<>();
|
||||
DefaultListModel<KeyValueItem> dataModel = new DefaultListModel();
|
||||
|
||||
final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
|
||||
|
||||
public void showDialog(Choice choice) {
|
||||
showDialog(choice, null, null, null);
|
||||
}
|
||||
|
||||
public void showDialog(Choice choice, String startSelectionValue) {
|
||||
showDialog(choice, null, null, startSelectionValue);
|
||||
}
|
||||
|
||||
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState) {
|
||||
this.lblMessage.setText("<html>" + choice.getMessage());
|
||||
showDialog(choice, objectId, mageDialogState, null);
|
||||
}
|
||||
|
||||
public void showDialog(Choice choice, UUID objectId, MageDialogState mageDialogState, String startSelectionValue) {
|
||||
this.choice = choice;
|
||||
this.autoSelect = false;
|
||||
btnAutoSelect.setVisible(choice.isKeyChoice());
|
||||
|
||||
if (choice.isKeyChoice()){
|
||||
|
||||
ComboItem[] comboItems = new ComboItem[choice.getKeyChoices().size()];
|
||||
int count = 0;
|
||||
for (Map.Entry<String, String> entry : choice.getKeyChoices().entrySet()) {
|
||||
comboItems[count] = new ComboItem(entry.getKey(), entry.getValue());
|
||||
count++;
|
||||
setLabelText(this.labelMessage, choice.getMessage());
|
||||
setLabelText(this.labelSubMessage, choice.getSubMessage());
|
||||
|
||||
btCancel.setEnabled(!choice.isRequired());
|
||||
|
||||
// 2 modes: string or key-values
|
||||
// sore data in allItems for inremental filtering
|
||||
// http://logicbig.com/tutorials/core-java-tutorial/swing/list-filter/
|
||||
this.allItems.clear();
|
||||
if (choice.isKeyChoice()){
|
||||
for (Map.Entry<String, String> entry: choice.getKeyChoices().entrySet()) {
|
||||
this.allItems.add(new KeyValueItem(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
this.lstChoices.setListData(comboItems);
|
||||
} else {
|
||||
this.lstChoices.setListData(choice.getChoices().toArray());
|
||||
for (String value: choice.getChoices()){
|
||||
this.allItems.add(new KeyValueItem(value, value));
|
||||
}
|
||||
}
|
||||
|
||||
// sorting
|
||||
if(choice.isSortEnabled()){
|
||||
Collections.sort(this.allItems, new Comparator<KeyValueItem>() {
|
||||
@Override
|
||||
public int compare(KeyValueItem o1, KeyValueItem o2) {
|
||||
Integer n1 = choice.getSortData().get(o1.Key);
|
||||
Integer n2 = choice.getSortData().get(o2.Key);
|
||||
return n1.compareTo(n2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
// search
|
||||
if(choice.isSearchEnabled())
|
||||
{
|
||||
panelSearch.setVisible(true);
|
||||
this.editSearch.setText(choice.getSearchText());
|
||||
}else{
|
||||
panelSearch.setVisible(false);
|
||||
this.editSearch.setText("");
|
||||
}
|
||||
|
||||
// listeners for inremental filtering
|
||||
editSearch.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
choice.setSearchText(editSearch.getText());
|
||||
loadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
choice.setSearchText(editSearch.getText());
|
||||
loadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
choice.setSearchText(editSearch.getText());
|
||||
loadData();
|
||||
}
|
||||
});
|
||||
|
||||
// listeners for select up and down without edit focus lost
|
||||
editSearch.addKeyListener(new KeyListener() {
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
//System.out.println("types");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_UP){
|
||||
doPrevSelect();
|
||||
}else if(e.getKeyCode() == KeyEvent.VK_DOWN){
|
||||
doNextSelect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
//System.out.println("released");
|
||||
}
|
||||
});
|
||||
|
||||
// listeners double click choose
|
||||
listChoices.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if(e.getClickCount() == 2){
|
||||
doChoose();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// listeners for ESC close
|
||||
if(!choice.isRequired()){
|
||||
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) {
|
||||
doCancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -86,155 +178,317 @@ public class PickChoiceDialog extends MageDialog {
|
|||
this.setLocation(centered.x, centered.y);
|
||||
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
|
||||
}
|
||||
|
||||
|
||||
// final load
|
||||
loadData();
|
||||
|
||||
// start selection
|
||||
if((startSelectionValue != null)){
|
||||
int selectIndex = -1;
|
||||
for(int i = 0; i < this.listChoices.getModel().getSize(); i++){
|
||||
KeyValueItem listItem = (KeyValueItem)this.listChoices.getModel().getElementAt(i);
|
||||
if (listItem.Key.equals(startSelectionValue)){
|
||||
selectIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(selectIndex >= 0){
|
||||
this.listChoices.setSelectedIndex(selectIndex);
|
||||
this.listChoices.ensureIndexIsVisible(selectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public boolean isAutoSelect() {
|
||||
return autoSelect;
|
||||
|
||||
public void setWindowSize(int width, int heigth){
|
||||
this.setSize(new Dimension(width, heigth));
|
||||
}
|
||||
|
||||
private void loadData(){
|
||||
// load data to datamodel after filter or on startup
|
||||
String filter = choice.getSearchText();
|
||||
if (filter == null){ filter = ""; }
|
||||
filter = filter.toLowerCase();
|
||||
|
||||
this.dataModel.clear();
|
||||
for(KeyValueItem item: this.allItems){
|
||||
if(!choice.isSearchEnabled() || item.Value.toLowerCase().contains(filter)){
|
||||
this.dataModel.addElement(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setLabelText(JLabel label, String text){
|
||||
if ((text != null) && !text.equals("")){
|
||||
label.setText(String.format(HTML_TEMPLATE, text));
|
||||
label.setVisible(true);
|
||||
}else{
|
||||
label.setText("");
|
||||
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(){
|
||||
int newSel = this.listChoices.getSelectedIndex() - 1;
|
||||
if(newSel >= 0){
|
||||
this.listChoices.setSelectedIndex(newSel);
|
||||
this.listChoices.ensureIndexIsVisible(newSel);
|
||||
}
|
||||
}
|
||||
|
||||
public void setChoice() {
|
||||
if (this.lstChoices.getSelectedValue() == null) {
|
||||
choice.clearChoice();
|
||||
private void doChoose(){
|
||||
if(setChoice()){
|
||||
this.hideDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void doCancel(){
|
||||
this.listChoices.clearSelection();
|
||||
this.choice.clearChoice();
|
||||
hideDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form PickChoiceDialog
|
||||
*/
|
||||
public PickChoiceDialog() {
|
||||
initComponents();
|
||||
this.listChoices.setModel(dataModel);
|
||||
this.setModal(true);
|
||||
}
|
||||
|
||||
public boolean setChoice() {
|
||||
KeyValueItem item = (KeyValueItem)this.listChoices.getSelectedValue();
|
||||
|
||||
// auto select one item (after incemental filtering)
|
||||
if((item == null) && (this.listChoices.getModel().getSize() == 1)){
|
||||
this.listChoices.setSelectedIndex(0);
|
||||
item = (KeyValueItem)this.listChoices.getSelectedValue();
|
||||
}
|
||||
|
||||
if (choice.isKeyChoice()) {
|
||||
ComboItem item = (ComboItem)this.lstChoices.getSelectedValue();
|
||||
if (item != null) {
|
||||
choice.setChoiceByKey(item.getValue());
|
||||
} else {
|
||||
choice.clearChoice();
|
||||
if(item != null){
|
||||
if(choice.isKeyChoice()){
|
||||
choice.setChoiceByKey(item.getKey());
|
||||
}else{
|
||||
choice.setChoice(item.getKey());
|
||||
}
|
||||
} else {
|
||||
choice.setChoice((String)this.lstChoices.getSelectedValue());
|
||||
return true;
|
||||
}else{
|
||||
choice.clearChoice();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class KeyValueItem
|
||||
{
|
||||
private final String Key;
|
||||
private final String Value;
|
||||
|
||||
public KeyValueItem(String value, String label) {
|
||||
this.Key = value;
|
||||
this.Value = label;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
public String getKey() {
|
||||
return this.Key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.Value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
btnAutoSelect = new javax.swing.JButton();
|
||||
btnCancel = new javax.swing.JButton();
|
||||
btnOk = new javax.swing.JButton();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
lstChoices = new javax.swing.JList();
|
||||
lblMessage = new javax.swing.JLabel();
|
||||
panelHeader = new javax.swing.JPanel();
|
||||
labelMessage = new javax.swing.JLabel();
|
||||
labelSubMessage = new javax.swing.JLabel();
|
||||
panelSearch = new javax.swing.JPanel();
|
||||
labelSearch = new javax.swing.JLabel();
|
||||
editSearch = new javax.swing.JTextField();
|
||||
scrollList = new javax.swing.JScrollPane();
|
||||
listChoices = new javax.swing.JList();
|
||||
panelCommands = new javax.swing.JPanel();
|
||||
btOK = new javax.swing.JButton();
|
||||
btCancel = new javax.swing.JButton();
|
||||
|
||||
setResizable(true);
|
||||
setMinimumSize(new java.awt.Dimension(280, 200));
|
||||
setName(""); // NOI18N
|
||||
labelMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
labelMessage.setText("<html><div style='text-align: center;'>example long message example long message example long message example long message example long message</div></html>");
|
||||
|
||||
btnAutoSelect.setText("Auto select");
|
||||
btnAutoSelect.setToolTipText("If you select an effect with \"Auto select\", this effect will be selected the next time automatically first.");
|
||||
btnAutoSelect.addActionListener(evt -> btnAutoSelectActionPerformed(evt));
|
||||
labelSubMessage.setFont(labelSubMessage.getFont().deriveFont((labelSubMessage.getFont().getStyle() | java.awt.Font.ITALIC) | java.awt.Font.BOLD));
|
||||
labelSubMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
labelSubMessage.setText("<html><div style='text-align: center;'>example long message example long</div></html>");
|
||||
|
||||
btnCancel.setText("Cancel");
|
||||
btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt));
|
||||
javax.swing.GroupLayout panelHeaderLayout = new javax.swing.GroupLayout(panelHeader);
|
||||
panelHeader.setLayout(panelHeaderLayout);
|
||||
panelHeaderLayout.setHorizontalGroup(
|
||||
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelHeaderLayout.createSequentialGroup()
|
||||
.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(labelSubMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE))
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
panelHeaderLayout.setVerticalGroup(
|
||||
panelHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelHeaderLayout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(labelMessage)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(labelSubMessage))
|
||||
);
|
||||
|
||||
btnOk.setText("OK");
|
||||
btnOk.addActionListener(evt -> btnOkActionPerformed(evt));
|
||||
labelSearch.setText("Search:");
|
||||
|
||||
lstChoices.setModel(new javax.swing.AbstractListModel() {
|
||||
final String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||
editSearch.setText("sample search text");
|
||||
|
||||
javax.swing.GroupLayout panelSearchLayout = new javax.swing.GroupLayout(panelSearch);
|
||||
panelSearch.setLayout(panelSearchLayout);
|
||||
panelSearchLayout.setHorizontalGroup(
|
||||
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelSearchLayout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(labelSearch)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(editSearch)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
panelSearchLayout.setVerticalGroup(
|
||||
panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelSearchLayout.createSequentialGroup()
|
||||
.addGap(3, 3, 3)
|
||||
.addGroup(panelSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(labelSearch)
|
||||
.addComponent(editSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(3, 3, 3))
|
||||
);
|
||||
|
||||
listChoices.setModel(new javax.swing.AbstractListModel() {
|
||||
String[] strings = { "item1", "item2", "item3" };
|
||||
public int getSize() { return strings.length; }
|
||||
public Object getElementAt(int i) { return strings[i]; }
|
||||
});
|
||||
jScrollPane1.setViewportView(lstChoices);
|
||||
scrollList.setViewportView(listChoices);
|
||||
|
||||
lblMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
lblMessage.setText("message");
|
||||
btOK.setText("Choose");
|
||||
btOK.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btOKActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btCancel.setText("Cancel");
|
||||
btCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btCancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands);
|
||||
panelCommands.setLayout(panelCommandsLayout);
|
||||
panelCommandsLayout.setHorizontalGroup(
|
||||
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelCommandsLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btOK)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btCancel, btOK});
|
||||
|
||||
panelCommandsLayout.setVerticalGroup(
|
||||
panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelCommandsLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btCancel)
|
||||
.addComponent(btOK))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
getRootPane().setDefaultButton(btOK);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 335, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnAutoSelect)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnOk)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel))
|
||||
.addComponent(lblMessage, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 335, Short.MAX_VALUE))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(scrollList, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.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(panelSearch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(lblMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap()
|
||||
.addComponent(panelHeader, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE)
|
||||
.addComponent(panelSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnCancel)
|
||||
.addComponent(btnOk)
|
||||
.addComponent(btnAutoSelect))
|
||||
.addGap(10, 10, 10))
|
||||
.addComponent(scrollList, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed
|
||||
setChoice();
|
||||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnOkActionPerformed
|
||||
private void btOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btOKActionPerformed
|
||||
doChoose();
|
||||
}//GEN-LAST:event_btOKActionPerformed
|
||||
|
||||
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
|
||||
this.lstChoices.clearSelection();
|
||||
this.choice.clearChoice();
|
||||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnCancelActionPerformed
|
||||
private void btCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btCancelActionPerformed
|
||||
doCancel();
|
||||
}//GEN-LAST:event_btCancelActionPerformed
|
||||
|
||||
private void btnAutoSelectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAutoSelectActionPerformed
|
||||
this.autoSelect = true;
|
||||
setChoice();
|
||||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnAutoSelectActionPerformed
|
||||
/**
|
||||
* Closes the dialog
|
||||
*/
|
||||
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
|
||||
doCancel();
|
||||
}//GEN-LAST:event_closeDialog
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btnAutoSelect;
|
||||
private javax.swing.JButton btnCancel;
|
||||
private javax.swing.JButton btnOk;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JLabel lblMessage;
|
||||
private javax.swing.JList lstChoices;
|
||||
private javax.swing.JButton btCancel;
|
||||
private javax.swing.JButton btOK;
|
||||
private javax.swing.JTextField editSearch;
|
||||
private javax.swing.JLabel labelMessage;
|
||||
private javax.swing.JLabel labelSearch;
|
||||
private javax.swing.JLabel labelSubMessage;
|
||||
private javax.swing.JList listChoices;
|
||||
private javax.swing.JPanel panelCommands;
|
||||
private javax.swing.JPanel panelHeader;
|
||||
private javax.swing.JPanel panelSearch;
|
||||
private javax.swing.JScrollPane scrollList;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
||||
class ComboItem {
|
||||
|
||||
private final String value;
|
||||
private final String label;
|
||||
|
||||
public ComboItem(String value, String label) {
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
}
|
||||
}
|
|
@ -35,7 +35,9 @@
|
|||
package mage.client.dialog;
|
||||
|
||||
import java.awt.Point;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.*;
|
||||
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.util.SettingsManager;
|
||||
import mage.client.util.gui.GuiDisplayUtil;
|
||||
|
||||
|
@ -60,6 +62,13 @@ public class PickNumberDialog extends MageDialog {
|
|||
this.btnCancel.setVisible(false);
|
||||
this.pack();
|
||||
|
||||
// window settings
|
||||
if (this.isModal()){
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
|
||||
}else{
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
}
|
||||
|
||||
Point centered = SettingsManager.instance.getComponentPosition(getWidth(), getHeight());
|
||||
this.setLocation(centered.x, centered.y);
|
||||
GuiDisplayUtil.keepComponentInsideScreen(centered.x, centered.y, this);
|
||||
|
|
|
@ -114,6 +114,14 @@ public class PickPileDialog extends MageDialog {
|
|||
this.revalidate();
|
||||
this.repaint();
|
||||
this.setModal(true);
|
||||
|
||||
// window settings
|
||||
if (this.isModal()){
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
|
||||
}else{
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
}
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,15 +120,19 @@ public class ShowCardsDialog extends MageDialog {
|
|||
this.cardArea.addCardEventListener(eventListener);
|
||||
}
|
||||
|
||||
if (getParent() != MageFrame.getDesktop() /*|| this.isClosed*/) {
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.DEFAULT_LAYER);
|
||||
}
|
||||
pack();
|
||||
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
this.setModal(modal);
|
||||
|
||||
// window settings
|
||||
if (this.isModal()){
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
|
||||
}else{
|
||||
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (!positioned) {
|
||||
int width = ShowCardsDialog.this.getWidth();
|
||||
|
|
|
@ -791,7 +791,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
if (!exiles.containsKey(exile.getId())) {
|
||||
CardInfoWindowDialog newExile = new CardInfoWindowDialog(ShowType.EXILE, exile.getName());
|
||||
exiles.put(exile.getId(), newExile);
|
||||
MageFrame.getDesktop().add(newExile, JLayeredPane.MODAL_LAYER);
|
||||
MageFrame.getDesktop().add(newExile, JLayeredPane.PALETTE_LAYER);
|
||||
newExile.show();
|
||||
}
|
||||
exiles.get(exile.getId()).loadCards(exile, bigCard, gameId);
|
||||
|
@ -1004,7 +1004,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
CardInfoWindowDialog newGraveyard = new CardInfoWindowDialog(ShowType.GRAVEYARD, playerName);
|
||||
graveyardWindows.put(playerName, newGraveyard);
|
||||
MageFrame.getDesktop().add(newGraveyard, JLayeredPane.MODAL_LAYER);
|
||||
MageFrame.getDesktop().add(newGraveyard, JLayeredPane.PALETTE_LAYER);
|
||||
newGraveyard.loadCards(graveyards.get(playerName), bigCard, gameId, false);
|
||||
}
|
||||
|
||||
|
@ -1039,7 +1039,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
if (!windowMap.containsKey(name)) {
|
||||
cardInfoWindowDialog = new CardInfoWindowDialog(showType, name);
|
||||
windowMap.put(name, cardInfoWindowDialog);
|
||||
MageFrame.getDesktop().add(cardInfoWindowDialog, JLayeredPane.MODAL_LAYER);
|
||||
MageFrame.getDesktop().add(cardInfoWindowDialog, JLayeredPane.PALETTE_LAYER);
|
||||
} else {
|
||||
cardInfoWindowDialog = windowMap.get(name);
|
||||
}
|
||||
|
@ -1115,7 +1115,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
this.feedbackPanel.getFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId);
|
||||
if (dialog != null) {
|
||||
this.pickTarget.add(dialog);
|
||||
this.pickTarget.add(dialog); // TODO: 01.01.2018, JayDi85: why feedbackPanel saved to pickTarget list? Need to research
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1220,14 +1220,17 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
|
||||
public void getChoice(Choice choice, UUID objectId) {
|
||||
hideAll();
|
||||
// TODO: remember last choices and search incremental for same events?
|
||||
PickChoiceDialog pickChoice = new PickChoiceDialog();
|
||||
pickChoice.showDialog(choice, objectId, choiceWindowState);
|
||||
if (choice.isKeyChoice()) {
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoiceKey());
|
||||
/* // old code, auto complete was for auto scripting?
|
||||
if (pickChoice.isAutoSelect()) {
|
||||
SessionHandler.sendPlayerString(gameId, '#' + choice.getChoiceKey());
|
||||
} else {
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoiceKey());
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
SessionHandler.sendPlayerString(gameId, choice.getChoice());
|
||||
}
|
||||
|
|
|
@ -51,7 +51,9 @@ import javax.swing.UIManager;
|
|||
|
||||
import mage.client.SessionHandler;
|
||||
import mage.client.components.MageTextArea;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.game.FeedbackPanel.FeedbackMode;
|
||||
|
||||
import static mage.client.game.FeedbackPanel.FeedbackMode.QUESTION;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_ID_NO;
|
||||
|
@ -82,7 +84,6 @@ public class HelperPanel extends JPanel {
|
|||
private javax.swing.JButton linkSpecial;
|
||||
private javax.swing.JButton linkUndo;
|
||||
|
||||
private final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay();
|
||||
private final Object tooltipBackground = UIManager.get("info");
|
||||
|
||||
private static final String CMD_AUTO_ANSWER_ID_YES = "cmdAutoAnswerIdYes";
|
||||
|
@ -232,13 +233,13 @@ public class HelperPanel extends JPanel {
|
|||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent me) {
|
||||
ToolTipManager.sharedInstance().setDismissDelay(100000);
|
||||
ToolTipManager.sharedInstance().setDismissDelay(100 * 1000);
|
||||
UIManager.put("info", Color.DARK_GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent me) {
|
||||
ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout);
|
||||
ToolTipManager.sharedInstance().setDismissDelay(Constants.TOOLTIPS_DELAY_MS);
|
||||
UIManager.put("info", tooltipBackground);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,9 +32,11 @@ import org.apache.log4j.Logger;
|
|||
import org.mage.plugins.card.CardPluginImpl;
|
||||
import org.mage.plugins.theme.ThemePluginImpl;
|
||||
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
public enum Plugins implements MagePlugins {
|
||||
instance;
|
||||
public static final String PLUGINS_DIRECTORY = "plugins/";
|
||||
public static final String PLUGINS_DIRECTORY = "plugins";
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Plugins.class);
|
||||
private static PluginManager pm;
|
||||
|
@ -48,9 +50,10 @@ public enum Plugins implements MagePlugins {
|
|||
|
||||
@Override
|
||||
public void loadPlugins() {
|
||||
|
||||
LOGGER.info("Loading plugins...");
|
||||
pm = PluginManagerFactory.createPluginManager();
|
||||
pm.addPluginsFrom(new File(PLUGINS_DIRECTORY).toURI());
|
||||
pm.addPluginsFrom(new File(PLUGINS_DIRECTORY + File.separator).toURI());
|
||||
this.cardPlugin = new CardPluginImpl();
|
||||
this.counterPlugin = pm.getPlugin(CounterPlugin.class);
|
||||
this.themePlugin = new ThemePluginImpl();
|
||||
|
@ -131,10 +134,8 @@ public enum Plugins implements MagePlugins {
|
|||
|
||||
@Override
|
||||
public void downloadSymbols() {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String path = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
if (this.cardPlugin != null) {
|
||||
this.cardPlugin.downloadSymbols(path);
|
||||
this.cardPlugin.downloadSymbols(getImagesDir());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
import mage.cards.decks.importer.DeckImporterUtil;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.SessionHandler;
|
||||
|
@ -54,7 +57,6 @@ import mage.client.components.MageComponents;
|
|||
import mage.client.dialog.*;
|
||||
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_ORDER;
|
||||
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_WIDTH;
|
||||
import static mage.client.table.TablesPanel.PASSWORDED;
|
||||
import mage.client.util.ButtonColumn;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.client.util.IgnoreList;
|
||||
|
@ -70,6 +72,9 @@ import mage.view.RoomUsersView;
|
|||
import mage.view.TableView;
|
||||
import mage.view.UserRequestMessage;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.ocpsoft.prettytime.PrettyTime;
|
||||
import org.ocpsoft.prettytime.units.JustNow;
|
||||
import org.ocpsoft.prettytime.Duration;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -80,7 +85,6 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
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};
|
||||
|
||||
public static final String PASSWORDED = "***";
|
||||
private final TableTableModel tableModel;
|
||||
private final MatchesTableModel matchesModel;
|
||||
private UUID roomId;
|
||||
|
@ -94,12 +98,62 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
private java.util.List<String> messages;
|
||||
private int currentMessage;
|
||||
private final MageTableRowSorter activeTablesSorter;
|
||||
private final MageTableRowSorter completedTablesSorter;
|
||||
|
||||
private final ButtonColumn actionButton1;
|
||||
private final ButtonColumn actionButton2;
|
||||
|
||||
final JToggleButton[] filterButtons;
|
||||
|
||||
// time formater
|
||||
private PrettyTime timeFormater = new PrettyTime();
|
||||
|
||||
// time ago renderer
|
||||
TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
Date d = (Date)value;
|
||||
label.setText(timeFormater.format(d));
|
||||
return label;
|
||||
}
|
||||
};
|
||||
|
||||
// duration renderer
|
||||
TableCellRenderer durationCellRenderer = new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
Long ms = (Long)value;
|
||||
|
||||
if(ms != 0){
|
||||
Duration dur = timeFormater.approximateDuration(new Date(ms));
|
||||
label.setText((timeFormater.formatDuration(dur)));
|
||||
}else{
|
||||
label.setText("");
|
||||
}
|
||||
return label;
|
||||
}
|
||||
};
|
||||
|
||||
// datetime render
|
||||
TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() {
|
||||
DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
Date d = (Date)value;
|
||||
if(d != null){
|
||||
label.setText(datetimeFormater.format(d));
|
||||
}else{
|
||||
label.setText("");
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new form TablesPanel
|
||||
*/
|
||||
|
@ -112,20 +166,56 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
initComponents();
|
||||
// tableModel.setSession(session);
|
||||
|
||||
tableTables.createDefaultColumnsFromModel();
|
||||
// formater
|
||||
timeFormater.setLocale(Locale.ENGLISH);
|
||||
JustNow jn = timeFormater.getUnit(JustNow.class);
|
||||
jn.setMaxQuantity(1000L * 30L); // 30 seconds gap (show "just now" from 0 to 30 secs)
|
||||
|
||||
// 1. TABLE CURRENT
|
||||
tableTables.createDefaultColumnsFromModel();
|
||||
activeTablesSorter = new MageTableRowSorter(tableModel);
|
||||
tableTables.setRowSorter(activeTablesSorter);
|
||||
|
||||
// time ago
|
||||
tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer);
|
||||
/* date sorter (not need, default is good - see getColumnClass)
|
||||
activeTablesSorter.setComparator(TableTableModel.COLUMN_CREATED, new Comparator<Date>() {
|
||||
@Override
|
||||
public int compare(Date v1, Date v2) {
|
||||
return v1.compareTo(v2);
|
||||
}
|
||||
|
||||
});*/
|
||||
// default sort by created date (last games from above)
|
||||
ArrayList list = new ArrayList();
|
||||
list.add(new RowSorter.SortKey(TableTableModel.COLUMN_CREATED, SortOrder.DESCENDING));
|
||||
activeTablesSorter.setSortKeys(list);
|
||||
|
||||
TableUtil.setColumnWidthAndOrder(tableTables, DEFAULT_COLUMNS_WIDTH,
|
||||
PreferencesDialog.KEY_TABLES_COLUMNS_WIDTH, PreferencesDialog.KEY_TABLES_COLUMNS_ORDER);
|
||||
PreferencesDialog.KEY_TABLES_COLUMNS_WIDTH, PreferencesDialog.KEY_TABLES_COLUMNS_ORDER); // TODO: is sort order save and restore after app restart/window open?
|
||||
|
||||
tableCompleted.setRowSorter(new MageTableRowSorter(matchesModel));
|
||||
|
||||
|
||||
// 2. TABLE COMPLETED
|
||||
completedTablesSorter = new MageTableRowSorter(matchesModel);
|
||||
tableCompleted.setRowSorter(completedTablesSorter);
|
||||
|
||||
// duration
|
||||
tableCompleted.getColumnModel().getColumn(MatchesTableModel.COLUMN_DURATION).setCellRenderer(durationCellRenderer);
|
||||
// start-end
|
||||
tableCompleted.getColumnModel().getColumn(MatchesTableModel.COLUMN_START).setCellRenderer(datetimeCellRenderer);
|
||||
tableCompleted.getColumnModel().getColumn(MatchesTableModel.COLUMN_END).setCellRenderer(datetimeCellRenderer);
|
||||
// default sort by ended date (last games from above)
|
||||
ArrayList list2 = new ArrayList();
|
||||
list2.add(new RowSorter.SortKey(MatchesTableModel.COLUMN_END, SortOrder.DESCENDING));
|
||||
completedTablesSorter.setSortKeys(list2);
|
||||
|
||||
// 3. CHAT
|
||||
chatPanelMain.getUserChatPanel().useExtendedView(ChatPanelBasic.VIEW_MODE.NONE);
|
||||
chatPanelMain.getUserChatPanel().setBorder(null);
|
||||
chatPanelMain.getUserChatPanel().setChatType(ChatPanelBasic.ChatType.TABLES);
|
||||
|
||||
// 4. BUTTONS
|
||||
filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished,
|
||||
btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited,
|
||||
btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther,
|
||||
|
@ -181,7 +271,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
if (isTournament) {
|
||||
LOGGER.info("Joining tournament " + tableId);
|
||||
if (deckType.startsWith("Limited")) {
|
||||
if (PASSWORDED.equals(pwdColumn)) {
|
||||
if (TableTableModel.PASSWORD_VALUE_YES.equals(pwdColumn)) {
|
||||
joinTableDialog.showDialog(roomId, tableId, true, deckType.startsWith("Limited"));
|
||||
} else {
|
||||
SessionHandler.joinTournamentTable(roomId, tableId, SessionHandler.getUserName(), PlayerType.HUMAN, 1, null, "");
|
||||
|
@ -225,7 +315,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int modelRow = Integer.valueOf(e.getActionCommand());
|
||||
String action = (String) matchesModel.getValueAt(modelRow, MatchesTableModel.ACTION_COLUMN);
|
||||
String action = (String) matchesModel.getValueAt(modelRow, MatchesTableModel.COLUMN_ACTION);
|
||||
switch (action) {
|
||||
case "Replay":
|
||||
java.util.List<UUID> gameList = matchesModel.getListofGames(modelRow);
|
||||
|
@ -250,7 +340,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
|
||||
// !!!! adds action buttons to the table panel (don't delete this)
|
||||
actionButton1 = new ButtonColumn(tableTables, openTableAction, tableTables.convertColumnIndexToView(TableTableModel.ACTION_COLUMN));
|
||||
actionButton2 = new ButtonColumn(tableCompleted, closedTableAction, tableCompleted.convertColumnIndexToView(MatchesTableModel.ACTION_COLUMN));
|
||||
actionButton2 = new ButtonColumn(tableCompleted, closedTableAction, tableCompleted.convertColumnIndexToView(MatchesTableModel.COLUMN_ACTION));
|
||||
// !!!!
|
||||
}
|
||||
|
||||
|
@ -560,7 +650,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
formatFilterList.add(RowFilter.regexFilter("^Constructed - Vintage", TableTableModel.COLUMN_DECK_TYPE));
|
||||
}
|
||||
if (btnFormatCommander.isSelected()) {
|
||||
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander", TableTableModel.COLUMN_DECK_TYPE));
|
||||
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander", TableTableModel.COLUMN_DECK_TYPE));
|
||||
}
|
||||
if (btnFormatTinyLeader.isSelected()) {
|
||||
formatFilterList.add(RowFilter.regexFilter("^Tiny", TableTableModel.COLUMN_DECK_TYPE));
|
||||
|
@ -583,21 +673,27 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
skillFilterList.add(RowFilter.regexFilter(SkillLevel.SERIOUS.toString(), TableTableModel.COLUMN_SKILL));
|
||||
}
|
||||
|
||||
String ratedMark = TableTableModel.RATED_VALUE_YES;
|
||||
java.util.List<RowFilter<Object, Object>> ratingFilterList = new ArrayList<>();
|
||||
if (btnRated.isSelected()) {
|
||||
ratingFilterList.add(RowFilter.regexFilter("^Rated", TableTableModel.COLUMN_RATING));
|
||||
// yes word
|
||||
ratingFilterList.add(RowFilter.regexFilter("^" + ratedMark, TableTableModel.COLUMN_RATING));
|
||||
}
|
||||
if (btnUnrated.isSelected()) {
|
||||
ratingFilterList.add(RowFilter.regexFilter("^Unrated", TableTableModel.COLUMN_RATING));
|
||||
// not yes word, see https://stackoverflow.com/a/406408/1276632
|
||||
ratingFilterList.add(RowFilter.regexFilter("^((?!" + ratedMark + ").)*$", TableTableModel.COLUMN_RATING));
|
||||
}
|
||||
|
||||
// Password
|
||||
String passwordMark = TableTableModel.PASSWORD_VALUE_YES;
|
||||
java.util.List<RowFilter<Object, Object>> passwordFilterList = new ArrayList<>();
|
||||
if (btnOpen.isSelected()) {
|
||||
passwordFilterList.add(RowFilter.regexFilter("^$", TableTableModel.COLUMN_PASSWORD));
|
||||
}
|
||||
if (btnPassword.isSelected()) {
|
||||
passwordFilterList.add(RowFilter.regexFilter("^\\*\\*\\*$", TableTableModel.COLUMN_PASSWORD));
|
||||
// yes
|
||||
passwordFilterList.add(RowFilter.regexFilter("^" + passwordMark, TableTableModel.COLUMN_PASSWORD));
|
||||
}
|
||||
if (btnOpen.isSelected()) {
|
||||
// no
|
||||
passwordFilterList.add(RowFilter.regexFilter("^((?!" + passwordMark + ").)*$", TableTableModel.COLUMN_PASSWORD));
|
||||
}
|
||||
|
||||
// Hide games of ignored players
|
||||
|
@ -1281,16 +1377,24 @@ class TableTableModel extends AbstractTableModel {
|
|||
public static final int COLUMN_QUIT_RATIO = 10;
|
||||
public static final int ACTION_COLUMN = 11; // 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", "Rating", "Quit %", "Action"};
|
||||
|
||||
private TableView[] tables = new TableView[0];
|
||||
private static final DateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
TableTableModel() {
|
||||
}
|
||||
|
||||
public void loadData(Collection<TableView> tables) throws MageRemoteException {
|
||||
this.tables = tables.toArray(new TableView[0]);
|
||||
this.fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return tables.length;
|
||||
|
@ -1317,13 +1421,13 @@ class TableTableModel extends AbstractTableModel {
|
|||
case 5:
|
||||
return tables[arg0].getTableStateText();
|
||||
case 6:
|
||||
return tables[arg0].isPassworded() ? PASSWORDED : "";
|
||||
return tables[arg0].isPassworded() ? PASSWORD_VALUE_YES : "";
|
||||
case 7:
|
||||
return timeFormatter.format(tables[arg0].getCreateTime());
|
||||
return tables[arg0].getCreateTime(); // use cell render, not format here
|
||||
case 8:
|
||||
return tables[arg0].getSkillLevel();
|
||||
case 9:
|
||||
return tables[arg0].isRated() ? "Rated" : "Unrated";
|
||||
return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO;
|
||||
case 10:
|
||||
return tables[arg0].getQuitRatio();
|
||||
case 11:
|
||||
|
@ -1384,6 +1488,8 @@ class TableTableModel extends AbstractTableModel {
|
|||
return Icon.class;
|
||||
case COLUMN_SKILL:
|
||||
return SkillLevel.class;
|
||||
case COLUMN_CREATED:
|
||||
return Date.class;
|
||||
default:
|
||||
return String.class;
|
||||
}
|
||||
|
@ -1486,17 +1592,22 @@ class UpdatePlayersTask extends SwingWorker<Void, Collection<RoomUsersView>> {
|
|||
|
||||
class MatchesTableModel extends AbstractTableModel {
|
||||
|
||||
public static final int ACTION_COLUMN = 7; // column the action is located (starting with 0)
|
||||
public static final int GAMES_LIST_COLUMN = 8;
|
||||
private final String[] columnNames = new String[]{"Deck Type", "Players", "Game Type", "Rating", "Result", "Start Time", "End Time", "Action"};
|
||||
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];
|
||||
private static final DateFormat timeFormatter = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||
|
||||
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;
|
||||
|
@ -1517,22 +1628,20 @@ class MatchesTableModel extends AbstractTableModel {
|
|||
case 2:
|
||||
return matches[arg0].getGameType();
|
||||
case 3:
|
||||
return matches[arg0].isRated() ? "Rated" : "Unrated";
|
||||
return matches[arg0].isRated() ? TableTableModel.RATED_VALUE_YES : TableTableModel.RATED_VALUE_NO;
|
||||
case 4:
|
||||
return matches[arg0].getResult();
|
||||
case 5:
|
||||
if (matches[arg0].getStartTime() != null) {
|
||||
return timeFormatter.format(matches[arg0].getStartTime());
|
||||
if (matches[arg0].getEndTime() != null) {
|
||||
return matches[arg0].getEndTime().getTime() - matches[arg0].getStartTime().getTime() + new Date().getTime();
|
||||
} else {
|
||||
return "";
|
||||
return 0L;
|
||||
}
|
||||
case 6:
|
||||
if (matches[arg0].getEndTime() != null) {
|
||||
return timeFormatter.format(matches[arg0].getEndTime());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return matches[arg0].getStartTime();
|
||||
case 7:
|
||||
return matches[arg0].getEndTime();
|
||||
case 8:
|
||||
if (matches[arg0].isTournament()) {
|
||||
return "Show";
|
||||
} else if (matches[arg0].isReplayAvailable()) {
|
||||
|
@ -1540,7 +1649,7 @@ class MatchesTableModel extends AbstractTableModel {
|
|||
} else {
|
||||
return "None";
|
||||
}
|
||||
case 8:
|
||||
case 9:
|
||||
return matches[arg0].getGames();
|
||||
}
|
||||
return "";
|
||||
|
@ -1575,12 +1684,21 @@ class MatchesTableModel extends AbstractTableModel {
|
|||
|
||||
@Override
|
||||
public Class getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
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 == ACTION_COLUMN;
|
||||
return columnIndex == COLUMN_ACTION;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package mage.client.util.gui;
|
||||
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.client.dialog.PickChoiceDialog;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class FastSearchUtil {
|
||||
|
||||
public static String DEFAULT_EXPANSION_SEARCH_MESSAGE = "Select set or expansion";
|
||||
public static String DEFAULT_EXPANSION_TOOLTIP_MESSAGE = "Fast search set or expansion";
|
||||
|
||||
/**
|
||||
* Show fast choice modal dialog with incremental searching for any string combobox components
|
||||
* @param combo combobox control with default data model
|
||||
* @param chooseMessage caption message for dialog
|
||||
*/
|
||||
public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage){
|
||||
// fast search/choice dialog for string combobox
|
||||
|
||||
mage.choices.Choice choice = new ChoiceImpl(false);
|
||||
|
||||
// collect data from expansion combobox (String)
|
||||
DefaultComboBoxModel comboModel = (DefaultComboBoxModel)combo.getModel();
|
||||
Map<String, String> choiceItems = new HashMap<>(comboModel.getSize());
|
||||
Map<String, Integer> choiceSorting = new HashMap<>(comboModel.getSize());
|
||||
String item;
|
||||
|
||||
for(int i = 0; i < comboModel.getSize(); i++){
|
||||
item = comboModel.getElementAt(i).toString();
|
||||
choiceItems.put(item, item);
|
||||
choiceSorting.put(item, i); // need so sorting
|
||||
}
|
||||
|
||||
choice.setKeyChoices(choiceItems);
|
||||
choice.setSortData(choiceSorting);
|
||||
choice.setMessage(chooseMessage);
|
||||
|
||||
// current selection value restore
|
||||
String needSelectValue;
|
||||
needSelectValue = comboModel.getSelectedItem().toString();
|
||||
|
||||
// ask for new value
|
||||
PickChoiceDialog dlg = new PickChoiceDialog();
|
||||
dlg.setWindowSize(300, 500);
|
||||
dlg.showDialog(choice, needSelectValue);
|
||||
if(choice.isChosen()){
|
||||
item = choice.getChoiceKey();
|
||||
|
||||
// compatible select for object's models (use setSelectedIndex instead setSelectedObject)
|
||||
for(int i = 0; i < comboModel.getSize(); i++){
|
||||
if(comboModel.getElementAt(i).toString().equals(item)){
|
||||
combo.setSelectedIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,44 +27,34 @@
|
|||
*/
|
||||
package mage.client.util.gui.countryBox;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.plaf.basic.BasicComboBoxEditor;
|
||||
|
||||
|
||||
/**
|
||||
* Editor for JComboBox
|
||||
* @author wwww.codejava.net
|
||||
* @author wwww.codejava.net, JayDi85
|
||||
*
|
||||
*/
|
||||
public class CountryItemEditor extends BasicComboBoxEditor {
|
||||
private final JPanel panel = new JPanel();
|
||||
private final JLabel labelItem = new JLabel();
|
||||
private String selectedValue;
|
||||
private String selectedImage;
|
||||
private String[] editValue = new String[2];
|
||||
|
||||
public CountryItemEditor() {
|
||||
panel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraints.weightx = 1.0;
|
||||
// constraints.insets = new Insets(2, 5, 2, 2);
|
||||
constraints.insets = new Insets(0, 5, 0, 0);
|
||||
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
||||
panel.setBackground(new Color(0, 100,190, 255));
|
||||
|
||||
panel.add(labelItem);
|
||||
labelItem.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
labelItem.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
|
||||
labelItem.setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||
labelItem.setOpaque(false);
|
||||
labelItem.setHorizontalAlignment(JLabel.LEFT);
|
||||
labelItem.setForeground(Color.WHITE);
|
||||
|
||||
panel.add(labelItem, constraints);
|
||||
// panel.setBackground(Color.WHITE);
|
||||
panel.setBackground(new Color(0, 100,190, 255));
|
||||
selectedValue = null;
|
||||
|
||||
editValue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,21 +64,26 @@ public class CountryItemEditor extends BasicComboBoxEditor {
|
|||
|
||||
@Override
|
||||
public Object getItem() {
|
||||
return this.selectedValue;
|
||||
return this.editValue;
|
||||
}
|
||||
|
||||
public String getImageItem() {
|
||||
return this.selectedImage;
|
||||
}
|
||||
return this.editValue[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(Object item) {
|
||||
if (item == null || !(item instanceof String[])) {
|
||||
return;
|
||||
}
|
||||
String[] countryItem = (String[]) item;
|
||||
selectedValue = countryItem[0];
|
||||
selectedImage = countryItem[1];
|
||||
labelItem.setText(selectedValue);
|
||||
labelItem.setIcon(new ImageIcon(getClass().getResource("/flags/"+ countryItem[1] + ".png")));
|
||||
|
||||
String[] newItem = (String[])item;
|
||||
|
||||
editValue = new String[2];
|
||||
editValue[0] = newItem[0];
|
||||
editValue[1] = newItem[1];
|
||||
|
||||
labelItem.setText(editValue[0]);
|
||||
labelItem.setIcon(new ImageIcon(getClass().getResource("/flags/"+ editValue[1] + ".png")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,10 @@ public class MyComboBoxRenderer extends JLabel implements ListCellRenderer {
|
|||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
setText(value.toString());
|
||||
|
||||
String[] val = (String[]) value;
|
||||
setText(val[0]);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package mage.client.util.stats;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class MemoryStats {
|
||||
|
||||
private float Available = 0;
|
||||
private float MaxAvailable = 0;
|
||||
private float Used = 0;
|
||||
private float Free = 0;
|
||||
|
||||
public MemoryStats(float MaxAvailable, float Available, float Used, float Free){
|
||||
this.setMaxAvailable(MaxAvailable);
|
||||
this.setAvailable(Available);
|
||||
this.setUsed(Used);
|
||||
this.setFree(Free);
|
||||
}
|
||||
|
||||
public float getAvailable() {
|
||||
return Available;
|
||||
}
|
||||
|
||||
public void setAvailable(float available) {
|
||||
Available = available;
|
||||
}
|
||||
|
||||
public float getUsed() {
|
||||
return Used;
|
||||
}
|
||||
|
||||
public void setUsed(float used) {
|
||||
Used = used;
|
||||
}
|
||||
|
||||
public float getFree() {
|
||||
return Free;
|
||||
}
|
||||
|
||||
public void setFree(float free) {
|
||||
Free = free;
|
||||
}
|
||||
|
||||
public float getMaxAvailable() {
|
||||
return MaxAvailable;
|
||||
}
|
||||
|
||||
public void setMaxAvailable(float maxAvailable) {
|
||||
MaxAvailable = maxAvailable;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package mage.client.util.stats;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
public final class MemoryUsageStatUtil {
|
||||
|
||||
private MemoryUsageStatUtil() {}
|
||||
|
||||
/**
|
||||
* Returns percentage of available memory used at runtime.
|
||||
* If not possible to determine, returns -1.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static float getMemoryFreeStatPercentage() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
if (runtime.maxMemory() != 0) {
|
||||
long usedMem = runtime.totalMemory() - runtime.freeMemory();
|
||||
return (1 - (1.0f*usedMem)/runtime.maxMemory())*100;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package mage.client.util.stats;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -11,11 +12,13 @@ import org.apache.log4j.Logger;
|
|||
* This updates the mem usage info in the Mage client every
|
||||
* MEM_USAGE_UPDATE_TIME ms.
|
||||
*
|
||||
* @author noxx
|
||||
* @author noxx, JayDi85
|
||||
*/
|
||||
public class UpdateMemUsageTask extends SwingWorker<Void, Float> {
|
||||
|
||||
public class UpdateMemUsageTask extends SwingWorker<Void, MemoryStats> {
|
||||
|
||||
private static final int MEM_USAGE_UPDATE_TIME = 2000;
|
||||
private static final int MEM_USAGE_WARNING_PERCENT = 80; // red color for mem used more than xx%
|
||||
|
||||
private final JLabel jLabelToDisplayInfo;
|
||||
|
||||
|
@ -23,24 +26,60 @@ public class UpdateMemUsageTask extends SwingWorker<Void, Float> {
|
|||
|
||||
public UpdateMemUsageTask(JLabel jLabelToDisplayInfo) {
|
||||
this.jLabelToDisplayInfo = jLabelToDisplayInfo;
|
||||
this.jLabelToDisplayInfo.setToolTipText("<html>Memory usage statistics");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
while (!isCancelled()) {
|
||||
float memUsage = MemoryUsageStatUtil.getMemoryFreeStatPercentage();
|
||||
this.publish(memUsage >= 0 ? memUsage : null);
|
||||
MemoryStats memoryStats = new MemoryStats(0, 0, 0, 0);
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
if (runtime.maxMemory() != 0) {
|
||||
memoryStats.setMaxAvailable(runtime.maxMemory());
|
||||
memoryStats.setAvailable(runtime.totalMemory());
|
||||
memoryStats.setFree(runtime.freeMemory());
|
||||
memoryStats.setUsed(runtime.totalMemory() - runtime.freeMemory());
|
||||
}
|
||||
|
||||
this.publish(memoryStats);
|
||||
TimeUnit.MILLISECONDS.sleep(MEM_USAGE_UPDATE_TIME);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<Float> chunks) {
|
||||
protected void process(List<MemoryStats> chunks) {
|
||||
if (chunks != null && !chunks.isEmpty()) {
|
||||
Float memUsage = chunks.get(chunks.size() - 1);
|
||||
if (memUsage != null) {
|
||||
jLabelToDisplayInfo.setText(Math.round(memUsage) + "% Mem free");
|
||||
MemoryStats memoryStats = chunks.get(chunks.size() - 1);
|
||||
if (memoryStats != null) {
|
||||
int max = Math.round(memoryStats.getMaxAvailable() / (1000 * 1000));
|
||||
int used = Math.round(memoryStats.getUsed() / (1000 * 1000));
|
||||
int total = Math.round(memoryStats.getAvailable() / (1000 * 1000));
|
||||
int percent = 0;
|
||||
if(max != 0){
|
||||
percent = Math.round((used * 100) / max);
|
||||
}
|
||||
|
||||
jLabelToDisplayInfo.setText("Memory used: " + percent + "% (" + used + " of " + max + " MB)");
|
||||
String warning = "";
|
||||
String optimizeHint = "<br><br>If you see low memory warning and have free system memory then try to increase max limit in launcher settings:<br>"
|
||||
+ " - Go to <i>launcher -> settings -> java tab</i>;<br>"
|
||||
+ " - Find <i>client java options</i> (it's may contain many commands);<br>"
|
||||
+ " - Find max available memory setting: <i>-Xmx256m</i> (it's must start with <b>-Xmx</b>);<br>"
|
||||
+ " - Increase number in that value from 256 to 512, or 512 to 1024;<br>"
|
||||
+ " - Save new settings and restart application.";
|
||||
if(percent >= MEM_USAGE_WARNING_PERCENT){
|
||||
jLabelToDisplayInfo.setForeground(Color.red);
|
||||
warning = "<br><br><b>WARNING</b><br>"
|
||||
+ "Application memory limit almost reached. Errors and freezes are very possible.";
|
||||
|
||||
}else{
|
||||
jLabelToDisplayInfo.setForeground(Color.black);
|
||||
}
|
||||
|
||||
this.jLabelToDisplayInfo.setToolTipText("<html>Memory usage statistics" + warning + optimizeHint);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
|
||||
private JPanel cardArea;
|
||||
|
||||
private int yTextOffset = 10;
|
||||
// default offset, e.g. for battlefield
|
||||
private int yCardCaptionOffsetPercent = 8; // card caption offset (use for moving card caption view center, below mana icons -- for more good UI)
|
||||
|
||||
// if this is set, it's opened if the user right clicks on the card panel
|
||||
private JPopupMenu popupMenu;
|
||||
|
@ -819,12 +820,12 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setTextOffset(int yOffset) {
|
||||
yTextOffset = yOffset;
|
||||
public void setCardCaptionTopOffset(int yOffsetPercent) {
|
||||
yCardCaptionOffsetPercent = yOffsetPercent;
|
||||
}
|
||||
|
||||
public int getTextOffset() {
|
||||
return yTextOffset;
|
||||
public int getCardCaptionTopOffset() {
|
||||
return yCardCaptionOffsetPercent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,28 +13,26 @@ import mage.view.CardView;
|
|||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.StackAbilityView;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||
import mage.client.constants.Constants;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.LineBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||
|
||||
/**
|
||||
* Class for drawing the mage card object by using a form based JComponent
|
||||
* approach
|
||||
*
|
||||
* @author arcane, nantuko, noxx, stravant
|
||||
* @author arcane, nantuko, noxx, stravant, JayDi85
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class CardPanelComponentImpl extends CardPanel {
|
||||
|
@ -47,9 +45,14 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
|
||||
private static final float ROUNDED_CORNER_SIZE = 0.1f;
|
||||
private static final float BLACK_BORDER_SIZE = 0.03f;
|
||||
private static final float SELECTION_BORDER_SIZE = 0.03f;
|
||||
private static final int TEXT_GLOW_SIZE = 6;
|
||||
private static final float TEXT_GLOW_INTENSITY = 3f;
|
||||
|
||||
// size to show icons and text (help to see full size card without text)
|
||||
private static final int CARD_MIN_SIZE_FOR_ICONS = 60;
|
||||
private static final int CARD_MAX_SIZE_FOR_ICONS = 200;
|
||||
|
||||
public final ScaledImagePanel imagePanel;
|
||||
public ImagePanel overlayPanel;
|
||||
|
||||
|
@ -177,6 +180,34 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap((Function<Key, BufferedImage>) key -> createImage(key)));
|
||||
}
|
||||
|
||||
static private boolean canShowCardIcons(int cardFullWidth, boolean cardHasImage){
|
||||
// cards without images show icons and text always
|
||||
// TODO: apply "card names on card" setting to icon too?
|
||||
// TODO: fix card min-max size to hide (compare to settings size, not direct 60 and 200)
|
||||
return ((cardFullWidth > 60) && (cardFullWidth < 200)) || (!cardHasImage);
|
||||
}
|
||||
|
||||
private static class CardSizes{
|
||||
Rectangle rectFull;
|
||||
Rectangle rectSelection;
|
||||
Rectangle rectBorder;
|
||||
Rectangle rectCard;
|
||||
|
||||
CardSizes(int offsetX, int offsetY, int fullWidth, int fullHeight){
|
||||
|
||||
int realBorderSizeX = Math.round(fullWidth * BLACK_BORDER_SIZE);
|
||||
int realBorderSizeY = Math.round(fullWidth * BLACK_BORDER_SIZE);
|
||||
int realSelectionSizeX = Math.round(fullWidth * SELECTION_BORDER_SIZE);
|
||||
int realSelectionSizeY = Math.round(fullWidth * SELECTION_BORDER_SIZE);
|
||||
|
||||
// card full size = select border + black border + real card
|
||||
rectFull = new Rectangle(offsetX, offsetY, fullWidth, fullHeight);
|
||||
rectSelection = new Rectangle(rectFull.x, rectFull.y, rectFull.width, rectFull.height);
|
||||
rectBorder = new Rectangle(rectSelection.x + realSelectionSizeX, rectSelection.y + realSelectionSizeY, rectSelection.width - 2 * realSelectionSizeX, rectSelection.height - 2 * realSelectionSizeY);
|
||||
rectCard = new Rectangle(rectBorder.x + realBorderSizeX, rectBorder.y + realBorderSizeY, rectBorder.width - 2 * realBorderSizeX, rectBorder.height - 2 * realBorderSizeY);
|
||||
}
|
||||
}
|
||||
|
||||
public CardPanelComponentImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||
// Call to super
|
||||
super(newGameCard, gameId, loadImage, callback, foil, dimension);
|
||||
|
@ -368,32 +399,45 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
Graphics2D g2d = image.createGraphics();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
if (!key.hasImage) {
|
||||
g2d.setColor(new Color(30, 200, 200, 120));
|
||||
} else {
|
||||
g2d.setColor(new Color(0, 0, 0, 0));
|
||||
}
|
||||
// card full size = select border + black border + real card
|
||||
CardSizes sizes = new CardSizes(cardXOffset, cardYOffset, cardWidth, cardHeight);
|
||||
|
||||
int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
// corners for selection and for border
|
||||
int cornerSizeSelection = Math.max(4, Math.round(sizes.rectSelection.width * ROUNDED_CORNER_SIZE));
|
||||
int cornerSizeBorder = Math.max(4, Math.round(sizes.rectBorder.width * ROUNDED_CORNER_SIZE));
|
||||
|
||||
// DRAW ORDER from big to small: select -> select info -> border -> card
|
||||
|
||||
// draw selection
|
||||
if (key.isSelected) {
|
||||
g2d.setColor(Color.green);
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(sizes.rectSelection.x + 1, sizes.rectSelection.y + 1, sizes.rectSelection.width - 2, sizes.rectSelection.height - 2, cornerSizeSelection, cornerSizeSelection);
|
||||
} else if (key.isChoosable) {
|
||||
g2d.setColor(new Color(250, 250, 0, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(sizes.rectSelection.x + 1, sizes.rectSelection.y + 1, sizes.rectSelection.width - 2, sizes.rectSelection.height - 2, cornerSizeSelection, cornerSizeSelection);
|
||||
} else if (key.isPlayable) {
|
||||
g2d.setColor(new Color(153, 102, 204, 200));
|
||||
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(sizes.rectSelection.x, sizes.rectSelection.y, sizes.rectSelection.width, sizes.rectSelection.height, cornerSizeSelection, cornerSizeSelection);
|
||||
}
|
||||
|
||||
// draw empty card with border
|
||||
if (!key.hasImage) {
|
||||
// gray 1 px border
|
||||
g2d.setColor(new Color(125, 125, 125, 255));
|
||||
g2d.fillRoundRect(sizes.rectBorder.x, sizes.rectBorder.y, sizes.rectBorder.width, sizes.rectBorder.height, cornerSizeBorder, cornerSizeBorder);
|
||||
// color plate
|
||||
g2d.setColor(new Color(30, 200, 200, 200));
|
||||
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
|
||||
}
|
||||
|
||||
// draw attack border (inner part of selection)
|
||||
if (key.canAttack) {
|
||||
g2d.setColor(new Color(0, 0, 255, 230));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
|
||||
}
|
||||
|
||||
// draw real card by component (see imagePanel and other layout's items)
|
||||
|
||||
//TODO:uncomment
|
||||
/*
|
||||
if (gameCard.isAttacking()) {
|
||||
|
@ -409,23 +453,55 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
protected void paintChildren(Graphics g) {
|
||||
super.paintChildren(g);
|
||||
|
||||
if (getShowCastingCost() && !isAnimationPanel() && getCardWidth() < 200 && getCardWidth() > 60) {
|
||||
CardSizes realCard = new CardSizes(getCardXOffset(), getCardYOffset(), getCardWidth(), getCardHeight());
|
||||
|
||||
/*
|
||||
// draw recs for debug
|
||||
|
||||
// full card
|
||||
g.setColor(new Color(255, 0, 0));
|
||||
g.drawRect(realCard.rectFull.x, realCard.rectFull.y, realCard.rectFull.width, realCard.rectFull.height);
|
||||
|
||||
// real card - image
|
||||
g.setColor(new Color(0, 0, 255));
|
||||
g.drawRect(imagePanel.getX(), imagePanel.getY(), imagePanel.getBounds().width, imagePanel.getBounds().height);
|
||||
|
||||
// caption
|
||||
g.setColor(new Color(0, 255, 255));
|
||||
g.drawRect(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
|
||||
|
||||
// life points
|
||||
g.setColor(new Color(120, 0, 120));
|
||||
g.drawRect(ptText.getX(), ptText.getY(), ptText.getBounds().width, ptText.getBounds().height);
|
||||
//*/
|
||||
|
||||
if (getShowCastingCost() && !isAnimationPanel() && canShowCardIcons(getCardWidth(), hasImage)) {
|
||||
|
||||
int symbolMarginX = 2; // 2 px between icons
|
||||
|
||||
String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
|
||||
int width = getWidth(manaCost);
|
||||
if (hasImage) {
|
||||
ManaSymbols.draw(g, manaCost, getCardXOffset() + getCardWidth() - width - 5, getCardYOffset() + 5, getSymbolWidth());
|
||||
} else {
|
||||
ManaSymbols.draw(g, manaCost, getCardXOffset() + 8, getCardHeight() - 9, getSymbolWidth());
|
||||
}
|
||||
int manaWidth = getManaWidth(manaCost, symbolMarginX);
|
||||
|
||||
// right top corner with margin (sizes from any sample card, length from black border to mana icon)
|
||||
int manaMarginRight = Math.round(22f / 672f * getCardWidth());
|
||||
int manaMarginTop = Math.round(24f / 936f * getCardHeight());
|
||||
|
||||
int manaX = getCardXOffset() + getCardWidth() - manaMarginRight - manaWidth;
|
||||
int manaY = getCardYOffset() + manaMarginTop;
|
||||
|
||||
ManaSymbols.draw(g, manaCost, manaX, manaY, getSymbolWidth(), Color.black, symbolMarginX);
|
||||
}
|
||||
}
|
||||
|
||||
private int getWidth(String manaCost) {
|
||||
private int getManaWidth(String manaCost, int symbolMarginX) {
|
||||
int width = 0;
|
||||
manaCost = manaCost.replace("\\", "");
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
tok.nextToken();
|
||||
if(width != 0) {
|
||||
width += symbolMarginX;
|
||||
}
|
||||
width += getSymbolWidth();
|
||||
}
|
||||
return width;
|
||||
|
@ -439,24 +515,28 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
int cardHeight = getCardHeight();
|
||||
int cardXOffset = getCardXOffset();
|
||||
int cardYOffset = getCardYOffset();
|
||||
int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE);
|
||||
imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
|
||||
CardSizes sizes = new CardSizes(cardXOffset, cardYOffset, cardWidth, cardHeight);
|
||||
|
||||
// origin card without selection
|
||||
Rectangle realCardSize = sizes.rectBorder;
|
||||
imagePanel.setLocation(realCardSize.x, realCardSize.y);
|
||||
imagePanel.setSize(realCardSize.width, realCardSize.height);
|
||||
|
||||
if (hasSickness() && gameCard.isCreature() && isPermanent()) {
|
||||
overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
overlayPanel.setLocation(realCardSize.x, realCardSize.y);
|
||||
overlayPanel.setSize(realCardSize.width, realCardSize.height);
|
||||
} else {
|
||||
overlayPanel.setVisible(false);
|
||||
}
|
||||
|
||||
if (iconPanel != null) {
|
||||
iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
iconPanel.setLocation(realCardSize.x, realCardSize.y);
|
||||
iconPanel.setSize(realCardSize.width, realCardSize.height);
|
||||
}
|
||||
if (counterPanel != null) {
|
||||
counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
|
||||
counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
|
||||
counterPanel.setLocation(realCardSize.x, realCardSize.y);
|
||||
counterPanel.setSize(realCardSize.width, realCardSize.height);
|
||||
int size = cardWidth > WIDTH_LIMIT ? 40 : 20;
|
||||
|
||||
minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2);
|
||||
|
@ -472,32 +552,52 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
otherCounterLabel.setSize(size, size);
|
||||
|
||||
}
|
||||
int fontHeight = Math.round(cardHeight * (27f / 680));
|
||||
boolean showText = (!isAnimationPanel() && fontHeight < 12);
|
||||
|
||||
// TITLE
|
||||
|
||||
//old version - text hide on small fonts, why?
|
||||
//int fontHeight = Math.round(cardHeight * (26f / 672));
|
||||
//boolean showText = (!isAnimationPanel() && fontHeight < 12);
|
||||
|
||||
boolean showText = !isAnimationPanel() && canShowCardIcons(cardWidth, hasImage);
|
||||
titleText.setVisible(showText);
|
||||
ptText.setVisible(showText);
|
||||
fullImageText.setVisible(fullImagePath != null);
|
||||
|
||||
if (showText) {
|
||||
int fontSize = cardHeight / 11;
|
||||
int fontSize = cardHeight / 13; // startup font size (it same size on all zoom levels)
|
||||
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
|
||||
int titleX = Math.round(cardWidth * (20f / 480));
|
||||
int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset();
|
||||
titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY);
|
||||
// margins from card black border to text, not need? text show up good without margins
|
||||
int titleMarginLeft = 0; //Math.round(28f / 672f * cardWidth);
|
||||
int titleMarginRight = 0;
|
||||
int titleMarginTop = 0 + Math.round(getCardCaptionTopOffset() / 100f * cardHeight);//Math.round(28f / 936f * cardHeight);
|
||||
int titleMarginBottom = 0;
|
||||
titleText.setBounds(
|
||||
imagePanel.getX() + titleMarginLeft,
|
||||
imagePanel.getY() + titleMarginTop,
|
||||
imagePanel.getBounds().width - titleMarginLeft - titleMarginRight,
|
||||
imagePanel.getBounds().height - titleMarginTop - titleMarginBottom
|
||||
);
|
||||
|
||||
fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10));
|
||||
fullImageText.setBounds(cardXOffset, cardYOffset + titleY, cardWidth, cardHeight - titleY);
|
||||
fullImageText.setBounds(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
|
||||
|
||||
// life points location (font as title)
|
||||
ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
|
||||
Dimension ptSize = ptText.getPreferredSize();
|
||||
ptText.setSize(ptSize.width, ptSize.height);
|
||||
int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2;
|
||||
int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height;
|
||||
|
||||
int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f);
|
||||
// right bottom corner with margin (sizes from any sample card)
|
||||
int ptMarginRight = Math.round(64f / 672f * cardWidth);
|
||||
int ptMarginBottom = Math.round(62f / 936f * cardHeight);
|
||||
|
||||
ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
|
||||
int ptX = cardXOffset + cardWidth - ptMarginRight - ptSize.width;
|
||||
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptSize.height;
|
||||
ptText.setLocation(ptX, ptY);
|
||||
|
||||
// old version was with TEXT_GLOW_SIZE
|
||||
//ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,7 +648,7 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
final BufferedImage srcImage;
|
||||
if (gameCard.isFaceDown()) {
|
||||
srcImage = getFaceDownImage();
|
||||
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(gameCard);
|
||||
|
@ -581,7 +681,7 @@ public class CardPanelComponentImpl extends CardPanel {
|
|||
} else if (this.gameCard instanceof StackAbilityView) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||
return ImageCache.getCardbackImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.apache.log4j.Logger;
|
|||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import mage.client.constants.Constants;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
@ -21,8 +22,6 @@ import java.io.File;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
|
||||
|
||||
public class CardPanelRenderImpl extends CardPanel {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanelRenderImpl.class);
|
||||
|
@ -218,13 +217,15 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Map of generated images
|
||||
private final static Map<ImageKey, BufferedImage> IMAGE_CACHE = new MapMaker().softValues().makeMap();
|
||||
|
||||
// The art image for the card, loaded in from the disk
|
||||
private BufferedImage artImage;
|
||||
|
||||
// The faceart image for the card, loaded in from the disk (based on artid from mtgo)
|
||||
private BufferedImage faceArtImage;
|
||||
|
||||
// Factory to generate card appropriate views
|
||||
private CardRendererFactory cardRendererFactory = new CardRendererFactory();
|
||||
|
||||
|
@ -252,6 +253,8 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
// Use the art image and current rendered image from the card
|
||||
artImage = impl.artImage;
|
||||
cardRenderer.setArtImage(artImage);
|
||||
faceArtImage = impl.faceArtImage;
|
||||
cardRenderer.setFaceArtImage(faceArtImage);
|
||||
cardImage = impl.cardImage;
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +266,8 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
// Try to get card image from cache based on our card characteristics
|
||||
ImageKey key
|
||||
= new ImageKey(gameCard, artImage,
|
||||
getCardWidth(), getCardHeight(),
|
||||
isChoosable(), isSelected());
|
||||
getCardWidth(), getCardHeight(),
|
||||
isChoosable(), isSelected());
|
||||
cardImage = IMAGE_CACHE.computeIfAbsent(key, k -> renderCard());
|
||||
|
||||
// No cached copy exists? Render one and cache it
|
||||
|
@ -277,7 +280,6 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
/**
|
||||
* Create an appropriate card renderer for the
|
||||
*/
|
||||
|
||||
/**
|
||||
* Render the card to a new BufferedImage at it's current dimensions
|
||||
*
|
||||
|
@ -315,6 +317,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
artImage = null;
|
||||
cardImage = null;
|
||||
cardRenderer.setArtImage(null);
|
||||
cardRenderer.setFaceArtImage(null);
|
||||
|
||||
// Stop animation
|
||||
tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
|
||||
|
@ -332,19 +335,26 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
Util.threadPool.submit(() -> {
|
||||
try {
|
||||
final BufferedImage srcImage;
|
||||
final BufferedImage faceArtSrcImage;
|
||||
if (gameCard.isFaceDown()) {
|
||||
// Nothing to do
|
||||
srcImage = null;
|
||||
} else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) {
|
||||
faceArtSrcImage = null;
|
||||
} else if (getCardWidth() > Constants.THUMBNAIL_SIZE_FULL.width) {
|
||||
srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight());
|
||||
faceArtSrcImage = ImageCache.getFaceImage(gameCard, getCardWidth(), getCardHeight());
|
||||
} else {
|
||||
srcImage = ImageCache.getThumbnail(gameCard);
|
||||
faceArtSrcImage = ImageCache.getFaceImage(gameCard, getCardWidth(), getCardHeight());
|
||||
}
|
||||
|
||||
UI.invokeLater(() -> {
|
||||
if (stamp == updateArtImageStamp) {
|
||||
artImage = srcImage;
|
||||
cardRenderer.setArtImage(srcImage);
|
||||
faceArtImage = faceArtSrcImage;
|
||||
cardRenderer.setFaceArtImage(faceArtSrcImage);
|
||||
|
||||
if (srcImage != null) {
|
||||
// Invalidate and repaint
|
||||
cardImage = null;
|
||||
|
@ -370,6 +380,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
cardImage = null;
|
||||
cardRenderer = cardRendererFactory.create(gameCard, isTransformed());
|
||||
cardRenderer.setArtImage(artImage);
|
||||
cardRenderer.setFaceArtImage(faceArtImage);
|
||||
|
||||
// Repaint
|
||||
repaint();
|
||||
|
@ -398,7 +409,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
} else if (this.gameCard instanceof StackAbilityView) {
|
||||
return ImageCache.getMorphImage();
|
||||
} else {
|
||||
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||
return ImageCache.getCardbackImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,9 @@ public abstract class CardRenderer {
|
|||
// The card image
|
||||
protected BufferedImage artImage;
|
||||
|
||||
// The face card image
|
||||
protected BufferedImage faceArtImage;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Common layout metrics between all cards
|
||||
// Polygons for counters
|
||||
|
@ -289,8 +292,8 @@ public abstract class CardRenderer {
|
|||
try {
|
||||
BufferedImage subImg
|
||||
= artImage.getSubimage(
|
||||
(int) (artRect.getX() * fullCardImgWidth), (int) (artRect.getY() * fullCardImgHeight),
|
||||
(int) artWidth, (int) artHeight);
|
||||
(int) (artRect.getX() * fullCardImgWidth), (int) (artRect.getY() * fullCardImgHeight),
|
||||
(int) artWidth, (int) artHeight);
|
||||
g.drawImage(subImg,
|
||||
x, y,
|
||||
(int) targetWidth, (int) targetHeight,
|
||||
|
@ -300,6 +303,44 @@ public abstract class CardRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
protected void drawFaceArtIntoRect(Graphics2D g, int x, int y, int w, int h, Rectangle2D artRect, boolean shouldPreserveAspect) {
|
||||
// Perform a process to make sure that the art is scaled uniformly to fill the frame, cutting
|
||||
// off the minimum amount necessary to make it completely fill the frame without "squashing" it.
|
||||
double fullCardImgWidth = faceArtImage.getWidth();
|
||||
double fullCardImgHeight = faceArtImage.getHeight();
|
||||
double artWidth = fullCardImgWidth;
|
||||
double artHeight = fullCardImgHeight;
|
||||
double targetWidth = w;
|
||||
double targetHeight = h;
|
||||
double targetAspect = targetWidth / targetHeight;
|
||||
if (!shouldPreserveAspect) {
|
||||
// No adjustment to art
|
||||
} else if (targetAspect * artHeight < artWidth) {
|
||||
// Trim off some width
|
||||
artWidth = targetAspect * artHeight;
|
||||
} else {
|
||||
// Trim off some height
|
||||
artHeight = artWidth / targetAspect;
|
||||
}
|
||||
try {
|
||||
/*BufferedImage subImg
|
||||
= faceArtImage.getSubimage(
|
||||
(int) (artRect.getX() * fullCardImgWidth), (int) (artRect.getY() * fullCardImgHeight),
|
||||
(int) artWidth, (int) artHeight);*/
|
||||
RenderingHints rh = new RenderingHints(
|
||||
RenderingHints.KEY_INTERPOLATION,
|
||||
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
g.setRenderingHints(rh);
|
||||
g.drawImage(faceArtImage,
|
||||
x, y,
|
||||
(int) targetWidth, (int) targetHeight,
|
||||
null);
|
||||
} catch (RasterFormatException e) {
|
||||
// At very small card sizes we may encounter a problem with rounding error making the rect not fit
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw +1/+1 and other counters
|
||||
protected void drawCounters(Graphics2D g) {
|
||||
int xPos = (int) (0.65 * cardWidth);
|
||||
|
@ -442,4 +483,10 @@ public abstract class CardRenderer {
|
|||
public void setArtImage(Image image) {
|
||||
artImage = CardRendererUtils.toBufferedImage(image);
|
||||
}
|
||||
|
||||
// Set the card art image (CardPanel will give it to us when it
|
||||
// is loaded and ready)
|
||||
public void setFaceArtImage(Image image) {
|
||||
faceArtImage = CardRendererUtils.toBufferedImage(image);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ import java.util.regex.Pattern;
|
|||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
* <p>
|
||||
* Various static utilities for use in the card renderer
|
||||
* <p>
|
||||
* Various static utilities for use in the card renderer
|
||||
*/
|
||||
public final class CardRendererUtils {
|
||||
|
||||
|
@ -51,6 +51,38 @@ public final class CardRendererUtils {
|
|||
// Return the buffered image
|
||||
return bimage;
|
||||
}
|
||||
|
||||
private static Color abitbrighter(Color c) {
|
||||
int r = c.getRed();
|
||||
int g = c.getGreen();
|
||||
int b = c.getBlue();
|
||||
int alpha = c.getAlpha();
|
||||
|
||||
int plus_r = (int) ((255 - r) / 2);
|
||||
int plus_g = (int) ((255 - g) / 2);
|
||||
int plus_b = (int) ((255 - b) / 2);
|
||||
|
||||
return new Color(r + plus_r,
|
||||
g + plus_g,
|
||||
b + plus_b,
|
||||
alpha);
|
||||
}
|
||||
|
||||
private static Color abitdarker(Color c) {
|
||||
int r = c.getRed();
|
||||
int g = c.getGreen();
|
||||
int b = c.getBlue();
|
||||
int alpha = c.getAlpha();
|
||||
|
||||
int plus_r = (int) (Math.min (255 - r, r) / 2);
|
||||
int plus_g = (int) (Math.min (255 - g, g) / 2);
|
||||
int plus_b = (int) (Math.min (255 - b, b) / 2);
|
||||
|
||||
return new Color(r - plus_r,
|
||||
g - plus_g,
|
||||
b - plus_b,
|
||||
alpha);
|
||||
}
|
||||
|
||||
// Draw a rounded box with a 2-pixel border
|
||||
// Used on various card parts.
|
||||
|
@ -68,6 +100,12 @@ public final class CardRendererUtils {
|
|||
g.fillOval(x + 2, y + 2, bevel * 2 - 4, h - 4);
|
||||
g.fillOval(x + 2 + w - bevel * 2, y + 2, bevel * 2 - 4, h - 4);
|
||||
g.fillRect(x + bevel, y + 2, w - 2 * bevel, h - 4);
|
||||
g.setPaint(fill);
|
||||
g.setColor(abitbrighter(g.getColor()));
|
||||
g.drawLine(x + 1 + bevel, y + 1, x + 1 + bevel + w - 2 * bevel - 2, y + 1);
|
||||
g.setPaint(fill);
|
||||
g.setColor(abitdarker(g.getColor()));
|
||||
g.drawLine(x + 1 + bevel, y + h - 2, x + 1 + bevel + w - 2 * bevel - 2, y + h - 2);
|
||||
}
|
||||
|
||||
// Get the width of a mana cost rendered with ManaSymbols.draw
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.FilteredImageSource;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.RGBImageFilter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
|
@ -16,27 +18,37 @@ import java.nio.file.Paths;
|
|||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
|
||||
import mage.cards.repository.ExpansionRepository;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.BufferedImageBuilder;
|
||||
import org.apache.batik.dom.svg.SVGDOMImplementation;
|
||||
import org.apache.batik.transcoder.TranscoderException;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.TranscodingHints;
|
||||
import org.apache.batik.transcoder.image.ImageTranscoder;
|
||||
import org.apache.batik.util.SVGConstants;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.constants.Constants.ResourceSymbolSize;
|
||||
import mage.client.constants.Constants.ResourceSetSize;
|
||||
|
||||
import org.jdesktop.swingx.graphics.ShadowRenderer;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
||||
public final class ManaSymbols {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ManaSymbols.class);
|
||||
private static final Map<Integer, Map<String, BufferedImage>> manaImages = new HashMap<>();
|
||||
private static boolean smallSymbolsFound = false;
|
||||
private static boolean mediumSymbolsFound = false;
|
||||
|
||||
private static final Map<String, Map<String, Image>> setImages = new HashMap<>();
|
||||
|
||||
|
@ -63,11 +75,46 @@ public final class ManaSymbols {
|
|||
"BR", "G", "GU", "GW", "R", "RG", "RW", "S", "T", "U", "UB", "UR", "W", "WB", "WU",
|
||||
"WP", "UP", "BP", "RP", "GP", "X", "C", "E"};
|
||||
|
||||
public static void loadImages() {
|
||||
renameSymbols(getSymbolsPath() + File.separator + "symbols");
|
||||
smallSymbolsFound = loadSymbolsImages(15);
|
||||
mediumSymbolsFound = loadSymbolsImages(25);
|
||||
private static final JLabel labelRender = new JLabel(); // render mana text
|
||||
|
||||
public static void loadImages() {
|
||||
// TODO: delete files rename jpg->gif (it was for backward compatibility for one of the old version?)
|
||||
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.SMALL));
|
||||
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.MEDIUM));
|
||||
renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.LARGE));
|
||||
//renameSymbols(getSymbolsPath(ResourceSymbolSize.SVG)); // not need
|
||||
// TODO: remove medium sets files to "medium" folder like symbols above?
|
||||
|
||||
// preload symbol images
|
||||
loadSymbolImages(15);
|
||||
loadSymbolImages(25);
|
||||
loadSymbolImages(50);
|
||||
|
||||
// save symbol images in png for html replacement in texts
|
||||
// you can add bigger size for better quality
|
||||
Map<String, BufferedImage> pngImages = manaImages.get(50);
|
||||
if (pngImages != null){
|
||||
|
||||
File pngPath = new File(getResourceSymbolsPath(ResourceSymbolSize.PNG));
|
||||
if (!pngPath.exists()) {
|
||||
pngPath.mkdirs();
|
||||
}
|
||||
|
||||
for(String symbol: symbols){
|
||||
try
|
||||
{
|
||||
BufferedImage image = pngImages.get(symbol);
|
||||
if (image != null){
|
||||
File newFile = new File(pngPath.getPath() + File.separator + symbol + ".png");
|
||||
ImageIO.write(image, "png", newFile);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
LOGGER.warn("Can't generate png image for symbol:" + symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preload set images
|
||||
List<String> setCodes = ExpansionRepository.instance.getSetCodes();
|
||||
if (setCodes == null) {
|
||||
// the cards db file is probaly not included in the client. It will be created after the first connect to a server.
|
||||
|
@ -75,9 +122,11 @@ public final class ManaSymbols {
|
|||
return;
|
||||
}
|
||||
for (String set : setCodes) {
|
||||
|
||||
if (withoutSymbols.contains(set)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] codes;
|
||||
if (onlyMythics.contains(set)) {
|
||||
codes = new String[]{"M"};
|
||||
|
@ -88,8 +137,9 @@ public final class ManaSymbols {
|
|||
Map<String, Image> rarityImages = new HashMap<>();
|
||||
setImages.put(set, rarityImages);
|
||||
|
||||
// load medium size
|
||||
for (String rarityCode : codes) {
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + '-' + rarityCode + ".jpg");
|
||||
File file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + rarityCode + ".jpg");
|
||||
try {
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
int width = image.getWidth(null);
|
||||
|
@ -107,18 +157,19 @@ public final class ManaSymbols {
|
|||
}
|
||||
}
|
||||
|
||||
// generate small size
|
||||
try {
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
||||
File file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM));
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
for (String code : codes) {
|
||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL + set + '-' + code + ".png");
|
||||
file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + code + ".png");
|
||||
if (file.exists()) {
|
||||
continue;
|
||||
}
|
||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + '-' + code + ".jpg");
|
||||
file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + code + ".jpg");
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
try {
|
||||
int width = image.getWidth(null);
|
||||
|
@ -130,7 +181,7 @@ public final class ManaSymbols {
|
|||
}
|
||||
Rectangle r = new Rectangle(15 + dx, (int) (height * (15.0f + dx) / width));
|
||||
BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||
File newFile = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL + File.separator + set + '-' + code + ".png");
|
||||
File newFile = new File(getResourceSetsPath(ResourceSetSize.SMALL) + set + '-' + code + ".png");
|
||||
ImageIO.write(resized, "png", newFile);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -144,13 +195,15 @@ public final class ManaSymbols {
|
|||
}
|
||||
}
|
||||
|
||||
// mark loaded images
|
||||
// TODO: delete that code, images draw-show must dynamicly
|
||||
File file;
|
||||
for (String set : ExpansionRepository.instance.getSetCodes()) {
|
||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL);
|
||||
file = new File(getResourceSetsPath(ResourceSetSize.SMALL));
|
||||
if (!file.exists()) {
|
||||
break;
|
||||
}
|
||||
file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL + set + "-C.png");
|
||||
file = new File(getResourceSetsPath(ResourceSetSize.SMALL) + set + "-C.png");
|
||||
try {
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
int width = image.getWidth(null);
|
||||
|
@ -161,42 +214,250 @@ public final class ManaSymbols {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean loadSymbolsImages(int size) {
|
||||
boolean fileErrors = false;
|
||||
HashMap<String, BufferedImage> sizedSymbols = new HashMap<>();
|
||||
String resourcePath = Constants.RESOURCE_PATH_MANA_SMALL;
|
||||
if (size > 25) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_LARGE;
|
||||
} else if (size > 15) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_MEDIUM;
|
||||
}
|
||||
for (String symbol : symbols) {
|
||||
File file = new File(getSymbolsPath() + resourcePath + '/' + symbol + ".gif");
|
||||
try {
|
||||
public static BufferedImage loadSVG(File svgFile, int resizeToWidth, int resizeToHeight, boolean useShadow) throws IOException {
|
||||
|
||||
if (size == 15 || size == 25) {
|
||||
BufferedImage notResized = ImageIO.read(file);
|
||||
sizedSymbols.put(symbol, notResized);
|
||||
} else {
|
||||
Rectangle r = new Rectangle(size, size);
|
||||
//Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
BufferedImage image = ImageIO.read(file);
|
||||
//BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
|
||||
if (image != null) {
|
||||
BufferedImage resized = ImageHelper.getResizedImage(image, r);
|
||||
sizedSymbols.put(symbol, resized);
|
||||
}
|
||||
// debug: disable shadow gen, need to test it
|
||||
useShadow = false;
|
||||
|
||||
// load SVG image
|
||||
// base loader code: https://stackoverflow.com/questions/11435671/how-to-get-a-buffererimage-from-a-svg
|
||||
// resize code: https://vibranttechie.wordpress.com/2015/05/15/svg-loading-to-javafx-stage-and-auto-scaling-when-stage-resize/
|
||||
|
||||
if (useShadow && ((resizeToWidth <= 0) || (resizeToHeight <= 0))){
|
||||
throw new IllegalArgumentException("Must use non zero sizes for shadow.");
|
||||
}
|
||||
|
||||
final BufferedImage[] imagePointer = new BufferedImage[1];
|
||||
|
||||
// Rendering hints can't be set programatically, so
|
||||
// we override defaults with a temporary stylesheet.
|
||||
// These defaults emphasize quality and precision, and
|
||||
// are more similar to the defaults of other SVG viewers.
|
||||
// SVG documents can still override these defaults.
|
||||
String css = "svg {" +
|
||||
"shape-rendering: geometricPrecision;" +
|
||||
"text-rendering: geometricPrecision;" +
|
||||
"color-rendering: optimizeQuality;" +
|
||||
"image-rendering: optimizeQuality;" +
|
||||
"}";
|
||||
File cssFile = File.createTempFile("batik-default-override-", ".css");
|
||||
FileWriter w = new FileWriter(cssFile);
|
||||
w.write(css);
|
||||
w.close();
|
||||
|
||||
TranscodingHints transcoderHints = new TranscodingHints();
|
||||
|
||||
// resize
|
||||
int shadowX = 0;
|
||||
int shadowY = 0;
|
||||
if(useShadow) {
|
||||
// shadow size (16px image: 1px left, 2px bottom)
|
||||
shadowX = 1 * Math.round(1f / 16f * resizeToWidth);
|
||||
shadowY = 2 * Math.round(1f / 16f * resizeToHeight);
|
||||
resizeToWidth = resizeToWidth - shadowX;
|
||||
resizeToHeight = resizeToHeight - shadowY;
|
||||
};
|
||||
|
||||
if(resizeToWidth > 0){
|
||||
transcoderHints.put(ImageTranscoder.KEY_WIDTH, (float)resizeToWidth); //your image width
|
||||
}
|
||||
if(resizeToHeight > 0){
|
||||
transcoderHints.put(ImageTranscoder.KEY_HEIGHT, (float)resizeToHeight); //your image height
|
||||
}
|
||||
|
||||
transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
|
||||
transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
|
||||
SVGDOMImplementation.getDOMImplementation());
|
||||
transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
|
||||
SVGConstants.SVG_NAMESPACE_URI);
|
||||
transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
|
||||
transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
|
||||
|
||||
try {
|
||||
TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));
|
||||
|
||||
ImageTranscoder t = new ImageTranscoder() {
|
||||
|
||||
@Override
|
||||
public BufferedImage createImage(int w, int h) {
|
||||
return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Error for symbol:" + symbol);
|
||||
|
||||
@Override
|
||||
public void writeImage(BufferedImage image, TranscoderOutput out)
|
||||
throws TranscoderException {
|
||||
imagePointer[0] = image;
|
||||
}
|
||||
};
|
||||
t.setTranscodingHints(transcoderHints);
|
||||
t.transcode(input, null);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Couldn't convert svg file: " + svgFile + " , reason: " + e.getMessage());
|
||||
}
|
||||
finally {
|
||||
cssFile.delete();
|
||||
}
|
||||
|
||||
BufferedImage originImage = imagePointer[0];
|
||||
|
||||
if(useShadow && (originImage.getWidth() > 0)){
|
||||
// draw shadow
|
||||
// origin image was reduces in sizes to fit shadow
|
||||
// see https://stackoverflow.com/a/40833715/1276632
|
||||
|
||||
// a filter which converts all colors except 0 to black
|
||||
ImageProducer prod = new FilteredImageSource(originImage.getSource(), new RGBImageFilter() {
|
||||
@Override
|
||||
public int filterRGB(int x, int y, int rgb) {
|
||||
if (rgb == 0)
|
||||
return 0;
|
||||
else
|
||||
return 0xff000000;
|
||||
}
|
||||
});
|
||||
// create whe black image
|
||||
Image shadow = Toolkit.getDefaultToolkit().createImage(prod);
|
||||
// result
|
||||
BufferedImage result = new BufferedImage(originImage.getWidth() + shadowX, originImage.getHeight() + shadowY, originImage.getType());
|
||||
Graphics2D g = (Graphics2D) result.getGraphics();
|
||||
// draw shadow with offset (left bottom)
|
||||
g.drawImage(shadow, -1 * shadowX, shadowY, null);
|
||||
// draw original image
|
||||
g.drawImage(originImage, 0, 0, null);
|
||||
return result;
|
||||
}else{
|
||||
// return origin image without shadow
|
||||
return originImage;
|
||||
}
|
||||
|
||||
/*
|
||||
BufferedImage base = GraphicsUtilities.createCompatibleTranslucentImage(w, h);
|
||||
Graphics2D g2 = base.createGraphics();
|
||||
g2.setColor(Color.WHITE);
|
||||
g2.fillRoundRect(0, 0, image.getWidth(), image.getHeight(), 10, 10);
|
||||
g2.dispose();
|
||||
|
||||
ShadowRenderer renderer = new ShadowRenderer(shadowSize, 0.5f,
|
||||
Color.GRAY);
|
||||
return renderer.createShadow(base);
|
||||
*/
|
||||
|
||||
//imagePointer[0];
|
||||
}
|
||||
|
||||
public static File getSymbolFileNameAsSVG(String symbol){
|
||||
return new File(getResourceSymbolsPath(ResourceSymbolSize.SVG) + symbol + ".svg");
|
||||
}
|
||||
|
||||
private static BufferedImage loadSymbolAsSVG(String symbol, int resizeToWidth, int resizeToHeight){
|
||||
|
||||
File sourceFile = getSymbolFileNameAsSVG(symbol);
|
||||
return loadSymbolAsSVG(sourceFile, resizeToWidth, resizeToHeight);
|
||||
}
|
||||
|
||||
private static BufferedImage loadSymbolAsSVG(File sourceFile, int resizeToWidth, int resizeToHeight){
|
||||
try{
|
||||
// no need to resize svg (lib already do it on load)
|
||||
return loadSVG(sourceFile, resizeToWidth, resizeToHeight, true);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Can't load svg symbol: " + sourceFile.getPath() + " , reason: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static File getSymbolFileNameAsGIF(String symbol, int size){
|
||||
|
||||
ResourceSymbolSize needSize = null;
|
||||
if (size <= 15){
|
||||
needSize = ResourceSymbolSize.SMALL;
|
||||
}else if (size <= 25){
|
||||
needSize = ResourceSymbolSize.MEDIUM;
|
||||
} else {
|
||||
needSize = ResourceSymbolSize.LARGE;
|
||||
}
|
||||
|
||||
return new File(getResourceSymbolsPath(needSize) + symbol + ".gif");
|
||||
}
|
||||
|
||||
private static BufferedImage loadSymbolAsGIF(String symbol, int resizeToWidth, int resizeToHeight){
|
||||
File file = getSymbolFileNameAsGIF(symbol, resizeToWidth);
|
||||
return loadSymbolAsGIF(file, resizeToWidth, resizeToHeight);
|
||||
}
|
||||
|
||||
private static BufferedImage loadSymbolAsGIF(File sourceFile, int resizeToWidth, int resizeToHeight){
|
||||
|
||||
BufferedImage image = null;
|
||||
|
||||
try {
|
||||
if ((resizeToWidth == 15) || (resizeToWidth == 25)){
|
||||
// normal size
|
||||
image = ImageIO.read(sourceFile);
|
||||
}else{
|
||||
// resize size
|
||||
image = ImageIO.read(sourceFile);
|
||||
|
||||
if (image != null) {
|
||||
Rectangle r = new Rectangle(resizeToWidth, resizeToHeight);
|
||||
image = ImageHelper.getResizedImage(image, r);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Can't load gif symbol: " + sourceFile.getPath());
|
||||
return null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private static boolean loadSymbolImages(int size) {
|
||||
// load all symbols to cash
|
||||
// priority: SVG -> GIF
|
||||
// gif remain for backward compatibility
|
||||
|
||||
boolean fileErrors = false;
|
||||
|
||||
HashMap<String, BufferedImage> sizedSymbols = new HashMap<>();
|
||||
for (String symbol : symbols) {
|
||||
|
||||
BufferedImage image = null;
|
||||
File file = null;
|
||||
|
||||
// svg
|
||||
file = getSymbolFileNameAsSVG(symbol);
|
||||
if (file.exists()) {
|
||||
image = loadSymbolAsSVG(file, size, size);
|
||||
}
|
||||
|
||||
// gif
|
||||
if (image == null) {
|
||||
//LOGGER.info("SVG symbol can't be load: " + file.getPath());
|
||||
|
||||
file = getSymbolFileNameAsGIF(symbol, size);
|
||||
if (file.exists()) {
|
||||
image = loadSymbolAsGIF(file, size, size);
|
||||
}
|
||||
}
|
||||
|
||||
// save
|
||||
if (image != null) {
|
||||
sizedSymbols.put(symbol, image);
|
||||
} else {
|
||||
fileErrors = true;
|
||||
LOGGER.warn("SVG or GIF symbol can't be load: " + symbol);
|
||||
}
|
||||
}
|
||||
|
||||
manaImages.put(size, sizedSymbols);
|
||||
return !fileErrors;
|
||||
}
|
||||
|
||||
private static void renameSymbols(String path) {
|
||||
File file = new File(path);
|
||||
if (!file.exists()){
|
||||
return;
|
||||
}
|
||||
|
||||
final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.jpg");
|
||||
try {
|
||||
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>() {
|
||||
|
@ -210,60 +471,184 @@ public final class ManaSymbols {
|
|||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Couldn't rename mana symbols!");
|
||||
LOGGER.error("Couldn't rename mana symbols on " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSymbolsPath() {
|
||||
return getSymbolsPath(false);
|
||||
private static String getResourceSymbolsPath(ResourceSymbolSize needSize){
|
||||
// return real path to symbols (default or user defined)
|
||||
|
||||
String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator;
|
||||
|
||||
// folder by sizes
|
||||
switch (needSize) {
|
||||
case SMALL:
|
||||
path = path + Constants.RESOURCE_SYMBOL_FOLDER_SMALL;
|
||||
break;
|
||||
case MEDIUM:
|
||||
path = path + Constants.RESOURCE_SYMBOL_FOLDER_MEDIUM;
|
||||
break;
|
||||
case LARGE:
|
||||
path = path + Constants.RESOURCE_SYMBOL_FOLDER_LARGE;
|
||||
break;
|
||||
case SVG:
|
||||
path = path + Constants.RESOURCE_SYMBOL_FOLDER_SVG;
|
||||
break;
|
||||
case PNG:
|
||||
path = path + Constants.RESOURCE_SYMBOL_FOLDER_PNG;
|
||||
break;
|
||||
default:
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"ResourceSymbolSize value is unknown");
|
||||
}
|
||||
|
||||
// fix double separator if size folder is not set
|
||||
while(path.endsWith(File.separator))
|
||||
{
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
|
||||
return path + File.separator;
|
||||
}
|
||||
|
||||
private static String getSymbolsPath(boolean forHtmlCode) {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String path = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
if (path == null) {
|
||||
if (forHtmlCode) {
|
||||
// for html code we need to use double '//' symbols
|
||||
// and seems it should be hard coded - as it is not the same as using File.separator
|
||||
return "plugins/images/";
|
||||
} else {
|
||||
return mage.client.constants.Constants.IO.imageBaseDir;
|
||||
}
|
||||
private static String getResourceSetsPath(ResourceSetSize needSize){
|
||||
// return real path to sets icons (default or user defined)
|
||||
|
||||
String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator;
|
||||
|
||||
// folder by sizes
|
||||
switch (needSize) {
|
||||
case SMALL:
|
||||
path = path + Constants.RESOURCE_SET_FOLDER_SMALL;
|
||||
break;
|
||||
case MEDIUM:
|
||||
path = path + Constants.RESOURCE_SET_FOLDER_MEDIUM;
|
||||
break;
|
||||
case SVG:
|
||||
path = path + Constants.RESOURCE_SET_FOLDER_SVG;
|
||||
break;
|
||||
default:
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"ResourceSetSize value is unknown");
|
||||
}
|
||||
if (forHtmlCode) {
|
||||
if (cachedPath != null) {
|
||||
return cachedPath;
|
||||
}
|
||||
if (path.contains("\\")) {
|
||||
cachedPath = path.replaceAll("[\\\\]", "/");
|
||||
return cachedPath;
|
||||
}
|
||||
|
||||
// fix double separator if size folder is not set
|
||||
while(path.endsWith(File.separator))
|
||||
{
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
return path;
|
||||
|
||||
return path + File.separator;
|
||||
}
|
||||
|
||||
public static void draw(Graphics g, String manaCost, int x, int y, int symbolWidth) {
|
||||
draw(g, manaCost, x, y, symbolWidth, Color.white, 0);
|
||||
}
|
||||
|
||||
public static void draw(Graphics g, String manaCost, int x, int y, int symbolWidth, Color symbolsTextColor, int symbolMarginX) {
|
||||
if (!manaImages.containsKey(symbolWidth)) {
|
||||
loadSymbolsImages(symbolWidth);
|
||||
loadSymbolImages(symbolWidth);
|
||||
}
|
||||
|
||||
// TODO: replace with jlabel render (look at table rendere)?
|
||||
|
||||
/*
|
||||
// NEW version with component draw
|
||||
JPanel manaPanel = new JPanel();
|
||||
|
||||
// icons size with margin
|
||||
int symbolHorizontalMargin = 2;
|
||||
|
||||
// create each mana symbol as child label
|
||||
manaPanel.removeAll();
|
||||
manaPanel.setLayout(new BoxLayout(manaPanel, BoxLayout.X_AXIS));
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String symbol = tok.nextToken();
|
||||
|
||||
JLabel symbolLabel = new JLabel();
|
||||
//symbolLabel.setBorder(new LineBorder(new Color(150, 150, 150))); // debug
|
||||
symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin,0, 0));
|
||||
|
||||
BufferedImage image = ManaSymbols.getSizedManaSymbol(symbol, symbolWidth);
|
||||
if (image != null){
|
||||
// icon
|
||||
symbolLabel.setIcon(new ImageIcon(image));
|
||||
}else
|
||||
{
|
||||
// text
|
||||
symbolLabel.setText("{" + symbol + "}");
|
||||
//symbolLabel.setOpaque(baseLabel.isOpaque());
|
||||
//symbolLabel.setForeground(baseLabel.getForeground());
|
||||
//symbolLabel.setBackground(baseLabel.getBackground());
|
||||
}
|
||||
|
||||
manaPanel.add(symbolLabel);
|
||||
}
|
||||
|
||||
// draw result
|
||||
Dimension d = manaPanel.getPreferredSize();
|
||||
BufferedImage image = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D gg = image.createGraphics();
|
||||
manaPanel.paint(gg);
|
||||
g.drawImage(image, x, y, null);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// OLD version with custom draw
|
||||
Map<String, BufferedImage> sizedSymbols = manaImages.get(symbolWidth);
|
||||
if (manaCost.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
manaCost = manaCost.replace("\\", "");
|
||||
manaCost = UI.getDisplayManaCost(manaCost);
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String symbol = tok.nextToken();
|
||||
// Check and load symbol in the width
|
||||
Image image = sizedSymbols.get(symbol);
|
||||
|
||||
if (image == null) {
|
||||
//log.error("Symbol not recognized \"" + symbol + "\" in mana cost: " + manaCost);
|
||||
continue;
|
||||
// TEXT draw
|
||||
|
||||
labelRender.setText("{" + symbol + "}");
|
||||
labelRender.setForeground(symbolsTextColor);
|
||||
labelRender.setSize(symbolWidth, symbolWidth);
|
||||
labelRender.setVerticalAlignment(SwingConstants.CENTER);
|
||||
labelRender.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
//labelRender.setBorder(new LineBorder(new Color(125, 250, 250), 1));
|
||||
|
||||
// fix font size for mana text
|
||||
// work for labels WITHOUT borders
|
||||
// https://stackoverflow.com/questions/2715118/how-to-change-the-size-of-the-font-of-a-jlabel-to-take-the-maximum-size
|
||||
Font labelFont = labelRender.getFont();
|
||||
String labelText = "{W}"; //labelRender.getText(); // need same font size for all -- use max symbol ever, not current text
|
||||
int stringWidth = labelRender.getFontMetrics(labelFont).stringWidth(labelText);
|
||||
int componentWidth = labelRender.getWidth();
|
||||
// Find out how much the font can grow in width.
|
||||
double widthRatio = (double)componentWidth / (double)stringWidth;
|
||||
int newFontSize = (int)(labelFont.getSize() * widthRatio);
|
||||
int componentHeight = labelRender.getHeight();
|
||||
// Pick a new font size so it will not be larger than the height of label.
|
||||
int fontSizeToUse = Math.min(newFontSize, componentHeight);
|
||||
// Set the label's font size to the newly determined size.
|
||||
labelRender.setFont(new Font(labelFont.getName(), Font.PLAIN + Font.BOLD, fontSizeToUse - 1)); // - for "..." fix in text
|
||||
|
||||
// render component to new position
|
||||
// need to copy graphics, overvise it draw at top left corner
|
||||
// https://stackoverflow.com/questions/4974268/java-paint-problem
|
||||
Graphics2D labelG = (Graphics2D)g.create(x, y, symbolWidth, symbolWidth);
|
||||
labelG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
labelG.fillOval(x + 1, y + 1, symbolWidth - 2, symbolWidth - 2);
|
||||
labelRender.paint(labelG);
|
||||
}else {
|
||||
// ICON draw
|
||||
g.drawImage(image, x, y, null);
|
||||
}
|
||||
g.drawImage(image, x, y, null);
|
||||
x += symbolWidth;
|
||||
x += symbolWidth + symbolMarginX;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getStringManaCost(List<String> manaCost) {
|
||||
|
@ -281,11 +666,21 @@ public final class ManaSymbols {
|
|||
TOOLTIP,
|
||||
}
|
||||
|
||||
private static String filePathToUrl(String path){
|
||||
// convert file path to uri path (for html docs)
|
||||
if((path != null) && (!path.equals(""))){
|
||||
File file = new File(path);
|
||||
return file.toURI().toString();
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized String replaceSymbolsWithHTML(String value, Type type) {
|
||||
value = value.replace("{source}", "|source|");
|
||||
value = value.replace("{this}", "|this|");
|
||||
String replaced = value;
|
||||
boolean symbolFilesFound;
|
||||
|
||||
// mana cost to HTML images (urls to files)
|
||||
// do not use it for new code - try to suppotr svg render
|
||||
|
||||
int symbolSize;
|
||||
switch (type) {
|
||||
case TABLE:
|
||||
|
@ -304,21 +699,41 @@ public final class ManaSymbols {
|
|||
symbolSize = 11;
|
||||
break;
|
||||
}
|
||||
String resourcePath = "small";
|
||||
symbolFilesFound = smallSymbolsFound;
|
||||
if (symbolSize > 25) {
|
||||
resourcePath = "large";
|
||||
} else if (symbolSize > 15) {
|
||||
resourcePath = "medium";
|
||||
symbolFilesFound = mediumSymbolsFound;
|
||||
|
||||
// auto size
|
||||
ResourceSymbolSize needSize = null;
|
||||
if (symbolSize <= 15){
|
||||
needSize = ResourceSymbolSize.SMALL;
|
||||
}else if (symbolSize <= 25){
|
||||
needSize = ResourceSymbolSize.MEDIUM;
|
||||
} else {
|
||||
needSize = ResourceSymbolSize.LARGE;
|
||||
}
|
||||
if (symbolFilesFound) {
|
||||
replaced = REPLACE_SYMBOLS_PATTERN.matcher(value).replaceAll(
|
||||
"<img src='file:" + getSymbolsPath(true) + "/symbols/" + resourcePath + "/$1$2.gif' alt='$1$2' width=" + symbolSize
|
||||
+ " height=" + symbolSize + '>');
|
||||
}
|
||||
replaced = replaced.replace("|source|", "{source}");
|
||||
replaced = replaced.replace("|this|", "{this}");
|
||||
|
||||
// replace every {symbol} to <img> link
|
||||
|
||||
// ignore data backup
|
||||
String replaced = value
|
||||
.replace("{source}", "|source|")
|
||||
.replace("{this}", "|this|");
|
||||
|
||||
|
||||
// not need to add different images (width and height do the work)
|
||||
// use best png size (generated on startup) TODO: add reload images after update
|
||||
String htmlImagesPath = getResourceSymbolsPath(ResourceSymbolSize.PNG);
|
||||
htmlImagesPath = htmlImagesPath
|
||||
.replace("$", "@S@"); // paths with $ will rise error, need escape that
|
||||
|
||||
replaced = REPLACE_SYMBOLS_PATTERN.matcher(replaced).replaceAll(
|
||||
"<img src='" + filePathToUrl(htmlImagesPath) + "$1$2" + ".png' alt='$1$2' width="
|
||||
+ symbolSize + " height=" + symbolSize + '>');
|
||||
|
||||
// ignore data restore
|
||||
replaced = replaced
|
||||
.replace("|source|", "{source}")
|
||||
.replace("|this|", "{this}")
|
||||
.replace("@S@", "$");
|
||||
|
||||
return replaced;
|
||||
}
|
||||
|
||||
|
@ -328,7 +743,7 @@ public final class ManaSymbols {
|
|||
int factor = size / 15 + 1;
|
||||
Integer width = setImagesExist.get(_set).width * factor;
|
||||
Integer height = setImagesExist.get(_set).height * factor;
|
||||
return "<img src='file:" + getSymbolsPath() + "/sets/small/" + _set + '-' + rarity + ".png' alt='" + rarity + "' height='" + height + "' width='" + width + "' >";
|
||||
return "<img src='" + filePathToUrl(getResourceSetsPath(ResourceSetSize.SMALL)) + _set + '-' + rarity + ".png' alt='" + rarity + "' height='" + height + "' width='" + width + "' >";
|
||||
} else {
|
||||
return set;
|
||||
}
|
||||
|
@ -353,9 +768,10 @@ public final class ManaSymbols {
|
|||
|
||||
public static BufferedImage getSizedManaSymbol(String symbol, int size) {
|
||||
if (!manaImages.containsKey(size)) {
|
||||
loadSymbolsImages(size);
|
||||
loadSymbolImages(size);
|
||||
}
|
||||
Map<String, BufferedImage> sizedSymbols = manaImages.get(size);
|
||||
return sizedSymbols.get(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import mage.client.util.GUISizeHelper;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
// base panel to render
|
||||
private JPanel manaPanel = new JPanel();
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int column) {
|
||||
|
||||
// get table text cell settings
|
||||
DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class);
|
||||
JLabel baseLabel = (JLabel)baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
// apply settings to mana panel from parent
|
||||
manaPanel.setOpaque(baseLabel.isOpaque());
|
||||
manaPanel.setForeground(baseLabel.getForeground());
|
||||
manaPanel.setBackground(baseLabel.getBackground());
|
||||
|
||||
// icons size with margin
|
||||
int symbolWidth = GUISizeHelper.symbolTableSize;
|
||||
int symbolHorizontalMargin = 2;
|
||||
|
||||
// create each mana symbol as child label
|
||||
String manaCost = (String)value;
|
||||
manaPanel.removeAll();
|
||||
manaPanel.setLayout(new BoxLayout(manaPanel, BoxLayout.X_AXIS));
|
||||
if(manaCost != null){
|
||||
StringTokenizer tok = new StringTokenizer(manaCost, " ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String symbol = tok.nextToken();
|
||||
|
||||
JLabel symbolLabel = new JLabel();
|
||||
//symbolLabel.setBorder(new LineBorder(new Color(150, 150, 150))); // debug
|
||||
symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin,0, 0));
|
||||
|
||||
BufferedImage image = ManaSymbols.getSizedManaSymbol(symbol, symbolWidth);
|
||||
if (image != null){
|
||||
// icon
|
||||
symbolLabel.setIcon(new ImageIcon(image));
|
||||
}else
|
||||
{
|
||||
// text
|
||||
symbolLabel.setText("{" + symbol + "}");
|
||||
symbolLabel.setOpaque(baseLabel.isOpaque());
|
||||
symbolLabel.setForeground(baseLabel.getForeground());
|
||||
symbolLabel.setBackground(baseLabel.getBackground());
|
||||
}
|
||||
|
||||
manaPanel.add(symbolLabel);
|
||||
}
|
||||
}
|
||||
|
||||
return manaPanel;
|
||||
}
|
||||
}
|
|
@ -5,19 +5,6 @@
|
|||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.cards.ArtRect;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.MageObjectType;
|
||||
import mage.constants.SubType;
|
||||
import mage.util.SubTypeList;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PermanentView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.font.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
@ -31,6 +18,18 @@ import java.text.CharacterIterator;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import mage.ObjectColor;
|
||||
import mage.cards.ArtRect;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.MageObjectType;
|
||||
import mage.constants.SubType;
|
||||
import mage.util.SubTypeList;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PermanentView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -77,9 +76,9 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
}
|
||||
|
||||
private static Font loadFont(String name) {
|
||||
try(InputStream in = ModernCardRenderer.class.getResourceAsStream("/cardrender/" + name + ".ttf")) {
|
||||
try (InputStream in = ModernCardRenderer.class.getResourceAsStream("/cardrender/" + name + ".ttf")) {
|
||||
return Font.createFont(
|
||||
Font.TRUETYPE_FONT,in);
|
||||
Font.TRUETYPE_FONT, in);
|
||||
} catch (IOException e) {
|
||||
LOGGER.info("Failed to load font `" + name + "`, couldn't find resource.");
|
||||
} catch (FontFormatException e) {
|
||||
|
@ -107,7 +106,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
public static final Color BORDER_RED = new Color(201, 71, 58);
|
||||
public static final Color BORDER_GREEN = new Color(4, 136, 69);
|
||||
public static final Color BORDER_GOLD = new Color(255, 228, 124);
|
||||
public static final Color BORDER_COLORLESS = new Color(238, 242, 242);
|
||||
public static final Color BORDER_COLORLESS = new Color(208, 212, 212);
|
||||
public static final Color BORDER_LAND = new Color(190, 173, 115);
|
||||
|
||||
public static final Color BOX_WHITE = new Color(244, 245, 239);
|
||||
|
@ -116,7 +115,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
public static final Color BOX_RED = new Color(246, 208, 185);
|
||||
public static final Color BOX_GREEN = new Color(205, 221, 213);
|
||||
public static final Color BOX_GOLD = new Color(223, 195, 136);
|
||||
public static final Color BOX_COLORLESS = new Color(220, 228, 232);
|
||||
public static final Color BOX_COLORLESS = new Color(200, 208, 212);
|
||||
public static final Color BOX_LAND = new Color(220, 215, 213);
|
||||
public static final Color BOX_INVENTION = new Color(209, 97, 33);
|
||||
public static final Color BOX_VEHICLE = new Color(155, 105, 60);
|
||||
|
@ -129,21 +128,21 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
public static final Color BOX_GOLD_NIGHT = new Color(171, 134, 70);
|
||||
public static final Color BOX_COLORLESS_NIGHT = new Color(118, 147, 158);
|
||||
|
||||
public static final Color LAND_TEXTBOX_WHITE = new Color(248, 232, 188, 244);
|
||||
public static final Color LAND_TEXTBOX_BLUE = new Color(189, 212, 236, 244);
|
||||
public static final Color LAND_TEXTBOX_BLACK = new Color(174, 164, 162, 244);
|
||||
public static final Color LAND_TEXTBOX_RED = new Color(242, 168, 133, 244);
|
||||
public static final Color LAND_TEXTBOX_GREEN = new Color(198, 220, 198, 244);
|
||||
public static final Color LAND_TEXTBOX_GOLD = new Color(236, 229, 207, 244);
|
||||
public static final Color LAND_TEXTBOX_WHITE = new Color(248, 232, 188, 234);
|
||||
public static final Color LAND_TEXTBOX_BLUE = new Color(189, 212, 236, 234);
|
||||
public static final Color LAND_TEXTBOX_BLACK = new Color(174, 164, 162, 234);
|
||||
public static final Color LAND_TEXTBOX_RED = new Color(242, 168, 133, 234);
|
||||
public static final Color LAND_TEXTBOX_GREEN = new Color(198, 220, 198, 234);
|
||||
public static final Color LAND_TEXTBOX_GOLD = new Color(236, 229, 207, 234);
|
||||
|
||||
public static final Color TEXTBOX_WHITE = new Color(252, 249, 244, 244);
|
||||
public static final Color TEXTBOX_BLUE = new Color(229, 238, 247, 244);
|
||||
public static final Color TEXTBOX_BLACK = new Color(241, 241, 240, 244);
|
||||
public static final Color TEXTBOX_RED = new Color(243, 224, 217, 244);
|
||||
public static final Color TEXTBOX_GREEN = new Color(217, 232, 223, 244);
|
||||
public static final Color TEXTBOX_GOLD = new Color(240, 234, 209, 244);
|
||||
public static final Color TEXTBOX_COLORLESS = new Color(219, 229, 233, 244);
|
||||
public static final Color TEXTBOX_LAND = new Color(218, 214, 212, 244);
|
||||
public static final Color TEXTBOX_WHITE = new Color(252, 249, 244, 234);
|
||||
public static final Color TEXTBOX_BLUE = new Color(229, 238, 247, 234);
|
||||
public static final Color TEXTBOX_BLACK = new Color(241, 241, 240, 234);
|
||||
public static final Color TEXTBOX_RED = new Color(243, 224, 217, 234);
|
||||
public static final Color TEXTBOX_GREEN = new Color(217, 232, 223, 234);
|
||||
public static final Color TEXTBOX_GOLD = new Color(240, 234, 209, 234);
|
||||
public static final Color TEXTBOX_COLORLESS = new Color(199, 209, 213, 234);
|
||||
public static final Color TEXTBOX_LAND = new Color(218, 214, 212, 234);
|
||||
|
||||
public static final Color ERROR_COLOR = new Color(255, 0, 255);
|
||||
|
||||
|
@ -280,6 +279,8 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Just draw a brown rectangle
|
||||
drawCardBack(g);
|
||||
} else {
|
||||
BufferedImage bufferedImage = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// Set texture to paint with
|
||||
g.setPaint(getBackgroundPaint(cardView.getColor(), cardView.getCardTypes(), cardView.getSubTypes()));
|
||||
|
||||
|
@ -349,11 +350,18 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
@Override
|
||||
protected void drawArt(Graphics2D g) {
|
||||
if (artImage != null && !cardView.isFaceDown()) {
|
||||
|
||||
boolean useFaceArt = false;
|
||||
if (faceArtImage != null) {
|
||||
useFaceArt = true;
|
||||
}
|
||||
|
||||
// Invention rendering, art fills the entire frame
|
||||
if (useInventionFrame()) {
|
||||
useFaceArt = false;
|
||||
drawArtIntoRect(g,
|
||||
borderWidth, borderWidth,
|
||||
cardWidth - 2*borderWidth, cardHeight - 2*borderWidth,
|
||||
cardWidth - 2 * borderWidth, cardHeight - 2 * borderWidth,
|
||||
getArtRect(), false);
|
||||
}
|
||||
|
||||
|
@ -361,17 +369,18 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
Rectangle2D sourceRect = getArtRect();
|
||||
|
||||
if (cardView.getMageObjectType() == MageObjectType.SPELL) {
|
||||
useFaceArt = false;
|
||||
ArtRect rect = cardView.getArtRect();
|
||||
if (rect == ArtRect.SPLIT_FUSED) {
|
||||
// Special handling for fused, draw the art from both halves stacked on top of one and other
|
||||
// each filling half of the art rect
|
||||
drawArtIntoRect(g,
|
||||
totalContentInset + 1, totalContentInset + boxHeight,
|
||||
contentWidth - 2, (typeLineY - totalContentInset - boxHeight)/2,
|
||||
contentWidth - 2, (typeLineY - totalContentInset - boxHeight) / 2,
|
||||
ArtRect.SPLIT_LEFT.rect, useInventionFrame());
|
||||
drawArtIntoRect(g,
|
||||
totalContentInset + 1, totalContentInset + boxHeight + (typeLineY - totalContentInset - boxHeight)/2,
|
||||
contentWidth - 2, (typeLineY - totalContentInset - boxHeight)/2,
|
||||
totalContentInset + 1, totalContentInset + boxHeight + (typeLineY - totalContentInset - boxHeight) / 2,
|
||||
contentWidth - 2, (typeLineY - totalContentInset - boxHeight) / 2,
|
||||
ArtRect.SPLIT_RIGHT.rect, useInventionFrame());
|
||||
return;
|
||||
} else if (rect != ArtRect.NORMAL) {
|
||||
|
@ -381,10 +390,17 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
}
|
||||
|
||||
// Normal drawing of art from a source part of the card frame into the rect
|
||||
drawArtIntoRect(g,
|
||||
totalContentInset + 1, totalContentInset + boxHeight,
|
||||
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
|
||||
sourceRect, shouldPreserveAspect);
|
||||
if (useFaceArt) {
|
||||
drawFaceArtIntoRect(g,
|
||||
totalContentInset + 1, totalContentInset + boxHeight,
|
||||
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
|
||||
sourceRect, shouldPreserveAspect);
|
||||
} else {
|
||||
drawArtIntoRect(g,
|
||||
totalContentInset + 1, totalContentInset + boxHeight,
|
||||
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
|
||||
sourceRect, shouldPreserveAspect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,6 +437,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setPaint(new Color(255, 255, 255, 150));
|
||||
} else {
|
||||
g.setPaint(textboxPaint);
|
||||
|
||||
}
|
||||
g.fillRect(
|
||||
totalContentInset + 1, typeLineY,
|
||||
|
@ -477,6 +494,9 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Draw the transform circle
|
||||
int nameOffset = drawTransformationCircle(g, borderPaint);
|
||||
|
||||
// Draw the transform circle
|
||||
nameOffset = drawTransformationCircle(g, borderPaint);
|
||||
|
||||
// Draw the name line
|
||||
drawNameLine(g, cardView.getDisplayName(), manaCostString,
|
||||
totalContentInset + nameOffset, totalContentInset,
|
||||
|
@ -541,7 +561,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
|
||||
// Draw the mana symbols
|
||||
if (!cardView.isAbility() && !cardView.isFaceDown()) {
|
||||
ManaSymbols.draw(g, manaCost, x + w - manaCostWidth, y + boxTextOffset, boxTextHeight);
|
||||
ManaSymbols.draw(g, manaCost, x + w - manaCostWidth, y + boxTextOffset, boxTextHeight, Color.black, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,7 +844,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
String symbs = symbol;
|
||||
int symbHeight = (int) (0.8 * h);
|
||||
int manaCostWidth = CardRendererUtils.getManaCostWidth(symbs, symbHeight);
|
||||
ManaSymbols.draw(g, symbs, x + (w - manaCostWidth) / 2, y + (h - symbHeight) / 2, symbHeight);
|
||||
ManaSymbols.draw(g, symbs, x + (w - manaCostWidth) / 2, y + (h - symbHeight) / 2, symbHeight, Color.black, 2);
|
||||
}
|
||||
|
||||
// Get the first line of the textbox, the keyword string
|
||||
|
@ -849,6 +869,9 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
inset = cardWidth / 12;
|
||||
}
|
||||
int availWidth = w - inset;
|
||||
if (availWidth < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FontRenderContext frc = g.getFontRenderContext();
|
||||
AttributedCharacterIterator textIter = text.getIterator();
|
||||
|
|
|
@ -6,7 +6,6 @@ import mage.client.dialog.PreferencesDialog;
|
|||
import mage.client.util.GUISizeHelper;
|
||||
import mage.constants.Rarity;
|
||||
import mage.interfaces.plugin.CardPlugin;
|
||||
import mage.utils.CardUtil;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
|
@ -19,10 +18,10 @@ import org.mage.card.arcane.*;
|
|||
import org.mage.plugins.card.dl.DownloadGui;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import org.mage.plugins.card.dl.Downloader;
|
||||
import org.mage.plugins.card.dl.sources.CardFrames;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.dl.sources.GathererSets;
|
||||
import org.mage.plugins.card.dl.sources.GathererSymbols;
|
||||
import org.mage.plugins.card.dl.sources.ScryfallSymbolsSource;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
import org.mage.plugins.card.info.CardInfoPaneImpl;
|
||||
|
||||
|
@ -525,41 +524,49 @@ public class CardPluginImpl implements CardPlugin {
|
|||
/**
|
||||
* Download various symbols (mana, tap, set).
|
||||
*
|
||||
* @param imagesPath Path to check in and store symbols to. Can be null, in
|
||||
* such case default path should be used.
|
||||
* @param imagesDir Path to check in and store symbols to. Can't be null.
|
||||
*/
|
||||
@Override
|
||||
public void downloadSymbols(String imagesPath) {
|
||||
public void downloadSymbols(String imagesDir) {
|
||||
final DownloadGui g = new DownloadGui(new Downloader());
|
||||
|
||||
Iterable<DownloadJob> it = new GathererSymbols(imagesPath);
|
||||
Iterable<DownloadJob> it;
|
||||
|
||||
it = new GathererSymbols();
|
||||
for (DownloadJob job : it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
|
||||
it = new GathererSets(imagesPath);
|
||||
it = new GathererSets();
|
||||
for (DownloadJob job : it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
|
||||
it = new CardFrames(imagesPath);
|
||||
it = new ScryfallSymbolsSource();
|
||||
for (DownloadJob job : it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
|
||||
it = new DirectLinksForDownload(imagesPath);
|
||||
/*
|
||||
it = new CardFrames(imagesDir); // TODO: delete frames download (not need now)
|
||||
for (DownloadJob job : it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
*/
|
||||
|
||||
it = new DirectLinksForDownload();
|
||||
for (DownloadJob job : it) {
|
||||
g.getDownloader().add(job);
|
||||
}
|
||||
|
||||
JDialog d = new JDialog((Frame) null, "Download pictures", false);
|
||||
JDialog d = new JDialog((Frame) null, "Download symbols", false);
|
||||
d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
d.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
g.getDownloader().dispose();
|
||||
ManaSymbols.loadImages();
|
||||
// TODO: check reload process after download (icons do not update)
|
||||
}
|
||||
});
|
||||
d.setLayout(new BorderLayout());
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package org.mage.plugins.card.constants;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.io.File;
|
||||
|
||||
public final class Constants {
|
||||
|
||||
public static final String RESOURCE_PATH_SET = File.separator + "sets" + File.separator;
|
||||
|
||||
public static final String RESOURCE_PATH_MANA_SMALL = File.separator + "symbols" + File.separator + "small";
|
||||
public static final String RESOURCE_PATH_MANA_LARGE = File.separator + "symbols" + File.separator + "large";
|
||||
public static final String RESOURCE_PATH_MANA_MEDIUM = File.separator + "symbols" + File.separator + "medium";
|
||||
|
||||
public static final String RESOURCE_PATH_SET_SMALL = RESOURCE_PATH_SET + File.separator + "small" + File.separator;
|
||||
|
||||
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
|
||||
public static final Rectangle THUMBNAIL_SIZE_FULL = new Rectangle(102, 146);
|
||||
|
||||
public interface IO {
|
||||
|
||||
String imageBaseDir = "plugins" + File.separator + "images";
|
||||
String IMAGE_PROPERTIES_FILE = "image.url.properties";
|
||||
}
|
||||
|
||||
public static final String CARD_IMAGE_PATH_TEMPLATE = '.' + File.separator + "plugins" + File.separator + "images/{set}/{name}.{collector}.full.jpg";
|
||||
}
|
|
@ -28,7 +28,6 @@ import org.mage.plugins.card.utils.CardImageUtils;
|
|||
public class DownloadJob extends AbstractLaternaBean {
|
||||
|
||||
public enum State {
|
||||
|
||||
NEW, WORKING, FINISHED, ABORTED
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,12 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import mage.client.constants.Constants;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
/**
|
||||
* Used when we need to point to direct links to download resources from.
|
||||
|
@ -22,7 +25,7 @@ import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
|||
*/
|
||||
public class DirectLinksForDownload implements Iterable<DownloadJob> {
|
||||
|
||||
private static final String backsideUrl = "http://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg";
|
||||
private static final String backsideUrl = "https://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg";
|
||||
|
||||
private static final Map<String, String> directLinks = new LinkedHashMap<>();
|
||||
|
||||
|
@ -33,15 +36,13 @@ public class DirectLinksForDownload implements Iterable<DownloadJob> {
|
|||
directLinks.put(cardbackFilename, backsideUrl);
|
||||
}
|
||||
|
||||
private static final String DEFAULT_IMAGES_PATH = File.separator + "default";
|
||||
private static final File DEFAULT_OUT_DIR = new File("plugins" + File.separator + "images" + DEFAULT_IMAGES_PATH);
|
||||
public static File outDir = DEFAULT_OUT_DIR;
|
||||
public static File outDir;
|
||||
|
||||
public DirectLinksForDownload(String path) {
|
||||
if (path == null) {
|
||||
useDefaultDir();
|
||||
} else {
|
||||
changeOutDir(path);
|
||||
public DirectLinksForDownload() {
|
||||
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_DEFAUL_IMAGES);
|
||||
|
||||
if (!outDir.exists()){
|
||||
outDir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,20 +56,4 @@ public class DirectLinksForDownload implements Iterable<DownloadJob> {
|
|||
}
|
||||
return jobs.iterator();
|
||||
}
|
||||
|
||||
private void changeOutDir(String path) {
|
||||
File file = new File(path + DEFAULT_IMAGES_PATH);
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
} else {
|
||||
file.mkdirs();
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void useDefaultDir() {
|
||||
outDir = DEFAULT_OUT_DIR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,17 +8,41 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.Sets;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.constants.Rarity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
public class GathererSets implements Iterable<DownloadJob> {
|
||||
|
||||
private static final String SETS_PATH = File.separator + "sets";
|
||||
private static final File DEFAULT_OUT_DIR = new File("plugins" + File.separator + "images" + SETS_PATH);
|
||||
private static File outDir = DEFAULT_OUT_DIR;
|
||||
private class CheckResult {
|
||||
|
||||
private static final String[] symbols = {"10E", "9ED", "8ED", "7ED", "6ED", "5ED", "4ED", "3ED", "2ED", "LEB", "LEA",
|
||||
String code;
|
||||
ExpansionSet set;
|
||||
boolean haveCommon;
|
||||
boolean haveUncommon;
|
||||
boolean haveRare;
|
||||
boolean haveMyth;
|
||||
|
||||
private CheckResult(String ACode, ExpansionSet ASet, boolean AHaveCommon, boolean AHaveUncommon, boolean AHhaveRare, boolean AHaveMyth) {
|
||||
code = ACode;
|
||||
set = ASet;
|
||||
haveCommon = AHaveCommon;
|
||||
haveUncommon = AHaveUncommon;
|
||||
haveRare = AHhaveRare;
|
||||
haveMyth = AHaveMyth;
|
||||
}
|
||||
}
|
||||
|
||||
private static File outDir;
|
||||
|
||||
private static final int DAYS_BEFORE_RELEASE_TO_DOWNLOAD = +14; // Try to load the symbolsBasic eralies 14 days before release date
|
||||
private static final Logger logger = Logger.getLogger(GathererSets.class);
|
||||
|
||||
private static final String[] symbolsBasic = {"10E", "9ED", "8ED", "7ED", "6ED", "5ED", "4ED", "3ED", "2ED", "LEB", "LEA",
|
||||
"HOP",
|
||||
"ARN", "ATQ", "LEG", "DRK", "FEM", "HML",
|
||||
"ICE", "ALL", "CSP",
|
||||
|
@ -36,14 +60,19 @@ public class GathererSets implements Iterable<DownloadJob> {
|
|||
"LRW", "MOR",
|
||||
"SHM", "EVE",
|
||||
"MED", "ME2", "ME3", "ME4",
|
||||
"POR", "PO2", "PTK",
|
||||
"POR", "P02", "PTK",
|
||||
"ARC", "DD3EVG",
|
||||
"W16", "W17"};
|
||||
"W16", "W17",
|
||||
//"APAC" -- gatherer do not have that set, scrly have PALP
|
||||
//"ARENA" -- is't many set with different codes, not one
|
||||
"CLASH", "CP", "DD3GVL", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "MPS-AKH", "PTC", "S00", "S99", "SUS", "SWS", "UGIN", "UGL", "V10", "V17", "WMCQ", // need to fix
|
||||
"H09", "PD2", "PD3", "UNH", "CM1", "E02", "V11", "M25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "DDT", "8EB", "9EB", "CHR" // ok
|
||||
// current testing
|
||||
};
|
||||
|
||||
private static final String[] withMythics = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI",
|
||||
"ANB",
|
||||
private static final String[] symbolsBasicWithMyth = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI",
|
||||
"DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN",
|
||||
"DD3DVD", "DD3GLV", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS",
|
||||
"DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT",
|
||||
"ALA", "CON", "ARB",
|
||||
"ZEN", "WWK", "ROE",
|
||||
"SOM", "MBS", "NPH",
|
||||
|
@ -60,131 +89,249 @@ public class GathererSets implements Iterable<DownloadJob> {
|
|||
"SOI", "EMN",
|
||||
"KLD", "AER",
|
||||
"AKH", "HOU",
|
||||
"XLN", "C17",
|
||||
"RIX", "DOM", "M19", // not released
|
||||
"E01"
|
||||
};
|
||||
|
||||
private static final String[] onlyMythics = {
|
||||
"DRB", "V09", "V12", "V12", "V13", "V14", "V15", "V16", "EXP"
|
||||
private static final String[] symbolsOnlyMyth = {
|
||||
"DRB", "V09", "V12", "V13", "V14", "V15", "V16", "EXP"
|
||||
};
|
||||
private static final String[] onlyMythicsAsSpecial = {
|
||||
private static final String[] symbolsOnlySpecial = {
|
||||
"MPS"
|
||||
};
|
||||
|
||||
private static final HashMap<String, String> symbolsReplacements = new HashMap<>();
|
||||
private static final HashMap<String, String> codeReplacements = new HashMap<>();
|
||||
|
||||
static {
|
||||
symbolsReplacements.put("2ED", "2U");
|
||||
symbolsReplacements.put("3ED", "3E");
|
||||
symbolsReplacements.put("4ED", "4E");
|
||||
symbolsReplacements.put("5ED", "5E");
|
||||
symbolsReplacements.put("6ED", "6E");
|
||||
symbolsReplacements.put("7ED", "7E");
|
||||
symbolsReplacements.put("ALL", "AL");
|
||||
symbolsReplacements.put("APC", "AP");
|
||||
symbolsReplacements.put("ARN", "AN");
|
||||
symbolsReplacements.put("ATQ", "AQ");
|
||||
symbolsReplacements.put("CMA", "CM1");
|
||||
symbolsReplacements.put("DD3DVD", "DD3_DVD");
|
||||
symbolsReplacements.put("DD3EVG", "DD3_EVG");
|
||||
symbolsReplacements.put("DD3GLV", "DD3_GLV");
|
||||
symbolsReplacements.put("DD3JVC", "DD3_JVC");
|
||||
symbolsReplacements.put("DRK", "DK");
|
||||
symbolsReplacements.put("EXO", "EX");
|
||||
symbolsReplacements.put("FEM", "FE");
|
||||
symbolsReplacements.put("HML", "HM");
|
||||
symbolsReplacements.put("ICE", "IA");
|
||||
symbolsReplacements.put("INV", "IN");
|
||||
symbolsReplacements.put("LEA", "1E");
|
||||
symbolsReplacements.put("LEB", "2E");
|
||||
symbolsReplacements.put("LEG", "LE");
|
||||
symbolsReplacements.put("MPS", "MPS_KLD");
|
||||
symbolsReplacements.put("MIR", "MI");
|
||||
symbolsReplacements.put("MMQ", "MM");
|
||||
symbolsReplacements.put("NEM", "NE");
|
||||
symbolsReplacements.put("ODY", "OD");
|
||||
symbolsReplacements.put("PCY", "PR");
|
||||
symbolsReplacements.put("PLS", "PS");
|
||||
symbolsReplacements.put("POR", "PO");
|
||||
symbolsReplacements.put("PO2", "P2");
|
||||
symbolsReplacements.put("PTK", "PK");
|
||||
symbolsReplacements.put("STH", "ST");
|
||||
symbolsReplacements.put("TMP", "TE");
|
||||
symbolsReplacements.put("UDS", "CG");
|
||||
symbolsReplacements.put("ULG", "GU");
|
||||
symbolsReplacements.put("USG", "UZ");
|
||||
symbolsReplacements.put("VIS", "VI");
|
||||
symbolsReplacements.put("WTH", "WL");
|
||||
codeReplacements.put("2ED", "2U");
|
||||
codeReplacements.put("3ED", "3E");
|
||||
codeReplacements.put("4ED", "4E");
|
||||
codeReplacements.put("5ED", "5E");
|
||||
codeReplacements.put("6ED", "6E");
|
||||
codeReplacements.put("7ED", "7E");
|
||||
codeReplacements.put("ALL", "AL");
|
||||
codeReplacements.put("APC", "AP");
|
||||
codeReplacements.put("ARN", "AN");
|
||||
codeReplacements.put("ATQ", "AQ");
|
||||
codeReplacements.put("CMA", "CM1");
|
||||
codeReplacements.put("DD3DVD", "DD3_DVD");
|
||||
codeReplacements.put("DD3EVG", "DD3_EVG");
|
||||
codeReplacements.put("DD3JVC", "DD3_JVC");
|
||||
codeReplacements.put("DRK", "DK");
|
||||
codeReplacements.put("EXO", "EX");
|
||||
codeReplacements.put("FEM", "FE");
|
||||
codeReplacements.put("HML", "HM");
|
||||
codeReplacements.put("ICE", "IA");
|
||||
codeReplacements.put("INV", "IN");
|
||||
codeReplacements.put("LEA", "1E");
|
||||
codeReplacements.put("LEB", "2E");
|
||||
codeReplacements.put("LEG", "LE");
|
||||
codeReplacements.put("MPS", "MPS_KLD");
|
||||
codeReplacements.put("MIR", "MI");
|
||||
codeReplacements.put("MMQ", "MM");
|
||||
codeReplacements.put("NEM", "NE");
|
||||
codeReplacements.put("ODY", "OD");
|
||||
codeReplacements.put("PCY", "PR");
|
||||
codeReplacements.put("PLS", "PS");
|
||||
codeReplacements.put("POR", "PO");
|
||||
codeReplacements.put("P02", "P2");
|
||||
codeReplacements.put("PTK", "PK");
|
||||
codeReplacements.put("STH", "ST");
|
||||
codeReplacements.put("TMP", "TE");
|
||||
codeReplacements.put("UDS", "CG");
|
||||
codeReplacements.put("ULG", "GU");
|
||||
codeReplacements.put("USG", "UZ");
|
||||
codeReplacements.put("VIS", "VI");
|
||||
codeReplacements.put("WTH", "WL");
|
||||
codeReplacements.put("8EB", "8ED"); // inner xmage set for 8th edition
|
||||
codeReplacements.put("9EB", "8ED"); // inner xmage set for 9th edition
|
||||
codeReplacements.put("CHR", "CH");
|
||||
}
|
||||
|
||||
public GathererSets(String path) {
|
||||
if (path == null) {
|
||||
useDefaultDir();
|
||||
} else {
|
||||
changeOutDir(path);
|
||||
public GathererSets() {
|
||||
|
||||
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS);
|
||||
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
// checks for wrong card settings and support (easy to control what all good)
|
||||
private static final HashMap<String, CheckResult> setsToDownload = new HashMap<>();
|
||||
private static final HashMap<String, String> codesToIgnoreCheck = new HashMap<>();
|
||||
|
||||
static {
|
||||
// xMage have inner sets for 8th and 9th Edition for booster workaround (cards from core game do not include in boosters)
|
||||
// see https://mtg.gamepedia.com/8th_Edition/Core_Game
|
||||
// check must ignore that sets
|
||||
codesToIgnoreCheck.put("8EB", "8th Edition Box");
|
||||
codesToIgnoreCheck.put("9EB", "9th Edition Box");
|
||||
}
|
||||
|
||||
private void CheckSearchResult(String searchCode, ExpansionSet foundedExp, boolean canDownloadTask,
|
||||
boolean haveCommon, boolean haveUncommon, boolean haveRare, boolean haveMyth) {
|
||||
// duplicated in settings
|
||||
CheckResult res = setsToDownload.get(searchCode);
|
||||
|
||||
if (res != null) {
|
||||
logger.error(String.format("Symbols: founded duplicated code: %s", searchCode));
|
||||
} else {
|
||||
res = new CheckResult(searchCode, foundedExp, haveCommon, haveUncommon, haveRare, haveMyth);
|
||||
setsToDownload.put(searchCode, res);
|
||||
}
|
||||
|
||||
// not found
|
||||
if (foundedExp == null) {
|
||||
logger.error(String.format("Symbols: can't find set by code: %s", searchCode));
|
||||
return;
|
||||
}
|
||||
|
||||
// checks for founded sets only
|
||||
// to early to download
|
||||
if (!canDownloadTask) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(foundedExp.getReleaseDate());
|
||||
c.add(Calendar.DATE, -1 * DAYS_BEFORE_RELEASE_TO_DOWNLOAD);
|
||||
logger.warn(String.format("Symbols: early to download: %s (%s), available after %s",
|
||||
searchCode, foundedExp.getName(), c.getTime()));
|
||||
}
|
||||
}
|
||||
|
||||
private void AnalyseSearchResult() {
|
||||
// analyze supported sets and show wrong settings
|
||||
Date startedDate = new Date();
|
||||
|
||||
for (ExpansionSet set : Sets.getInstance().values()) {
|
||||
|
||||
// ignore some inner sets
|
||||
if (codesToIgnoreCheck.get(set.getCode()) != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CheckResult res = setsToDownload.get(set.getCode());
|
||||
|
||||
// 1. not configured at all
|
||||
if (res == null) {
|
||||
logger.warn(String.format("Symbols: set is not configured: %s (%s)", set.getCode(), set.getName()));
|
||||
continue; // can't do other checks
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
// 2. missing rarity icon:
|
||||
// WARNING, need too much time (60+ secs), only for debug mode
|
||||
///*
|
||||
if ((set.getCardsByRarity(Rarity.COMMON).size() > 0) && !res.haveCommon) {
|
||||
logger.error(String.format("Symbols: set have common cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
|
||||
}
|
||||
if ((set.getCardsByRarity(Rarity.UNCOMMON).size() > 0) && !res.haveUncommon) {
|
||||
logger.error(String.format("Symbols: set have uncommon cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
|
||||
}
|
||||
if ((set.getCardsByRarity(Rarity.RARE).size() > 0) && !res.haveRare) {
|
||||
logger.error(String.format("Symbols: set have rare cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
|
||||
}
|
||||
if ((set.getCardsByRarity(Rarity.MYTHIC).size() > 0) && !res.haveMyth) {
|
||||
logger.error(String.format("Symbols: set have mythic cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
|
||||
}
|
||||
//*/
|
||||
|
||||
// 3. info: sets with alternative numbers
|
||||
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
|
||||
if (String.valueOf(card.getCardNumberAsInt()).length() != card.getCardNumber().length()) {
|
||||
logger.info(String.format("Symbols: set have alternative card but do not config to it: %s (%s)", set.getCode(), set.getName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. info: sets with missing cards for boosters (todo: what about +20 number for alternative land arts?)
|
||||
if (set.getMaxCardNumberInBooster() != Integer.MAX_VALUE) {
|
||||
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
|
||||
if (card.getCardNumberAsInt() > set.getMaxCardNumberInBooster()) {
|
||||
if (card.getRarity() == Rarity.LAND) {
|
||||
logger.info(String.format("Symbols: set's booster have land above max card number: %s (%s), %s - %s", set.getCode(), set.getName(), card.getCardNumber(), card.getName()));
|
||||
} else {
|
||||
logger.info(String.format("Symbols: set's booster missing nonland card:: %s (%s), %s - %s", set.getCode(), set.getName(), card.getCardNumber(), card.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Date endedDate = new Date();
|
||||
long secs = (endedDate.getTime() - startedDate.getTime()) / 1000;
|
||||
logger.debug(String.format("Symbols: check completed after %d seconds", secs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<DownloadJob> iterator() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(new Date());
|
||||
c.add(Calendar.DATE, +14); // Try to load the symbols eralies 14 days before release date
|
||||
c.add(Calendar.DATE, DAYS_BEFORE_RELEASE_TO_DOWNLOAD);
|
||||
Date compareDate = c.getTime();
|
||||
ArrayList<DownloadJob> jobs = new ArrayList<>();
|
||||
for (String symbol : symbols) {
|
||||
boolean canDownload;
|
||||
|
||||
setsToDownload.clear();
|
||||
|
||||
for (String symbol : symbolsBasic) {
|
||||
ExpansionSet exp = Sets.findSet(symbol);
|
||||
canDownload = false;
|
||||
if (exp != null && exp.getReleaseDate().before(compareDate)) {
|
||||
canDownload = true;
|
||||
jobs.add(generateDownloadJob(symbol, "C", "C"));
|
||||
jobs.add(generateDownloadJob(symbol, "U", "U"));
|
||||
jobs.add(generateDownloadJob(symbol, "R", "R"));
|
||||
}
|
||||
CheckSearchResult(symbol, exp, canDownload, true, true, true, false);
|
||||
}
|
||||
for (String symbol : withMythics) {
|
||||
|
||||
for (String symbol : symbolsBasicWithMyth) {
|
||||
ExpansionSet exp = Sets.findSet(symbol);
|
||||
canDownload = false;
|
||||
if (exp != null && exp.getReleaseDate().before(compareDate)) {
|
||||
canDownload = true;
|
||||
jobs.add(generateDownloadJob(symbol, "C", "C"));
|
||||
jobs.add(generateDownloadJob(symbol, "U", "U"));
|
||||
jobs.add(generateDownloadJob(symbol, "R", "R"));
|
||||
jobs.add(generateDownloadJob(symbol, "M", "M"));
|
||||
}
|
||||
CheckSearchResult(symbol, exp, canDownload, true, true, true, true);
|
||||
}
|
||||
for (String symbol : onlyMythics) {
|
||||
|
||||
for (String symbol : symbolsOnlyMyth) {
|
||||
ExpansionSet exp = Sets.findSet(symbol);
|
||||
canDownload = false;
|
||||
if (exp != null && exp.getReleaseDate().before(compareDate)) {
|
||||
canDownload = true;
|
||||
jobs.add(generateDownloadJob(symbol, "M", "M"));
|
||||
}
|
||||
CheckSearchResult(symbol, exp, canDownload, false, false, false, true);
|
||||
}
|
||||
for (String symbol : onlyMythicsAsSpecial) {
|
||||
|
||||
for (String symbol : symbolsOnlySpecial) {
|
||||
ExpansionSet exp = Sets.findSet(symbol);
|
||||
canDownload = false;
|
||||
if (exp != null && exp.getReleaseDate().before(compareDate)) {
|
||||
canDownload = true;
|
||||
jobs.add(generateDownloadJob(symbol, "M", "S"));
|
||||
}
|
||||
CheckSearchResult(symbol, exp, canDownload, false, false, false, true);
|
||||
}
|
||||
|
||||
// check wrong settings
|
||||
AnalyseSearchResult();
|
||||
|
||||
return jobs.iterator();
|
||||
}
|
||||
|
||||
private DownloadJob generateDownloadJob(String set, String rarity, String urlRarity) {
|
||||
File dst = new File(outDir, set + '-' + rarity + ".jpg");
|
||||
if (symbolsReplacements.containsKey(set)) {
|
||||
set = symbolsReplacements.get(set);
|
||||
if (codeReplacements.containsKey(set)) {
|
||||
set = codeReplacements.get(set);
|
||||
}
|
||||
String url = "http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + urlRarity;
|
||||
return new DownloadJob(set + '-' + rarity, fromURL(url), toFile(dst));
|
||||
}
|
||||
|
||||
private void changeOutDir(String path) {
|
||||
File file = new File(path + SETS_PATH);
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
} else {
|
||||
file.mkdirs();
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void useDefaultDir() {
|
||||
outDir = DEFAULT_OUT_DIR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,12 @@ import com.google.common.collect.AbstractIterator;
|
|||
import java.io.File;
|
||||
import static java.lang.String.format;
|
||||
import java.util.Iterator;
|
||||
|
||||
import mage.client.constants.Constants;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
/**
|
||||
* The class GathererSymbols.
|
||||
|
@ -23,9 +26,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
|
|||
//TODO chaos and planeswalker symbol
|
||||
//chaos: http://gatherer.wizards.com/Images/Symbols/chaos.gif
|
||||
|
||||
private static final String SYMBOLS_PATH = File.separator + "symbols";
|
||||
private static final File DEFAULT_OUT_DIR = new File("plugins" + File.separator + "images" + SYMBOLS_PATH);
|
||||
private static File outDir = DEFAULT_OUT_DIR;
|
||||
private static File outDir;
|
||||
|
||||
private static final String urlFmt = "http://gatherer.wizards.com/handlers/image.ashx?size=%1$s&name=%2$s&type=symbol";
|
||||
|
||||
|
@ -38,11 +39,11 @@ public class GathererSymbols implements Iterable<DownloadJob> {
|
|||
"X", "S", "T", "Q", "C", "E"};
|
||||
private static final int minNumeric = 0, maxNumeric = 16;
|
||||
|
||||
public GathererSymbols(String path) {
|
||||
if (path == null) {
|
||||
useDefaultDir();
|
||||
} else {
|
||||
changeOutDir(path);
|
||||
public GathererSymbols() {
|
||||
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS);
|
||||
|
||||
if (!outDir.exists()){
|
||||
outDir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,20 +116,4 @@ public class GathererSymbols implements Iterable<DownloadJob> {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void changeOutDir(String path) {
|
||||
File file = new File(path + SYMBOLS_PATH);
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
} else {
|
||||
file.mkdirs();
|
||||
if (file.exists()) {
|
||||
outDir = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void useDefaultDir() {
|
||||
outDir = DEFAULT_OUT_DIR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,12 +199,12 @@ public enum MagicCardsImageSource implements CardImageSource {
|
|||
add("E01");
|
||||
add("HOU");
|
||||
add("C17");
|
||||
// add("XLN");
|
||||
// add("DDT");
|
||||
// add("IMA");
|
||||
// add("E02");
|
||||
// add("V17");
|
||||
// add("UST");
|
||||
add("XLN");
|
||||
add("DDT");
|
||||
add("IMA");
|
||||
add("E02");
|
||||
add("V17");
|
||||
add("UST");
|
||||
// add("RIX");
|
||||
// add("A25");
|
||||
// add("DOM");
|
||||
|
@ -262,6 +262,7 @@ public enum MagicCardsImageSource implements CardImageSource {
|
|||
put("DDQ", "duel-decks-blessed-vs-cursed");
|
||||
put("DDR", "duel-decks-nissa-vs-ob-nixilis");
|
||||
put("DDS", "duel-decks-mind-vs-might");
|
||||
put("DDS", "duel-decks-merfolk-vs-goblin");
|
||||
put("DGM", "dragons-maze");
|
||||
put("DKA", "dark-ascension");
|
||||
put("DRB", "from-the-vault-dragons");
|
||||
|
|
|
@ -228,11 +228,11 @@ public enum MagidexImageSource implements CardImageSource {
|
|||
supportedSets.add("E01");
|
||||
supportedSets.add("HOU");
|
||||
supportedSets.add("C17");
|
||||
// supportedSets.add("XLN");
|
||||
// supportedSets.add("DDT");
|
||||
// supportedSets.add("IMA");
|
||||
// supportedSets.add("E02");
|
||||
// supportedSets.add("V17");
|
||||
supportedSets.add("XLN");
|
||||
supportedSets.add("DDT");
|
||||
supportedSets.add("IMA");
|
||||
supportedSets.add("E02");
|
||||
supportedSets.add("V17");
|
||||
// supportedSets.add("UST");
|
||||
// supportedSets.add("RIX");
|
||||
// supportedSets.add("A25");
|
||||
|
|
|
@ -253,11 +253,14 @@ public enum MythicspoilerComSource implements CardImageSource {
|
|||
supportedSets.add("C17");
|
||||
supportedSets.add("IMA");
|
||||
supportedSets.add("XLN");
|
||||
supportedSets.add("UST");
|
||||
supportedSets.add("RIX");
|
||||
|
||||
sets = new LinkedHashMap<>();
|
||||
setsAliases = new HashMap<>();
|
||||
setsAliases.put("exp", "bfz");
|
||||
setsAliases.put("xln", "ixa");
|
||||
setsAliases.put("nem", "nms");
|
||||
cardNameAliases = new HashMap<>();
|
||||
// set+wrong name from web side => correct card name
|
||||
cardNameAliases.put("MM2-otherwordlyjourney", "otherworldlyjourney");
|
||||
|
@ -278,7 +281,8 @@ public enum MythicspoilerComSource implements CardImageSource {
|
|||
cardNameAliases.put("XLN-lookoutsdecision", "lookoutsdispersal");
|
||||
cardNameAliases.put("XLN-infuriatedgladiodon", "ragingswordtooth");
|
||||
cardNameAliases.put("XLN-redoubledvolley", "repeatingbarrage");
|
||||
|
||||
cardNameAliases.put("UST-captialoffense", "capitaloffense");
|
||||
cardNameAliases.put("RIX-tetzimocdeathprimordial", "tetzimocprimaldeath");
|
||||
// <card name, card link>
|
||||
manualLinks = new HashMap<>();
|
||||
HashMap<String, String> links = new HashMap<>();
|
||||
|
@ -294,6 +298,16 @@ public enum MythicspoilerComSource implements CardImageSource {
|
|||
links.put("spitfirebastion", "spitfirebastion");
|
||||
manualLinks.put("XLN", links);
|
||||
|
||||
HashMap<String, String> linksRix = new HashMap<>();
|
||||
linksRix.put("vaultofcatlacan", "vaultofcatlacan");
|
||||
linksRix.put("atzalcaveofeternity", "atzalcaveofeternity");
|
||||
linksRix.put("wingedtempleoforazca", "wingedtempleoforazca");
|
||||
linksRix.put("metzalitoweroftriumph", "metzalitoweroftriumph");
|
||||
linksRix.put("tomboftheduskrose", "tomboftheduskrose");
|
||||
linksRix.put("sanctumofthesun", "sanctumofthesun");
|
||||
linksRix.put("goldforgegarrison", "goldforgegarrison");
|
||||
manualLinks.put("RIX", linksRix);
|
||||
|
||||
cardNameAliasesStart = new HashMap<>();
|
||||
HashSet<String> names = new HashSet<>();
|
||||
names.add("eldrazidevastator.jpg");
|
||||
|
@ -411,6 +425,8 @@ public enum MythicspoilerComSource implements CardImageSource {
|
|||
Map<String, String> setLinks = sets.computeIfAbsent(cardSet, k -> getSetLinks(cardSet));
|
||||
String searchName = card.getDownloadName().toLowerCase()
|
||||
.replaceAll(" ", "")
|
||||
.replaceAll("\\.", "")
|
||||
.replaceAll("&", "and")
|
||||
.replaceAll("-", "")
|
||||
.replaceAll("'", "")
|
||||
.replaceAll(",", "")
|
||||
|
|
|
@ -8,7 +8,7 @@ import java.util.Set;
|
|||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
|
||||
/**
|
||||
* @author Quercitron
|
||||
* @author Quercitron, JayDi85
|
||||
*
|
||||
*/
|
||||
public enum ScryfallImageSource implements CardImageSource {
|
||||
|
@ -200,12 +200,14 @@ public enum ScryfallImageSource implements CardImageSource {
|
|||
supportedSets.add("HOU");
|
||||
supportedSets.add("C17");
|
||||
supportedSets.add("XLN");
|
||||
// supportedSets.add("DDT");
|
||||
supportedSets.add("DDT");
|
||||
supportedSets.add("IMA");
|
||||
// supportedSets.add("E02");
|
||||
// supportedSets.add("V17");
|
||||
// supportedSets.add("UST");
|
||||
// supportedSets.add("RIX");
|
||||
supportedSets.add("E02");
|
||||
supportedSets.add("V17");
|
||||
supportedSets.add("UST");
|
||||
supportedSets.add("RIX");
|
||||
supportedSets.add("WMCQ");
|
||||
supportedSets.add("PPRO");
|
||||
// supportedSets.add("A25");
|
||||
// supportedSets.add("DOM");
|
||||
// supportedSets.add("M19");
|
||||
|
@ -214,10 +216,24 @@ public enum ScryfallImageSource implements CardImageSource {
|
|||
|
||||
@Override
|
||||
public String generateURL(CardDownloadData card) throws Exception {
|
||||
|
||||
// special card number like "103a" already compatible
|
||||
if (card.isCollectorIdWithStr()) {
|
||||
return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/"
|
||||
+ card.getCollectorId() + ".jpg";
|
||||
}
|
||||
|
||||
// double faced cards do not supporte by API (need direct link for img)
|
||||
// example: https://img.scryfall.com/cards/large/en/xln/173b.jpg
|
||||
if (card.isTwoFacedCard()) {
|
||||
return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/"
|
||||
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg";
|
||||
}
|
||||
|
||||
// basic cards by api call (redirect to img link)
|
||||
// example: https://api.scryfall.com/cards/xln/121?format=image
|
||||
return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/"
|
||||
+ card.getCollectorId()
|
||||
+ (card.isSecondSide() ? "b" : "")
|
||||
+ "?format=image";
|
||||
+ card.getCollectorId() + "?format=image";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -275,6 +291,7 @@ public enum ScryfallImageSource implements CardImageSource {
|
|||
put("DD3EVG", "evg");
|
||||
put("MPS-AKH", "mp2");
|
||||
put("MBP", "pmei");
|
||||
put("WMCQ", "pwcq");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
package org.mage.plugins.card.dl.sources;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
|
||||
import static org.mage.card.arcane.ManaSymbols.getSymbolFileNameAsSVG;
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
// TODO: add force to download symbols (rewrite exist files)
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jaydi85@gmail.com
|
||||
*
|
||||
*/
|
||||
public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
|
||||
|
||||
|
||||
static final String SOURCE_URL = "https://assets.scryfall.com/assets/scryfall.css"; // search css-file on https://scryfall.com/docs/api/colors
|
||||
static final String STATE_PROP_NAME = "state";
|
||||
static final String DOWNLOAD_TEMP_FILE = getImagesDir() + File.separator + "temp" + File.separator + "scryfall-symbols-source.txt";
|
||||
|
||||
// card-symbol-(.{1,10}){background-image.+base64,(.+)("\)})
|
||||
// see https://regex101.com/
|
||||
static final String REGEXP_MANA_PATTERN = "card-symbol-(.{1,10})\\{background-image.+base64,(.+)(\"\\)\\})";
|
||||
|
||||
|
||||
protected static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(ScryfallSymbolsSource.class);
|
||||
|
||||
private static final int SYMBOLS_NUMBER_START = 0;
|
||||
private static final int SYMBOLS_NUMBER_END = 20;
|
||||
// copy-past symbols list from gatherer download
|
||||
private static final String[] SYMBOLS_LIST = {"W", "U", "B", "R", "G",
|
||||
"W/U", "U/B", "B/R", "R/G", "G/W", "W/B", "U/R", "B/G", "R/W", "G/U",
|
||||
"2/W", "2/U", "2/B", "2/R", "2/G",
|
||||
"WP", "UP", "BP", "RP", "GP",
|
||||
"X", "S", "T", "Q", "C", "E"};
|
||||
|
||||
@Override
|
||||
public Iterator<DownloadJob> iterator() {
|
||||
ArrayList<DownloadJob> jobs = new ArrayList<>();
|
||||
|
||||
// all symbols on one page
|
||||
jobs.add(generateDownloadJob());
|
||||
|
||||
return jobs.iterator();
|
||||
}
|
||||
|
||||
private void parseData(String sourcePath){
|
||||
|
||||
String sourceData = "";
|
||||
try {
|
||||
sourceData = new String(Files.readAllBytes(Paths.get(sourcePath)));
|
||||
}catch (IOException e) {
|
||||
LOGGER.error("Can't open file to parse data: " + sourcePath + " , reason: " + e.getMessage());
|
||||
}
|
||||
|
||||
// gen symbols list
|
||||
ArrayList<String> allMageSymbols = new ArrayList<>();
|
||||
for(int i = 0; i < SYMBOLS_LIST.length; i++){
|
||||
allMageSymbols.add(SYMBOLS_LIST[i]);
|
||||
}
|
||||
for(Integer i = SYMBOLS_NUMBER_START; i <= SYMBOLS_NUMBER_END; i++){
|
||||
allMageSymbols.add(String.valueOf(SYMBOLS_NUMBER_START + i));
|
||||
}
|
||||
|
||||
Map<String, String> foundedData = new HashMap<>();
|
||||
|
||||
// search raw data
|
||||
sourceData = sourceData.replaceAll(".card-symbol", "\n.card-symbol"); // css as one line, but need multiline
|
||||
Pattern regex = Pattern.compile(REGEXP_MANA_PATTERN);
|
||||
Matcher regexMatcher = regex.matcher(sourceData);
|
||||
while (regexMatcher.find()) {
|
||||
String symbolCode = regexMatcher.group(1).trim();
|
||||
String symbolData = regexMatcher.group(2).trim().replace(" ", "").replaceAll("\n", ""); // decoder need only wrapped text as one line
|
||||
|
||||
foundedData.put(symbolCode, symbolData);
|
||||
}
|
||||
|
||||
// dirs maker
|
||||
File dir = getSymbolFileNameAsSVG("W").getParentFile();
|
||||
if(!dir.exists()){
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// decode and save data (only if not exist)
|
||||
for(String needCode: allMageSymbols){
|
||||
|
||||
String searchCode = needCode.replace("/", "");
|
||||
|
||||
if(!foundedData.containsKey(searchCode))
|
||||
{
|
||||
LOGGER.warn("Can't found symbol code from scryfall: " + searchCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
File destFile = getSymbolFileNameAsSVG(searchCode);
|
||||
if (destFile.exists() && (destFile.length() > 0)){
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// base64 transform
|
||||
String data64 = foundedData.get(searchCode);
|
||||
Base64.Decoder dec = Base64.getDecoder();
|
||||
byte[] fileData = dec.decode(data64);
|
||||
|
||||
FileOutputStream stream = new FileOutputStream(destFile);
|
||||
stream.write(fileData);
|
||||
stream.close();
|
||||
|
||||
LOGGER.info("New svg symbol downloaded: " + needCode);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ScryfallSymbolsDownloadJob extends DownloadJob{
|
||||
|
||||
// listener for data parse after download complete
|
||||
private class ScryDownloadOnFinishedListener implements PropertyChangeListener {
|
||||
private String downloadedFile;
|
||||
|
||||
public ScryDownloadOnFinishedListener(String ADestFile){
|
||||
this.downloadedFile = ADestFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (!evt.getPropertyName().equals(STATE_PROP_NAME)){
|
||||
throw new IllegalArgumentException("Unknown download property " + evt.getPropertyName());
|
||||
}
|
||||
|
||||
if (evt.getNewValue() != State.FINISHED){
|
||||
return;
|
||||
}
|
||||
|
||||
// parse data and save to dest
|
||||
parseData(this.downloadedFile);
|
||||
}
|
||||
}
|
||||
|
||||
private String destFile = "";
|
||||
|
||||
public ScryfallSymbolsDownloadJob() {
|
||||
super("Scryfall symbols source", fromURL(SOURCE_URL), toFile(DOWNLOAD_TEMP_FILE));
|
||||
this.destFile = DOWNLOAD_TEMP_FILE;
|
||||
this.addPropertyChangeListener(STATE_PROP_NAME, new ScryDownloadOnFinishedListener(this.destFile));
|
||||
|
||||
// clear dest file (always download new data)
|
||||
File file = new File(this.destFile);
|
||||
if (file.exists()){
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadJob generateDownloadJob() {
|
||||
return new ScryfallSymbolsDownloadJob();
|
||||
}
|
||||
}
|
|
@ -45,6 +45,10 @@ import java.util.concurrent.ExecutorService;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.prefs.Preferences;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.remote.Connection;
|
||||
|
@ -258,11 +262,11 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
supportedSets.add("HOU");
|
||||
supportedSets.add("C17");
|
||||
supportedSets.add("XLN");
|
||||
// supportedSets.add("DDT"); // Duel Decks: Merfolk vs. Goblins
|
||||
// supportedSets.add("IMA"); // Iconic Msters
|
||||
// supportedSets.add("E02"); // Explorers of Ixalan
|
||||
// supportedSets.add("V17"); // From the Vault: Transform
|
||||
// supportedSets.add("UST"); // Unstable
|
||||
supportedSets.add("DDT"); // Duel Decks: Merfolk vs. Goblins
|
||||
supportedSets.add("IMA"); // Iconic Msters
|
||||
supportedSets.add("E02"); // Explorers of Ixalan
|
||||
supportedSets.add("V17"); // From the Vault: Transform
|
||||
supportedSets.add("UST"); // Unstable
|
||||
// supportedSets.add("RIX"); // Rivals of Ixalan
|
||||
// supportedSets.add("A25"); // Masters 25
|
||||
// supportedSets.add("DOM"); // Dominaria
|
||||
|
@ -332,6 +336,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
setsAliases.put("DDQ", "Duel Decks: Blessed vs. Cursed");
|
||||
setsAliases.put("DDR", "Duel Decks: Nissa vs. Ob Nixilis");
|
||||
setsAliases.put("DDS", "Duel Decks: Mind vs. Might");
|
||||
setsAliases.put("DDT", "Duel Decks: Merfolk vs. Goblins");
|
||||
setsAliases.put("DGM", "Dragon's Maze");
|
||||
setsAliases.put("DIS", "Dissension");
|
||||
setsAliases.put("DKA", "Dark Ascension");
|
||||
|
@ -359,6 +364,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
setsAliases.put("HOP", "Planechase");
|
||||
setsAliases.put("HOU", "Hour of Devastation");
|
||||
setsAliases.put("ICE", "Ice Age");
|
||||
setsAliases.put("IMA", "Iconic Masters");
|
||||
setsAliases.put("INV", "Invasion");
|
||||
setsAliases.put("ISD", "Innistrad");
|
||||
setsAliases.put("JOU", "Journey into Nyx");
|
||||
|
@ -472,11 +478,65 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String 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);
|
||||
}
|
||||
if (card.isFlippedSide()) { //doesn't support rotated images
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> setLinks = sets.computeIfAbsent(cardSet, k -> getSetLinks(cardSet));
|
||||
if (setLinks == null || setLinks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String searchKey = card.getDownloadName().toLowerCase().replace(" ", "").replace("&", "//");
|
||||
String link = setLinks.get(searchKey);
|
||||
if (link == null) {
|
||||
int length = collectorId.length();
|
||||
// Try to find card image with added letter (e.g. from Unstable)
|
||||
if (Character.isLetter(collectorId.charAt(length - 1))) {
|
||||
String key = searchKey + collectorId.charAt(length - 1);
|
||||
link = setLinks.get(key);
|
||||
}
|
||||
// Try to find image with added card number (e.g. basic lands)
|
||||
if (link == null) {
|
||||
String key = searchKey + collectorId;
|
||||
link = setLinks.get(key);
|
||||
if (link == null) {
|
||||
int number = Integer.parseInt(collectorId.substring(0, length));
|
||||
if (number > 0) {
|
||||
List<String> l = new ArrayList<>(setLinks.values());
|
||||
if (l.size() >= number) {
|
||||
link = l.get(number - 1);
|
||||
} else {;
|
||||
link = l.get(number - 21);
|
||||
if (link != null) {
|
||||
link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (link != null && !link.startsWith("http://")) {
|
||||
link = "http://gatherer.wizards.com" + link;
|
||||
}
|
||||
return link;
|
||||
|
||||
}
|
||||
|
||||
private Map<String, String> getSetLinks(String cardSet) {
|
||||
LinkedHashMap<String, String> setLinks = new LinkedHashMap<>();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||
try {
|
||||
String setNames = setsAliases.get(cardSet);
|
||||
if (setNames == null) {
|
||||
setNames = Sets.getInstance().get(cardSet).getName();
|
||||
}
|
||||
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
|
||||
for (String setName : setNames.split("\\^")) {
|
||||
// String URLSetName = URLEncoder.encode(setName, "UTF-8");
|
||||
|
@ -502,8 +562,22 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
}
|
||||
String cardName = normalizeName(cardsImages.get(i).attr("alt"));
|
||||
if (cardName != null && !cardName.isEmpty()) {
|
||||
Runnable task = new GetImageLinkTask(multiverseId, cardName, preferedLanguage, setLinks);
|
||||
executor.execute(task);
|
||||
if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island")
|
||||
|| cardName.equals("Plains") || cardName.equals("Wastes")) {
|
||||
getLandVariations(setLinks, cardSet, multiverseId, cardName);
|
||||
} else {
|
||||
String numberChar = "";
|
||||
int pos1 = cardName.indexOf("(");
|
||||
if (pos1 > 0) {
|
||||
int pos2 = cardName.indexOf("(", pos1 + 1);
|
||||
if (pos2 > 0) {
|
||||
numberChar = cardName.substring(pos2 + 1, pos2 + 2);
|
||||
cardName = cardName.substring(0, pos1);
|
||||
}
|
||||
}
|
||||
Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId);
|
||||
setLinks.put(cardName.toLowerCase() + numberChar, generateLink(preferedMultiverseId));
|
||||
}
|
||||
}
|
||||
}
|
||||
page++;
|
||||
|
@ -552,23 +626,38 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
return doc;
|
||||
}
|
||||
|
||||
private Map<String, String> getLandVariations(int multiverseId, String cardName) throws IOException, NumberFormatException {
|
||||
private void getLandVariations(LinkedHashMap<String, String> setLinks, String cardSet, int multiverseId, String cardName) throws IOException, NumberFormatException {
|
||||
CardCriteria criteria = new CardCriteria();
|
||||
criteria.nameExact(cardName);
|
||||
criteria.setCodes(cardSet);
|
||||
List<CardInfo> cards = CardRepository.instance.findCards(criteria);
|
||||
|
||||
String urlLandDocument = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId;
|
||||
Document landDoc = getDocument(urlLandDocument);
|
||||
Elements variations = landDoc.select("a.variationlink");
|
||||
Map<String, String> links = new HashMap<>();
|
||||
if (!variations.isEmpty()) {
|
||||
int landNumber = 1;
|
||||
if (variations.size() > cards.size()) {
|
||||
logger.warn("More links for lands than cards in DB found for set: " + cardSet + " Name: " + cardName);
|
||||
}
|
||||
if (variations.size() < cards.size()) {
|
||||
logger.warn("Less links for lands than cards in DB found for set: " + cardSet + " Name: " + cardName);
|
||||
}
|
||||
int iteration = 0;
|
||||
for (Element variation : variations) {
|
||||
String colNumb = String.valueOf(iteration);
|
||||
if (cards.size() > iteration) {
|
||||
CardInfo cardInfo = cards.get(iteration);
|
||||
if (cardInfo != null) {
|
||||
colNumb = cardInfo.getCardNumber();
|
||||
}
|
||||
}
|
||||
Integer landMultiverseId = Integer.parseInt(variation.attr("href").replaceAll("[^\\d]", ""));
|
||||
links.put((cardName + landNumber).toLowerCase(), generateLink(landMultiverseId));
|
||||
landNumber++;
|
||||
setLinks.put((cardName).toLowerCase() + colNumb, generateLink(landMultiverseId));
|
||||
iteration++;
|
||||
}
|
||||
} else {
|
||||
links.put(cardName.toLowerCase(), generateLink(multiverseId));
|
||||
setLinks.put(cardName.toLowerCase(), generateLink(multiverseId));
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
private static String generateLink(int landMultiverseId) {
|
||||
|
@ -623,50 +712,8 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
.replace("\u00DB", "U").replace("\u00FB", "u")
|
||||
.replace("\u00DC", "U").replace("\u00FC", "u")
|
||||
.replace("\u00E9", "e").replace("&", "//")
|
||||
.replace(" ", "")
|
||||
.replace("Hintreland Scourge", "Hinterland Scourge");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String 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);
|
||||
}
|
||||
if (card.isFlippedSide()) { //doesn't support rotated images
|
||||
return null;
|
||||
}
|
||||
String setNames = setsAliases.get(cardSet);
|
||||
if (setNames != null) {
|
||||
Map<String, String> setLinks = sets.computeIfAbsent(cardSet, k -> getSetLinks(cardSet));
|
||||
if (setLinks == null || setLinks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String link = setLinks.get(card.getDownloadName().toLowerCase());
|
||||
if (link == null) {
|
||||
int length = collectorId.length();
|
||||
|
||||
if (Character.isLetter(collectorId.charAt(length - 1))) {
|
||||
length -= 1;
|
||||
}
|
||||
|
||||
int number = Integer.parseInt(collectorId.substring(0, length));
|
||||
List<String> l = new ArrayList<>(setLinks.values());
|
||||
if (l.size() >= number) {
|
||||
link = l.get(number - 1);
|
||||
} else {;
|
||||
link = l.get(number - 21);
|
||||
if (link != null) {
|
||||
link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (link != null && !link.startsWith("http://")) {
|
||||
link = "http://gatherer.wizards.com" + link;
|
||||
}
|
||||
return link;
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
@ -680,44 +727,43 @@ public enum WizardCardsImageSource implements CardImageSource {
|
|||
return 60.0f;
|
||||
}
|
||||
|
||||
private final class GetImageLinkTask implements Runnable {
|
||||
|
||||
private int multiverseId;
|
||||
private String cardName;
|
||||
private String preferedLanguage;
|
||||
private LinkedHashMap setLinks;
|
||||
|
||||
public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, LinkedHashMap setLinks) {
|
||||
try {
|
||||
this.multiverseId = multiverseId;
|
||||
this.cardName = cardName;
|
||||
this.preferedLanguage = preferedLanguage;
|
||||
this.setLinks = setLinks;
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.error("multiverseId: " + multiverseId);
|
||||
logger.error("cardName: " + cardName);
|
||||
logger.error("preferedLanguage: " + preferedLanguage);
|
||||
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 preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId);
|
||||
setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
||||
}
|
||||
} catch (IOException | NumberFormatException ex) {
|
||||
logger.error("Exception when parsing the wizards page: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// private final class GetImageLinkTask implements Runnable {
|
||||
//
|
||||
// private int multiverseId;
|
||||
// private String cardName;
|
||||
// private String preferedLanguage;
|
||||
// private LinkedHashMap setLinks;
|
||||
//
|
||||
// public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, LinkedHashMap setLinks) {
|
||||
// try {
|
||||
// this.multiverseId = multiverseId;
|
||||
// this.cardName = cardName;
|
||||
// this.preferedLanguage = preferedLanguage;
|
||||
// this.setLinks = setLinks;
|
||||
// } catch (Exception ex) {
|
||||
// logger.error(ex.getMessage());
|
||||
// logger.error("multiverseId: " + multiverseId);
|
||||
// logger.error("cardName: " + cardName);
|
||||
// logger.error("preferedLanguage: " + preferedLanguage);
|
||||
// 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 preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId);
|
||||
// setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
||||
// }
|
||||
// } catch (IOException | NumberFormatException ex) {
|
||||
// logger.error("Exception when parsing the wizards page: " + ex.getMessage());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
@Override
|
||||
public int getTotalImages() {
|
||||
return -1;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.mage.plugins.card.images;
|
||||
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -128,6 +130,15 @@ public class CardDownloadData {
|
|||
return collectorId;
|
||||
}
|
||||
|
||||
public Integer getCollectorIdAsInt() {
|
||||
return CardUtil.parseCardNumberAsInt(collectorId);
|
||||
}
|
||||
|
||||
public boolean isCollectorIdWithStr(){
|
||||
// card have special numbers like "103a", "180b" (scryfall style)
|
||||
return !getCollectorId().equals(getCollectorIdAsInt().toString());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -27,13 +27,9 @@ import mage.cards.repository.CardCriteria;
|
|||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.remote.Connection;
|
||||
import static mage.remote.Connection.ProxyType.HTTP;
|
||||
import static mage.remote.Connection.ProxyType.NONE;
|
||||
import static mage.remote.Connection.ProxyType.SOCKS;
|
||||
import net.java.truevfs.access.TFile;
|
||||
import net.java.truevfs.access.TFileOutputStream;
|
||||
import net.java.truevfs.access.TVFS;
|
||||
|
@ -43,8 +39,12 @@ import org.mage.plugins.card.dl.sources.*;
|
|||
import org.mage.plugins.card.properties.SettingsManager;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable {
|
||||
|
||||
// don't forget to remove new sets from ignore.urls to download (propeties file in resources)
|
||||
|
||||
private static DownloadPictures instance;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DownloadPictures.class);
|
||||
|
@ -352,6 +352,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (cardImageSource.isTokenSource() && cardImageSource.isImageProvided(data.getSet(), data.getName())) {
|
||||
numberTokenImagesAvailable++;
|
||||
cardsToDownload.add(data);
|
||||
}else{
|
||||
//logger.warn("Source do not support token (set " + data.getSet() + ", token " + data.getName() + ")");
|
||||
}
|
||||
} else {
|
||||
if (selectedSetCodes != null && selectedSetCodes.contains(data.getSet())) {
|
||||
|
@ -430,7 +432,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
throw new IllegalStateException("Second side card can't have empty name.");
|
||||
}
|
||||
|
||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true);
|
||||
CardInfo secondSideCard = CardRepository.instance.findCard(card.getSecondSideName());
|
||||
if (secondSideCard == null){
|
||||
throw new IllegalStateException("Can''t find second side card in database: " + card.getSecondSideName());
|
||||
}
|
||||
|
||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), secondSideCard.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true);
|
||||
url.setType2(isType2);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
|
@ -462,7 +469,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
*/
|
||||
List<CardDownloadData> cardsToDownload = Collections.synchronizedList(new ArrayList<>());
|
||||
allCardsUrls.parallelStream().forEach(card -> {
|
||||
TFile file = new TFile(CardImageUtils.generateImagePath(card));
|
||||
File file = new TFile(CardImageUtils.buildImagePathToCard(card));
|
||||
logger.debug(card.getName() + " (is_token=" + card.isToken() + "). Image is here:" + file.getAbsolutePath() + " (exists=" + file.exists() + ')');
|
||||
if (!file.exists()) {
|
||||
logger.debug("Missing: " + file.getAbsolutePath());
|
||||
|
@ -544,7 +551,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
public void run() {
|
||||
this.cardIndex = 0;
|
||||
|
||||
File base = new File(Constants.IO.imageBaseDir);
|
||||
File base = new File(getImagesDir());
|
||||
if (!base.exists()) {
|
||||
base.mkdir();
|
||||
}
|
||||
|
@ -678,38 +685,78 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
StringBuilder filePath = new StringBuilder();
|
||||
File temporaryFile = null;
|
||||
TFile outputFile = null;
|
||||
if (cancel) {
|
||||
synchronized (sync) {
|
||||
update(cardIndex + 1, count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
TFile fileTempImage;
|
||||
TFile destFile;
|
||||
try {
|
||||
filePath.append(Constants.IO.imageBaseDir);
|
||||
if (!useSpecifiedPaths && card != null) {
|
||||
filePath.append(card.hashCode()).append('.').append(card.getName().replace(":", "").replace("//", "-")).append(".jpg");
|
||||
temporaryFile = new File(filePath.toString());
|
||||
}
|
||||
String imagePath;
|
||||
if (useSpecifiedPaths) {
|
||||
if (card != null && card.isToken()) {
|
||||
imagePath = CardImageUtils.getTokenBasePath() + actualFilename;
|
||||
} else if (card != null) {
|
||||
imagePath = CardImageUtils.getImageBasePath() + actualFilename;
|
||||
} else {
|
||||
imagePath = Constants.IO.imageBaseDir;
|
||||
}
|
||||
|
||||
String tmpFile = filePath + "temporary" + actualFilename;
|
||||
temporaryFile = new File(tmpFile);
|
||||
if (!temporaryFile.exists()) {
|
||||
temporaryFile.getParentFile().mkdirs();
|
||||
if (card == null){
|
||||
synchronized (sync) {
|
||||
update(cardIndex + 1, count);
|
||||
}
|
||||
} else {
|
||||
imagePath = CardImageUtils.generateImagePath(card);
|
||||
return;
|
||||
}
|
||||
|
||||
outputFile = new TFile(imagePath);
|
||||
if (!outputFile.exists()) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
// gen temp file (download to images folder)
|
||||
String tempPath = getImagesDir() + File.separator + "downloading" + File.separator;
|
||||
if(useSpecifiedPaths){
|
||||
fileTempImage = new TFile(tempPath + actualFilename + "-" + card.hashCode() + ".jpg");
|
||||
}else{
|
||||
fileTempImage = new TFile(tempPath + CardImageUtils.prepareCardNameForFile(card.getName()) + "-" + card.hashCode() + ".jpg");
|
||||
}
|
||||
if(!fileTempImage.getParentFile().exists()){
|
||||
fileTempImage.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
// gen dest file name
|
||||
if(useSpecifiedPaths)
|
||||
{
|
||||
if(card.isToken()){
|
||||
destFile = new TFile(CardImageUtils.buildImagePathToSet(card) + actualFilename + ".jpg");
|
||||
}else{
|
||||
destFile = new TFile(CardImageUtils.buildImagePathToTokens() + actualFilename + ".jpg");
|
||||
}
|
||||
}else{
|
||||
destFile = new TFile(CardImageUtils.buildImagePathToCard(card));
|
||||
}
|
||||
|
||||
// FILE already exists (in zip or in dir)
|
||||
if (destFile.exists()){
|
||||
synchronized (sync) {
|
||||
update(cardIndex + 1, count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// zip can't be read
|
||||
TFile testArchive = destFile.getTopLevelArchive();
|
||||
if (testArchive != null && testArchive.exists()) {
|
||||
try {
|
||||
testArchive.list();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error reading archive, may be it was corrapted. Try to delete it: " + testArchive.toString());
|
||||
|
||||
synchronized (sync) {
|
||||
update(cardIndex + 1, count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(!destFile.getParentFile().exists()){
|
||||
destFile.getParentFile().mkdirs();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// WTF start?! TODO: wtf
|
||||
File existingFile = new File(imagePath.replaceFirst("\\w{3}.zip", ""));
|
||||
if (existingFile.exists()) {
|
||||
try {
|
||||
|
@ -727,7 +774,87 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
}
|
||||
return;
|
||||
}
|
||||
// WTF end?!
|
||||
*/
|
||||
|
||||
|
||||
// START to download
|
||||
cardImageSource.doPause(url.getPath());
|
||||
URLConnection 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.connect();
|
||||
int responseCode = ((HttpURLConnection) httpConn).getResponseCode();
|
||||
|
||||
if (responseCode == 200){
|
||||
// download OK
|
||||
// save data to temp
|
||||
BufferedOutputStream out;
|
||||
try (BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream())) {
|
||||
out = new BufferedOutputStream(new TFileOutputStream(fileTempImage));
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) != -1) {
|
||||
// user cancelled
|
||||
if (cancel) {
|
||||
in.close();
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
// stop download, save current state and exit
|
||||
TFile archive = destFile.getTopLevelArchive();
|
||||
///* not need to unmout/close - it's auto action
|
||||
if (archive != null && archive.exists()){
|
||||
logger.info("User canceled download. Closing archive file: " + destFile.toString());
|
||||
try {
|
||||
TVFS.umount(archive);
|
||||
}catch (Exception e) {
|
||||
logger.error("Can't close archive file: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}//*/
|
||||
try {
|
||||
TFile.rm(fileTempImage);
|
||||
}catch (Exception e) {
|
||||
logger.error("Can't delete temp file: " + e.getMessage(), e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
// TODO: remove to finnaly section?
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
// TODO: add two faces card correction? (WTF)
|
||||
|
||||
// SAVE final data
|
||||
if (fileTempImage.exists()) {
|
||||
if (!destFile.getParentFile().exists()){
|
||||
destFile.getParentFile().mkdirs();
|
||||
}
|
||||
new TFile(fileTempImage).cp_rp(destFile);
|
||||
try {
|
||||
TFile.rm(fileTempImage);
|
||||
}catch (Exception e) {
|
||||
logger.error("Can't delete temp file: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
}else{
|
||||
// download ERROR
|
||||
logger.warn("Image download for " + card.getName()
|
||||
+ (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "")
|
||||
+ " (" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString()
|
||||
);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
// Shows the returned html from the request to the web server
|
||||
logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Logger.getLogger(this.getClass()).info(url.toString());
|
||||
boolean useTempFile = false;
|
||||
int responseCode = 0;
|
||||
|
@ -736,7 +863,6 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (temporaryFile != null && temporaryFile.length() > 100) {
|
||||
useTempFile = true;
|
||||
} else {
|
||||
|
||||
cardImageSource.doPause(url.getPath());
|
||||
httpConn = url.openConnection(p);
|
||||
httpConn.connect();
|
||||
|
@ -768,6 +894,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
out.close();
|
||||
}
|
||||
|
||||
// TODO: WTF?! start
|
||||
if (card != null && card.isTwoFacedCard()) {
|
||||
BufferedImage image = ImageIO.read(temporaryFile);
|
||||
if (image.getHeight() == 470) {
|
||||
|
@ -790,6 +917,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
outputFile.getParentFile().mkdirs();
|
||||
new TFile(temporaryFile).cp_rp(outputFile);
|
||||
}
|
||||
// WTF?! end
|
||||
} else {
|
||||
if (card != null && !useSpecifiedPaths) {
|
||||
logger.warn("Image download for " + card.getName()
|
||||
|
@ -800,16 +928,15 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream()));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} catch (AccessDeniedException e) {
|
||||
logger.error("The file " + (outputFile != null ? outputFile.toString() : "to add the image of " + card.getName() + '(' + card.getSet() + ')') + " can't be accessed. Try rebooting your system to remove the file lock.");
|
||||
logger.error("Can't access to files: " + card.getName() + "(" + card.getSet() + "). Try rebooting your system to remove the file lock.");
|
||||
} catch (Exception e) {
|
||||
logger.error(e, e);
|
||||
logger.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (temporaryFile != null) {
|
||||
temporaryFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (sync) {
|
||||
update(cardIndex + 1, count);
|
||||
}
|
||||
|
@ -823,7 +950,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
iwp.setCompressionQuality(0.96f);
|
||||
|
||||
File tempFile = new File(Constants.IO.imageBaseDir + File.separator + image.hashCode() + file.getName());
|
||||
File tempFile = new File(getImagesDir() + File.separator + image.hashCode() + file.getName());
|
||||
FileImageOutputStream output = new FileImageOutputStream(tempFile);
|
||||
writer.setOutput(output);
|
||||
IIOImage image2 = new IIOImage(image, null, null);
|
||||
|
@ -846,7 +973,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
} else {
|
||||
List<CardDownloadData> remainingCards = Collections.synchronizedList(new ArrayList<>());
|
||||
DownloadPictures.this.allCardsMissingImage.parallelStream().forEach(cardDownloadData -> {
|
||||
TFile file = new TFile(CardImageUtils.generateImagePath(cardDownloadData));
|
||||
TFile file = new TFile(CardImageUtils.buildImagePathToCard(cardDownloadData));
|
||||
if (!file.exists()) {
|
||||
remainingCards.add(cardDownloadData);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package org.mage.plugins.card.images;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ComputationException;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -18,9 +20,9 @@ import net.java.truevfs.access.TFile;
|
|||
import net.java.truevfs.access.TFileInputStream;
|
||||
import net.java.truevfs.access.TFileOutputStream;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
import mage.client.constants.Constants;
|
||||
|
||||
/**
|
||||
* This class stores ALL card images in a cache with soft values. this means
|
||||
|
@ -44,6 +46,7 @@ public final class ImageCache {
|
|||
private static final Logger LOGGER = Logger.getLogger(ImageCache.class);
|
||||
|
||||
private static final Map<String, BufferedImage> IMAGE_CACHE;
|
||||
private static final Map<String, BufferedImage> FACE_IMAGE_CACHE;
|
||||
|
||||
/**
|
||||
* Common pattern for keys. Format: "<cardname>#<setname>#<collectorID>"
|
||||
|
@ -81,15 +84,17 @@ public final class ImageCache {
|
|||
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
|
||||
|
||||
boolean cardback = false;
|
||||
String path;
|
||||
if (collectorId.isEmpty() || "0".equals(collectorId)) {
|
||||
info.setToken(true);
|
||||
path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename;
|
||||
cardback = true;
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename; // TODO: replace empty token by other default card, not cardback
|
||||
}
|
||||
} else {
|
||||
path = CardImageUtils.generateImagePath(info);
|
||||
path = CardImageUtils.buildImagePathToCard(info);
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
|
@ -101,6 +106,7 @@ public final class ImageCache {
|
|||
}
|
||||
|
||||
if (thumbnail && path.endsWith(".jpg")) {
|
||||
// need thumbnail image
|
||||
String thumbnailPath = buildThumbnailPath(path);
|
||||
TFile thumbnailFile = null;
|
||||
try {
|
||||
|
@ -123,14 +129,29 @@ public final class ImageCache {
|
|||
+ ", thumbnail file is probably broken, attempting to recreate it...");
|
||||
thumbnailImage = makeThumbnailByFile(key, file, thumbnailPath);
|
||||
}
|
||||
|
||||
if (cardback){
|
||||
// unknown tokens on opponent desk
|
||||
thumbnailImage = getRoundCorner(thumbnailImage);
|
||||
}
|
||||
|
||||
return thumbnailImage;
|
||||
} else {
|
||||
return makeThumbnailByFile(key, file, thumbnailPath);
|
||||
}
|
||||
} else {
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
return image;
|
||||
if (cardback){
|
||||
// need cardback image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}else {
|
||||
// need normal card image
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
|
@ -145,6 +166,56 @@ public final class ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
public BufferedImage makeThumbnailByFile(String key, TFile file, String thumbnailPath) {
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
image = getRoundCorner(image);
|
||||
if (image == null) {
|
||||
return null;
|
||||
}
|
||||
LOGGER.debug("creating thumbnail for " + key);
|
||||
return makeThumbnail(image, thumbnailPath);
|
||||
}
|
||||
});
|
||||
|
||||
FACE_IMAGE_CACHE = new MapMaker().softValues().makeComputingMap(new Function<String, BufferedImage>() {
|
||||
@Override
|
||||
public BufferedImage apply(String key) {
|
||||
try {
|
||||
|
||||
Matcher m = KEY_PATTERN.matcher(key);
|
||||
|
||||
if (m.matches()) {
|
||||
String name = m.group(1);
|
||||
String set = m.group(2);
|
||||
//Integer artid = Integer.parseInt(m.group(2));
|
||||
|
||||
String path;
|
||||
path = CardImageUtils.generateFaceImagePath(name, set);
|
||||
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedImage image = loadImage(file);
|
||||
return image;
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Requested face image doesn't fit the requirement for key (<cardname>#<artid>#: " + key);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (ex instanceof ComputationException) {
|
||||
throw (ComputationException) ex;
|
||||
} else {
|
||||
throw new ComputationException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage makeThumbnailByFile(String key, TFile file, String thumbnailPath) {
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getWizardsCard(image);
|
||||
|
@ -189,10 +260,10 @@ public final class ImageCache {
|
|||
info.setToken(true);
|
||||
path = CardImageUtils.generateFullTokenImagePath(info);
|
||||
if (path == null) {
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename;
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename; // TODO: replace empty token by other default card, not cardback
|
||||
}
|
||||
} else {
|
||||
path = CardImageUtils.generateImagePath(info);
|
||||
path = CardImageUtils.buildImagePathToCard(info);
|
||||
}
|
||||
|
||||
if (thumbnail && path.endsWith(".jpg")) {
|
||||
|
@ -207,6 +278,12 @@ public final class ImageCache {
|
|||
private ImageCache() {
|
||||
}
|
||||
|
||||
public static BufferedImage getCardbackImage() {
|
||||
BufferedImage image = ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
public static BufferedImage getMorphImage() {
|
||||
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", "");
|
||||
info.setToken(true);
|
||||
|
@ -215,7 +292,10 @@ public final class ImageCache {
|
|||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
return loadImage(file);
|
||||
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
public static BufferedImage getManifestImage() {
|
||||
|
@ -226,7 +306,10 @@ public final class ImageCache {
|
|||
return null;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
return loadImage(file);
|
||||
|
||||
BufferedImage image = loadImage(file);
|
||||
image = getRoundCorner(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
private static String buildThumbnailPath(String path) {
|
||||
|
@ -239,6 +322,32 @@ public final class ImageCache {
|
|||
return thumbnailPath;
|
||||
}
|
||||
|
||||
public static BufferedImage getRoundCorner(BufferedImage image){
|
||||
if (image != null) {
|
||||
BufferedImage cornerImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
// corner
|
||||
float ROUNDED_CORNER_SIZE = 0.11f; // see CardPanelComponentImpl
|
||||
int cornerSizeBorder = Math.max(4, Math.round(image.getWidth() * ROUNDED_CORNER_SIZE));
|
||||
|
||||
// corner mask
|
||||
Graphics2D gg = cornerImage.createGraphics();
|
||||
gg.setComposite(AlphaComposite.Src);
|
||||
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
gg.setColor(Color.white);
|
||||
gg.fill(new RoundRectangle2D.Float(0, 0, cornerImage.getWidth(), cornerImage.getHeight(), cornerSizeBorder, cornerSizeBorder));
|
||||
|
||||
// image draw to buffer
|
||||
gg.setComposite(AlphaComposite.SrcAtop);
|
||||
gg.drawImage(image, 0, 0, null);
|
||||
gg.dispose();
|
||||
|
||||
return cornerImage;
|
||||
} else {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage getWizardsCard(BufferedImage image) {
|
||||
if (image != null && image.getWidth() == 265 && image.getHeight() == 370) {
|
||||
BufferedImage crop = new BufferedImage(256, 360, BufferedImage.TYPE_INT_RGB);
|
||||
|
@ -251,6 +360,23 @@ public final class ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isFaceImagePresent(CardView card) {
|
||||
String path;
|
||||
path = CardImageUtils.generateFaceImagePath(card.getName(), card.getExpansionSetCode());
|
||||
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
TFile file = getTFile(path);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static BufferedImage getThumbnail(CardView card) {
|
||||
return getImage(getKey(card, card.getName(), "#thumb"));
|
||||
}
|
||||
|
@ -263,6 +389,10 @@ public final class ImageCache {
|
|||
return getImage(getKey(card, card.getName(), ""));
|
||||
}
|
||||
|
||||
public static BufferedImage getImageFaceOriginal(CardView card) {
|
||||
return getFaceImage(getFaceKey(card, card.getName(), card.getExpansionSetCode()));
|
||||
}
|
||||
|
||||
public static BufferedImage getImageOriginalAlternateName(CardView card) {
|
||||
return getImage(getKey(card, card.getAlternateName(), ""));
|
||||
}
|
||||
|
@ -288,6 +418,27 @@ public final class ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key
|
||||
*/
|
||||
private static BufferedImage getFaceImage(String key) {
|
||||
try {
|
||||
return FACE_IMAGE_CACHE.get(key);
|
||||
} catch (NullPointerException ex) {
|
||||
// unfortunately NullOutputException, thrown when apply() returns
|
||||
// null, is not public
|
||||
// NullOutputException is a subclass of NullPointerException
|
||||
// legitimate, happens when a card has no image
|
||||
return null;
|
||||
} catch (ComputationException ex) {
|
||||
if (ex.getCause() instanceof NullPointerException) {
|
||||
return null;
|
||||
}
|
||||
LOGGER.error(ex, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key only if it already exists in
|
||||
* the cache.
|
||||
|
@ -296,6 +447,14 @@ public final class ImageCache {
|
|||
return IMAGE_CACHE.containsKey(key) ? IMAGE_CACHE.get(key) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key only if it already exists in
|
||||
* the cache.
|
||||
*/
|
||||
private static BufferedImage tryGetFaceImage(String key) {
|
||||
return FACE_IMAGE_CACHE.containsKey(key) ? FACE_IMAGE_CACHE.get(key) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map key for a card, without any suffixes for the image size.
|
||||
*/
|
||||
|
@ -307,6 +466,13 @@ public final class ImageCache {
|
|||
+ (card.getTokenDescriptor() != null ? '#' + card.getTokenDescriptor() : "#");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map key for a card, without any suffixes for the image size.
|
||||
*/
|
||||
private static String getFaceKey(CardView card, String name, String set) {
|
||||
return name + '#' + set + "####";
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns the map key for the flip image of a card, without any suffixes for the image size.
|
||||
// */
|
||||
|
@ -409,6 +575,25 @@ public final class ImageCache {
|
|||
return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image appropriate to display the card in the picture panel
|
||||
*
|
||||
* @param card
|
||||
* @param width
|
||||
* @param height
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage getFaceImage(CardView card, int width, int height) {
|
||||
String key = getFaceKey(card, card.getName(), card.getExpansionSetCode());
|
||||
BufferedImage original = getFaceImage(key);
|
||||
if (original == null) {
|
||||
LOGGER.debug(key + " (faceimage) not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image appropriate to display for a card in a picture panel,
|
||||
* but only it was ALREADY LOADED. That is, the call is immediate and will
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
import mage.client.constants.Constants;
|
||||
|
||||
public class SettingsManager {
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.mage.plugins.card.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.prefs.Preferences;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.constants.Constants;
|
||||
|
@ -48,7 +48,7 @@ public final class CardImageUtils {
|
|||
log.warn("Token image file not found: " + card.getSet() + " - " + card.getTokenSetCode() + " - " + card.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param card
|
||||
|
@ -63,7 +63,7 @@ public final class CardImageUtils {
|
|||
}
|
||||
|
||||
private static String getTokenImagePath(CardDownloadData card) {
|
||||
String filename = generateImagePath(card);
|
||||
String filename = buildImagePathToCard(card);
|
||||
|
||||
TFile file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
|
@ -74,12 +74,12 @@ public final class CardImageUtils {
|
|||
if (!file.exists()) {
|
||||
CardDownloadData updated = new CardDownloadData(card);
|
||||
updated.setName(card.getName() + " 1");
|
||||
filename = generateImagePath(updated);
|
||||
filename = buildImagePathToCard(updated);
|
||||
file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
updated = new CardDownloadData(card);
|
||||
updated.setName(card.getName() + " 2");
|
||||
filename = generateImagePath(updated);
|
||||
filename = buildImagePathToCard(updated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,94 +121,136 @@ public final class CardImageUtils {
|
|||
return set;
|
||||
}
|
||||
|
||||
private static String getImageDir(CardDownloadData card, String imagesPath) {
|
||||
public static String prepareCardNameForFile(String cardName) {
|
||||
return cardName.replace(":", "").replace("\"", "").replace("//", "-");
|
||||
}
|
||||
|
||||
public static String getImagesDir() {
|
||||
// return real images dir (path without separator)
|
||||
|
||||
String path = null;
|
||||
|
||||
// user path
|
||||
if (!PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true").equals("true")) {
|
||||
path = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
}
|
||||
|
||||
// default path
|
||||
if (path == null) {
|
||||
path = Constants.IO.DEFAULT_IMAGES_DIR;
|
||||
}
|
||||
|
||||
while (path.endsWith(File.separator)) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static String buildImagePathToTokens() {
|
||||
String imagesPath = getImagesDir() + File.separator;
|
||||
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesPath + "TOK.zip" + File.separator;
|
||||
} else {
|
||||
return imagesPath + "TOK" + File.separator;
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildImagePathToTokenDescriptor(CardDownloadData card) {
|
||||
return buildImagePathToTokens() + card.getTokenDescriptor() + ".full.jpg";
|
||||
}
|
||||
|
||||
public static String buildImagePathToSet(CardDownloadData card) {
|
||||
|
||||
if (card.getSet() == null) {
|
||||
return "";
|
||||
throw new IllegalArgumentException("Card " + card.getName() + " have empty set.");
|
||||
}
|
||||
String set = updateSet(card.getSet(), false).toUpperCase();
|
||||
String imagesDir = (imagesPath != null ? imagesPath : Constants.IO.imageBaseDir);
|
||||
|
||||
String set = updateSet(card.getSet(), false).toUpperCase(); // TODO: research auto-replace... old code?
|
||||
|
||||
if (card.isToken()) {
|
||||
return buildTokenPath(imagesDir, set);
|
||||
return buildImagePathToSetAsToken(set);
|
||||
} else {
|
||||
return buildPath(imagesDir, set);
|
||||
return buildImagePathToSetAsCard(set);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getImageBasePath() {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String imagesPath = Objects.equals(useDefault, "true") ? Constants.IO.imageBaseDir : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
private static String buildImagePathToSetAsCard(String set) {
|
||||
String imagesPath = getImagesDir() + File.separator;
|
||||
|
||||
if (imagesPath != null && !imagesPath.endsWith(TFile.separator)) {
|
||||
imagesPath += TFile.separator;
|
||||
}
|
||||
return imagesPath;
|
||||
}
|
||||
|
||||
public static String getTokenBasePath() {
|
||||
String imagesPath = getImageBasePath();
|
||||
|
||||
String finalPath = "";
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
finalPath = imagesPath + "TOK" + ".zip" + TFile.separator;
|
||||
return imagesPath + set + ".zip" + File.separator + set + File.separator;
|
||||
} else {
|
||||
finalPath = imagesPath + "TOK" + TFile.separator;
|
||||
}
|
||||
return finalPath;
|
||||
}
|
||||
|
||||
private static String getTokenDescriptorImagePath(CardDownloadData card) {
|
||||
return getTokenBasePath() + card.getTokenDescriptor() + ".full.jpg";
|
||||
}
|
||||
|
||||
private static String buildTokenPath(String imagesDir, String set) {
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesDir + TFile.separator + "TOK" + ".zip" + TFile.separator + set;
|
||||
} else {
|
||||
return imagesDir + TFile.separator + "TOK" + TFile.separator + set;
|
||||
return imagesPath + set + File.separator;
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildPath(String imagesDir, String set) {
|
||||
if (PreferencesDialog.isSaveImagesToZip()) {
|
||||
return imagesDir + TFile.separator + set + ".zip" + TFile.separator + set;
|
||||
} else {
|
||||
return imagesDir + TFile.separator + set;
|
||||
}
|
||||
private static String buildImagePathToSetAsToken(String set) {
|
||||
return buildImagePathToTokens() + set + File.separator;
|
||||
}
|
||||
|
||||
public static String generateImagePath(CardDownloadData card) {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String imagesPath = Objects.equals(useDefault, "true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
public static String buildImagePathToCard(CardDownloadData card) {
|
||||
|
||||
String imageDir = getImageDir(card, imagesPath);
|
||||
String imageName;
|
||||
String setPath = buildImagePathToSet(card);
|
||||
|
||||
String type = card.getType() != 0 ? ' ' + Integer.toString(card.getType()) : "";
|
||||
String name = card.getFileName().isEmpty() ? card.getName().replace(":", "").replace("//", "-") : card.getFileName();
|
||||
String prefixType = "";
|
||||
if (card.getType() != 0) {
|
||||
prefixType = " " + Integer.toString(card.getType());
|
||||
}
|
||||
|
||||
String cardName = card.getFileName();
|
||||
if (cardName.isEmpty()) {
|
||||
cardName = prepareCardNameForFile(card.getName());
|
||||
}
|
||||
|
||||
String finalFileName = "";
|
||||
if (card.getUsesVariousArt()) {
|
||||
imageName = name + '.' + card.getCollectorId() + ".full.jpg";
|
||||
finalFileName = cardName + '.' + card.getCollectorId() + ".full.jpg";
|
||||
} else {
|
||||
imageName = name + type + ".full.jpg";
|
||||
}
|
||||
|
||||
if (new TFile(imageDir).exists() && !new TFile(imageDir + TFile.separator + imageName).exists()) {
|
||||
for (String fileName : new TFile(imageDir).list()) {
|
||||
if (fileName.toLowerCase().equals(imageName.toLowerCase())) {
|
||||
imageName = fileName;
|
||||
break;
|
||||
if (card.getUsesVariousArt()){
|
||||
// only various arts can be same name, but different postfixes (a,b,c,d,e)
|
||||
int len = card.getCollectorId().length();
|
||||
if (Character.isLetter(card.getCollectorId().charAt(len - 1))) {
|
||||
finalFileName = cardName + card.getCollectorId().charAt(len - 1) + ".full.jpg";
|
||||
} else {
|
||||
finalFileName = cardName + prefixType + ".full.jpg";
|
||||
}
|
||||
} else {
|
||||
// normal cards with same names;
|
||||
finalFileName = cardName + prefixType + ".full.jpg";
|
||||
}
|
||||
}
|
||||
|
||||
return imageDir + TFile.separator + imageName;
|
||||
// if image file exists, correct name (for case sensitive systems)
|
||||
// use TFile for zips
|
||||
TFile dirFile = new TFile(setPath);
|
||||
TFile imageFile = new TFile(setPath + finalFileName);
|
||||
// warning, zip files can be broken
|
||||
try {
|
||||
if (dirFile.exists() && !imageFile.exists()) {
|
||||
// search like names
|
||||
for (String fileName : dirFile.list()) {
|
||||
if (fileName.toLowerCase().equals(finalFileName.toLowerCase())) {
|
||||
finalFileName = fileName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("Can't read card name from file, may be it broken: " + setPath);
|
||||
}
|
||||
|
||||
return setPath + finalFileName;
|
||||
}
|
||||
|
||||
public static String generateFaceImagePath(String cardname, String set) {
|
||||
return getImagesDir() + File.separator + "FACE" + File.separator + set + File.separator + prepareCardNameForFile(cardname) + ".jpg";
|
||||
}
|
||||
|
||||
public static String generateTokenDescriptorImagePath(CardDownloadData card) {
|
||||
// String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
// String imagesPath = Objects.equals(useDefault, "true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
|
||||
String straightImageFile = getTokenDescriptorImagePath(card);
|
||||
String straightImageFile = buildImagePathToTokenDescriptor(card);
|
||||
TFile file = new TFile(straightImageFile);
|
||||
if (file.exists()) {
|
||||
return straightImageFile;
|
||||
|
|
BIN
Mage.Client/src/main/resources/buttons/rarity_common_20.png
Normal file
After Width: | Height: | Size: 565 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_common_32.png
Normal file
After Width: | Height: | Size: 849 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_mythic_20.png
Normal file
After Width: | Height: | Size: 563 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_mythic_32.png
Normal file
After Width: | Height: | Size: 753 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_rare_20.png
Normal file
After Width: | Height: | Size: 541 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_rare_32.png
Normal file
After Width: | Height: | Size: 767 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_special_20.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_special_32.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
Mage.Client/src/main/resources/buttons/rarity_uncommon_20.png
Normal file
After Width: | Height: | Size: 444 B |
BIN
Mage.Client/src/main/resources/buttons/rarity_uncommon_32.png
Normal file
After Width: | Height: | Size: 644 B |
BIN
Mage.Client/src/main/resources/buttons/search_128.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
Mage.Client/src/main/resources/buttons/search_24.png
Normal file
After Width: | Height: | Size: 595 B |
BIN
Mage.Client/src/main/resources/buttons/search_32.png
Normal file
After Width: | Height: | Size: 831 B |
BIN
Mage.Client/src/main/resources/buttons/search_64.png
Normal file
After Width: | Height: | Size: 2 KiB |
|
@ -501,6 +501,7 @@
|
|||
|Generate|TOK:E01|Soldier|||SoldierToken|
|
||||
|Generate|TOK:E01|Spirit|||SpiritWhiteToken|
|
||||
|Generate|TOK:E01|Zombie|||ZombieToken|
|
||||
|Generate|TOK:E02|Saproling|||SaprolingToken|
|
||||
|Generate|TOK:EMA|Assembly-Worker|||AssemblyWorkerToken|
|
||||
|Generate|TOK:EMA|Beast|||CarnivoreToken|
|
||||
|Generate|TOK:EMA|Carnivore||
|
||||
|
@ -1062,6 +1063,7 @@
|
|||
|Generate|TOK:USG|Minion|||MinionToken|
|
||||
|Generate|TOK:USG|Saproling|||SaprolingToken|
|
||||
|Generate|TOK:UST|Dragon|||DragonTokenGold|
|
||||
|Generate|TOK:UST|StormCrow|||StormCrowToken|
|
||||
|Generate|TOK:V10|Wolf|||WolfToken|
|
||||
|Generate|TOK:V11|Faerie Rogue|||OonaQueenFaerieToken|
|
||||
|Generate|TOK:V12|Spirit|||SpiritToken|
|
||||
|
@ -1118,4 +1120,4 @@
|
|||
|Generate|TOK:ZEN|Snake|||SnakeToken|
|
||||
|Generate|TOK:ZEN|Vampire||
|
||||
|Generate|TOK:ZEN|Wolf|||WolfToken|
|
||||
|Generate|TOK:ZEN|Zombie Giant|||QuestForTheGravelordZombieToken|
|
||||
|Generate|TOK:ZEN|Zombie Giant|||QuestForTheGravelordZombieToken|
|
|
@ -29,7 +29,6 @@ ulg=ul
|
|||
6ed=6e
|
||||
btd=bd
|
||||
sth=sh
|
||||
nem=ne
|
||||
por=po
|
||||
s99=st
|
||||
lgn=le
|
||||
|
@ -74,6 +73,6 @@ dd3evg=ddaevg
|
|||
dd3gvl=ddagvl
|
||||
dd3jvc=ddajvc
|
||||
# Remove setname as soon as the images can be downloaded
|
||||
ignore.urls=TOK,DDT,V17,RIX,E02,M19,M25,DOM,UST,H17
|
||||
ignore.urls=TOK,M19,M25,DOM,H17
|
||||
# sets ordered by release time (newest goes first)
|
||||
token.lookup.order=M19,M25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
BIN
Mage.Client/src/main/resources/label-xmage-christmas.png
Normal file
After Width: | Height: | Size: 141 KiB |
43
Mage.Client/src/test/java/mage/client/util/ChrismasTest.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package mage.client.util;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import static mage.client.MageFrame.isChrismasTime;
|
||||
|
||||
public class ChrismasTest {
|
||||
|
||||
private Date getDate(int Year, int Month, int Day){
|
||||
Calendar cal = new GregorianCalendar(Year, Month - 1, Day);
|
||||
cal.add(Calendar.HOUR, 10);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChrismasDays() throws Exception {
|
||||
// chrismas from 15 december to 15 january
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2017, 11, 1)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2017, 11, 15)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2017, 11, 30)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2017, 12, 1)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2017, 12, 14)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2017, 12, 15)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2017, 12, 16)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2017, 12, 31)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2018, 1, 1)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2018, 1, 14)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2018, 1, 15)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2018, 1, 16)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2018, 1, 31)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2018, 2, 1)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2018, 12, 1)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2018, 12, 20)));
|
||||
Assert.assertEquals(true, isChrismasTime(getDate(2019, 1, 10)));
|
||||
Assert.assertEquals(false, isChrismasTime(getDate(2019, 1, 25)));
|
||||
}
|
||||
|
||||
}
|
|
@ -25,8 +25,8 @@ public abstract class MageCard extends JPanel {
|
|||
|
||||
public abstract CardView getOriginal();
|
||||
|
||||
// sets the vertical text offset for the card name on the image
|
||||
public abstract void setTextOffset(int yOffset);
|
||||
// sets the vertical text offset for the card name on the image, use to move caption to card center
|
||||
public abstract void setCardCaptionTopOffset(int yOffsetPercent);
|
||||
|
||||
public abstract void setCardBounds(int x, int y, int width, int height);
|
||||
|
||||
|
|
|
@ -32,10 +32,9 @@ public interface CardPlugin extends Plugin {
|
|||
/**
|
||||
* Download various symbols (mana, tap, set).
|
||||
*
|
||||
* @param imagesPath Path to check in and store symbols to. Can be null, in
|
||||
* such case default path should be used.
|
||||
* @param imagesDir Path to check in and store symbols to. Can't be null.
|
||||
*/
|
||||
void downloadSymbols(String imagesPath);
|
||||
void downloadSymbols(String imagesDir);
|
||||
|
||||
void onAddCard(MagePermanent card, int count);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
|||
public final static int MAGE_VERSION_MAJOR = 1;
|
||||
public final static int MAGE_VERSION_MINOR = 4;
|
||||
public final static int MAGE_VERSION_PATCH = 26;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "V7";
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "V11b";
|
||||
public final static String MAGE_VERSION_INFO = "";
|
||||
|
||||
private final int major;
|
||||
|
|
|
@ -114,7 +114,39 @@ public class AusHighlander extends Constructed {
|
|||
int totalPoints = 0;
|
||||
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
|
||||
String cn = entry.getKey();
|
||||
|
||||
if (cn.equals("Ancestral Recall")
|
||||
|| cn.equals("Black Lotus")
|
||||
|| cn.equals("Time Vault")) {
|
||||
totalPoints += 4;
|
||||
invalid.put(cn, "4 points");
|
||||
}
|
||||
if (cn.equals("Demonic Tutor")
|
||||
|| cn.equals("Imperial Seal")
|
||||
|| cn.equals("Mox Emerald")
|
||||
|| cn.equals("Mox Jet")
|
||||
|| cn.equals("Mox Pearl")
|
||||
|| cn.equals("Mox Ruby")
|
||||
|| cn.equals("Sol Ring")
|
||||
|| cn.equals("Time Walk")
|
||||
|| cn.equals("Tinker")
|
||||
|| cn.equals("Vampiric Tutor")
|
||||
|| cn.equals("Yawgmoth's Will")
|
||||
|| cn.equals("Mox Sapphire.")) {
|
||||
totalPoints += 3;
|
||||
invalid.put(cn, "3 points");
|
||||
}
|
||||
if (cn.equals("Channel")
|
||||
|| cn.equals("Dig Through Time")
|
||||
|| cn.equals("Library of Alexandria")
|
||||
|| cn.equals("Mana Crypt")
|
||||
|| cn.equals("Mystical Tutor")
|
||||
|| cn.equals("Protean Hulk")
|
||||
|| cn.equals("Skullclamp")
|
||||
|| cn.equals("Strip Mine")
|
||||
|| cn.equals("Tolarian Academy.")) {
|
||||
totalPoints += 2;
|
||||
invalid.put(cn, "2 points");
|
||||
}
|
||||
if (cn.equals("Back to Basics")
|
||||
|| cn.equals("Balance")
|
||||
|| cn.equals("Birthing Pod")
|
||||
|
@ -139,8 +171,8 @@ public class AusHighlander extends Constructed {
|
|||
|| cn.equals("Natural Order")
|
||||
|| cn.equals("Oath of Druids")
|
||||
|| cn.equals("Personal Tutor")
|
||||
|| cn.equals("Sensei's Divining Top")
|
||||
|| cn.equals("Snapcaster Mage")
|
||||
|| cn.equals("Steelshaper's Gift")
|
||||
|| cn.equals("Stoneforge Mystic")
|
||||
|| cn.equals("Survival of the Fittest")
|
||||
|| cn.equals("Tainted Pact")
|
||||
|
@ -151,50 +183,15 @@ public class AusHighlander extends Constructed {
|
|||
|| cn.equals("Umezawa's Jitte")
|
||||
|| cn.equals("Wasteland")
|
||||
|| cn.equals("Wheel of Fortune")
|
||||
|| cn.equals("Worldly Tutor")
|
||||
|| cn.equals("Yawgmoth's Bargain")) {
|
||||
|| cn.equals("Yawgmoth's Bargain")
|
||||
|| cn.equals("Worldly Tutor")) {
|
||||
totalPoints += 1;
|
||||
invalid.put(cn, "1 point");
|
||||
}
|
||||
|
||||
if (cn.equals("Channel")
|
||||
|| cn.equals("Dig Through Time")
|
||||
|| cn.equals("Library of Alexandria")
|
||||
|| cn.equals("Mana Crypt")
|
||||
|| cn.equals("Mox Emerald")
|
||||
|| cn.equals("Mox Jet")
|
||||
|| cn.equals("Mox Pearl")
|
||||
|| cn.equals("Mox Ruby")
|
||||
|| cn.equals("Mox Sapphire")
|
||||
|| cn.equals("Mystical Tutor")
|
||||
|| cn.equals("Protean Hulk")
|
||||
|| cn.equals("Skullclamp")
|
||||
|| cn.equals("Strip Mine")
|
||||
|| cn.equals("Tolarian Academy")) {
|
||||
totalPoints += 2;
|
||||
invalid.put(cn, "2 points");
|
||||
}
|
||||
|
||||
if (cn.equals("Demonic Tutor")
|
||||
|| cn.equals("Imperial Seal")
|
||||
|| cn.equals("Sol Ring")
|
||||
|| cn.equals("Time Walk")
|
||||
|| cn.equals("Tinker")
|
||||
|| cn.equals("Vampiric Tutor")
|
||||
|| cn.equals("Yawgmoth's Will")) {
|
||||
totalPoints += 3;
|
||||
invalid.put(cn, "3 points");
|
||||
}
|
||||
|
||||
if (cn.equals("Ancestral Recall")
|
||||
|| cn.equals("Black Lotus")
|
||||
|| cn.equals("Time Vault")) {
|
||||
totalPoints += 4;
|
||||
invalid.put(cn, "4 points");
|
||||
}
|
||||
}
|
||||
if (totalPoints > 7) {
|
||||
invalid.put("Total points too high", "Your calculated point total was " + totalPoints);
|
||||
invalid.put("Only you can see this!", "Your opponents will not be able to see this message or what cards are in your deck!");
|
||||
valid = false;
|
||||
}
|
||||
return valid;
|
||||
|
|
|
@ -92,15 +92,14 @@ public class CanadianHighlander extends Constructed {
|
|||
String cn = entry.getKey();
|
||||
if (cn.equals("Balance")
|
||||
|| cn.equals("Dig Through Time")
|
||||
|| cn.equals("Doomsday")
|
||||
|| cn.equals("Enlightened Tutor")
|
||||
|| cn.equals("Fastbond")
|
||||
|| cn.equals("Intuition")
|
||||
|| cn.equals("Library of Alexandria")
|
||||
|| cn.equals("Lim-Dul's Vault")
|
||||
|| cn.equals("Mana Vault")
|
||||
|| cn.equals("Merchant Scroll")
|
||||
|| cn.equals("Mind Twist")
|
||||
|| cn.equals("Oath of Druids")
|
||||
|| cn.equals("Personal Tutor")
|
||||
|| cn.equals("Stoneforge Mystic")
|
||||
|| cn.equals("Tainted Pact")
|
||||
|
@ -112,8 +111,8 @@ public class CanadianHighlander extends Constructed {
|
|||
totalPoints += 1;
|
||||
invalid.put(entry.getKey(), " 1 point " + cn);
|
||||
}
|
||||
if (cn.equals("Doomsday")
|
||||
|| cn.equals("Gifts Ungiven")
|
||||
if (cn.equals("Gifts Ungiven")
|
||||
|| cn.equals("Hermit Druid")
|
||||
|| cn.equals("Imperial Seal")
|
||||
|| cn.equals("Mana Crypt")
|
||||
|| cn.equals("Mystical Tutor")
|
||||
|
@ -125,19 +124,19 @@ public class CanadianHighlander extends Constructed {
|
|||
invalid.put(entry.getKey(), " 2 points " + cn);
|
||||
}
|
||||
if (cn.equals("Birthing Pod")
|
||||
|| cn.equals("Hermit Druid")
|
||||
|| cn.equals("Mox Emerald")
|
||||
|| cn.equals("Mox Jet")
|
||||
|| cn.equals("Mox Pearl")
|
||||
|| cn.equals("Mox Ruby")
|
||||
|| cn.equals("Mox Sapphire")
|
||||
|| cn.equals("Protean Hulk")
|
||||
|| cn.equals("Sol Ring")
|
||||
|| cn.equals("Vampiric Tutor")) {
|
||||
totalPoints += 3;
|
||||
invalid.put(entry.getKey(), " 3 points " + cn);
|
||||
}
|
||||
if (cn.equals("Demonic Tutor")
|
||||
|| cn.equals("Sol Ring")) {
|
||||
|| cn.equals("Tinker")) {
|
||||
totalPoints += 4;
|
||||
invalid.put(entry.getKey(), " 4 points " + cn);
|
||||
}
|
||||
|
@ -147,13 +146,12 @@ public class CanadianHighlander extends Constructed {
|
|||
invalid.put(entry.getKey(), " 5 points " + cn);
|
||||
}
|
||||
if (cn.equals("Ancestral Recall")
|
||||
|| cn.equals("Time Walk")) {
|
||||
|| cn.equals("Time Vault")) {
|
||||
totalPoints += 6;
|
||||
invalid.put(entry.getKey(), " 5 points " + cn);
|
||||
invalid.put(entry.getKey(), " 6 points " + cn);
|
||||
}
|
||||
if (cn.equals("Black Lotus")
|
||||
|| cn.equals("Flash")
|
||||
|| cn.equals("Time Vault")) {
|
||||
|| cn.equals("Flash")) {
|
||||
totalPoints += 7;
|
||||
invalid.put(entry.getKey(), " 7 points " + cn);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class DuelCommander extends Commander {
|
|||
banned.add("Eidolon of the Great Revel");
|
||||
banned.add("Emrakul, the Aeons Torn");
|
||||
banned.add("Entomb");
|
||||
banned.add("Fastbond");
|
||||
banned.add("Fireblast");
|
||||
banned.add("Food Chain");
|
||||
banned.add("Gaea's Cradle");
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.deck;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.abilities.common.CanBeYourCommanderAbility;
|
||||
import mage.abilities.keyword.PartnerAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.decks.Constructed;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.SetType;
|
||||
import mage.filter.FilterMana;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class FreeformCommander extends Constructed {
|
||||
|
||||
protected List<String> bannedCommander = new ArrayList<>();
|
||||
private static final Map<String, Integer> pdAllowed = new HashMap<>();
|
||||
private static boolean setupAllowed = false;
|
||||
|
||||
public FreeformCommander() {
|
||||
this("Freeform Commander");
|
||||
for (ExpansionSet set : Sets.getInstance().values()) {
|
||||
setCodes.add(set.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public FreeformCommander(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(Deck deck) {
|
||||
boolean valid = true;
|
||||
FilterMana colorIdentity = new FilterMana();
|
||||
|
||||
if (deck.getCards().size() + deck.getSideboard().size() != 100) {
|
||||
invalid.put("Deck", "Must contain 100 cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes"));
|
||||
Map<String, Integer> counts = new HashMap<>();
|
||||
countCards(counts, deck.getCards());
|
||||
countCards(counts, deck.getSideboard());
|
||||
|
||||
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
|
||||
if (entry.getValue() > 1) {
|
||||
if (!basicLandNames.contains(entry.getKey())) {
|
||||
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateFreeformHash();
|
||||
|
||||
if (deck.getSideboard().size() < 1 || deck.getSideboard().size() > 2) {
|
||||
invalid.put("Commander", "Sideboard must contain only the commander(s)");
|
||||
valid = false;
|
||||
} else {
|
||||
for (Card commander : deck.getSideboard()) {
|
||||
if (!(commander.isCreature() ||
|
||||
commander.isLegendary())) {
|
||||
invalid.put("Commander", "For Freeform Commander, the commander must be a creature or be legendary. Yours was: " + commander.getName());
|
||||
valid = false;
|
||||
}
|
||||
if (deck.getSideboard().size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) {
|
||||
invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')');
|
||||
valid = false;
|
||||
}
|
||||
FilterMana commanderColor = commander.getColorIdentity();
|
||||
if (commanderColor.isWhite()) {
|
||||
colorIdentity.setWhite(true);
|
||||
}
|
||||
if (commanderColor.isBlue()) {
|
||||
colorIdentity.setBlue(true);
|
||||
}
|
||||
if (commanderColor.isBlack()) {
|
||||
colorIdentity.setBlack(true);
|
||||
}
|
||||
if (commanderColor.isRed()) {
|
||||
colorIdentity.setRed(true);
|
||||
}
|
||||
if (commanderColor.isGreen()) {
|
||||
colorIdentity.setGreen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Card card : deck.getCards()) {
|
||||
if (!cardHasValidColor(colorIdentity, card)) {
|
||||
invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')');
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (!isSetAllowed(card.getExpansionSetCode())) {
|
||||
if (!legalSets(card)) {
|
||||
invalid.put(card.getName(), "Not allowed Set: " + card.getExpansionSetCode());
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public boolean cardHasValidColor(FilterMana commander, Card card) {
|
||||
FilterMana cardColor = card.getColorIdentity();
|
||||
return !(cardColor.isBlack() && !commander.isBlack()
|
||||
|| cardColor.isBlue() && !commander.isBlue()
|
||||
|| cardColor.isGreen() && !commander.isGreen()
|
||||
|| cardColor.isRed() && !commander.isRed()
|
||||
|| cardColor.isWhite() && !commander.isWhite());
|
||||
}
|
||||
|
||||
public void generateFreeformHash() {
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.deck;
|
||||
|
||||
import mage.cards.decks.Constructed;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class IxalanBlock extends Constructed {
|
||||
|
||||
public IxalanBlock() {
|
||||
super("Constructed - Ixalan Block");
|
||||
setCodes.add("XLN");
|
||||
setCodes.add("RIX");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.deck;
|
||||
|
||||
import mage.cards.decks.Constructed;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class LorwynBlock extends Constructed {
|
||||
|
||||
public LorwynBlock() {
|
||||
super("Constructed - Lorwyn Block");
|
||||
setCodes.add("LRW");
|
||||
setCodes.add("MOR");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Mage Game Freeform Commander Free For All</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>mage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
<finalName>mage-game-freeforall</finalName>
|
||||
</build>
|
||||
|
||||
<properties/>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.game.match.MatchType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class FreeformCommanderFreeForAll extends GameCommanderImpl {
|
||||
|
||||
private int numPlayers;
|
||||
|
||||
public FreeformCommanderFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
|
||||
super(attackOption, range, freeMulligans, startLife);
|
||||
}
|
||||
|
||||
public FreeformCommanderFreeForAll(final FreeformCommanderFreeForAll game) {
|
||||
super(game);
|
||||
this.numPlayers = game.numPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
startingPlayerSkipsDraw = false;
|
||||
super.init(choosingPlayerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MatchType getGameType() {
|
||||
return new FreeformCommanderFreeForAllType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumPlayers() {
|
||||
return numPlayers;
|
||||
}
|
||||
|
||||
public void setNumPlayers(int numPlayers) {
|
||||
this.numPlayers = numPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FreeformCommanderFreeForAll copy() {
|
||||
return new FreeformCommanderFreeForAll(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game;
|
||||
|
||||
import mage.game.match.MatchImpl;
|
||||
import mage.game.match.MatchOptions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class FreeformCommanderFreeForAllMatch extends MatchImpl {
|
||||
|
||||
public FreeformCommanderFreeForAllMatch(MatchOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startGame() throws GameException {
|
||||
int startLife = 40;
|
||||
boolean alsoHand = true;
|
||||
FreeformCommanderFreeForAll game = new FreeformCommanderFreeForAll(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife);
|
||||
game.setStartMessage(this.createGameStartMessage());
|
||||
game.setAlsoHand(alsoHand);
|
||||
game.setAlsoLibrary(true);
|
||||
initGame(game);
|
||||
games.add(game);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game;
|
||||
|
||||
import mage.game.match.MatchType;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class FreeformCommanderFreeForAllType extends MatchType {
|
||||
|
||||
public FreeformCommanderFreeForAllType() {
|
||||
this.name = "Freeform Commander Free For All";
|
||||
this.maxPlayers = 10;
|
||||
this.minPlayers = 3;
|
||||
this.numTeams = 0;
|
||||
this.useAttackOption = true;
|
||||
this.useRange = true;
|
||||
this.sideboardingAllowed = false;
|
||||
}
|
||||
|
||||
protected FreeformCommanderFreeForAllType(final FreeformCommanderFreeForAllType matchType) {
|
||||
super(matchType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FreeformCommanderFreeForAllType copy() {
|
||||
return new FreeformCommanderFreeForAllType(this);
|
||||
}
|
||||
}
|
55
Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-momirfreeforall</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Mage Game Momir Basic Free for All</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>mage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>mage-game-freeforall</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
<finalName>mage-game-momir</finalName>
|
||||
</build>
|
||||
|
||||
<properties/>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game;
|
||||
|
||||
import mage.game.match.MatchImpl;
|
||||
import mage.game.match.MatchOptions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nigelzor
|
||||
*/
|
||||
public class MomirFreeForAllMatch extends MatchImpl {
|
||||
|
||||
public MomirFreeForAllMatch(MatchOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startGame() throws GameException {
|
||||
// Momir Vig, Simic Visionary gives +4 starting life
|
||||
int startLife = 24;
|
||||
|
||||
MomirGame game = new MomirGame(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife);
|
||||
game.setStartMessage(this.createGameStartMessage());
|
||||
|
||||
this.initGame(game);
|
||||
games.add(game);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game;
|
||||
|
||||
import mage.game.match.MatchType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nigelzor
|
||||
*/
|
||||
public class MomirFreeForAllType extends MatchType {
|
||||
|
||||
public MomirFreeForAllType() {
|
||||
this.name = "Momir Basic Free For All";
|
||||
this.maxPlayers = 10;
|
||||
this.minPlayers = 2;
|
||||
this.numTeams = 0;
|
||||
this.useAttackOption = true;
|
||||
this.useRange = true;
|
||||
this.sideboardingAllowed = false;
|
||||
}
|
||||
|
||||
protected MomirFreeForAllType(final MomirFreeForAllType matchType){
|
||||
super(matchType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomirFreeForAllType copy() {
|
||||
return new MomirFreeForAllType(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.command.emblems.MomirEmblem;
|
||||
import mage.game.match.MatchType;
|
||||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nigelzor
|
||||
*/
|
||||
public class MomirGame extends FreeForAll {
|
||||
|
||||
private int numPlayers;
|
||||
|
||||
public MomirGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
|
||||
super(attackOption, range, freeMulligans, startLife);
|
||||
}
|
||||
|
||||
public MomirGame(final MomirGame game) {
|
||||
super(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MatchType getGameType() {
|
||||
return new MomirFreeForAllType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumPlayers() {
|
||||
return numPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Vanguard effects"));
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
CardInfo cardInfo = CardRepository.instance.findCard("Momir Vig, Simic Visionary");
|
||||
addEmblem(new MomirEmblem(), cardInfo.getCard(), playerId);
|
||||
}
|
||||
}
|
||||
getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId);
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getOpponents(UUID playerId) {
|
||||
Set<UUID> opponents = new HashSet<>();
|
||||
for (UUID opponentId : this.getPlayer(playerId).getInRange()) {
|
||||
if (!opponentId.equals(playerId)) {
|
||||
opponents.add(opponentId);
|
||||
}
|
||||
}
|
||||
return opponents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomirGame copy() {
|
||||
return new MomirGame(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
#Generated by Maven
|
||||
#Fri Sep 15 22:14:29 CEST 2017
|
||||
version=1.4.26
|
||||
groupId=org.mage
|
||||
artifactId=mage-game-pennydreadfulcommanderfreeforall
|
|
@ -489,7 +489,9 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
maxSeconds = 3600;
|
||||
}
|
||||
logger.debug("maxThink: " + maxSeconds + " seconds ");
|
||||
return task.get(maxSeconds, TimeUnit.SECONDS);
|
||||
if (task.get(maxSeconds, TimeUnit.SECONDS) != null) {
|
||||
return task.get(maxSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
} catch (TimeoutException e) {
|
||||
logger.info("simulating - timed out");
|
||||
task.cancel(true);
|
||||
|
@ -519,7 +521,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
logger.trace("interrupted - " + val);
|
||||
return val;
|
||||
}
|
||||
if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.gameOver(null)) {
|
||||
if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.checkIfGameIsOver()) {
|
||||
logger.trace("Add actions -- reached end state, node count=" + SimulationNode2.nodeCount + ", depth=" + depth);
|
||||
val = GameStateEvaluator2.evaluate(playerId, game);
|
||||
UUID currentPlayerId = node.getGame().getPlayerList().get();
|
||||
|
@ -540,7 +542,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
}
|
||||
}
|
||||
|
||||
if (game.gameOver(null)) {
|
||||
if (game.checkIfGameIsOver()) {
|
||||
val = GameStateEvaluator2.evaluate(playerId, game);
|
||||
} else if (!node.getChildren().isEmpty()) {
|
||||
//declared attackers or blockers or triggered abilities
|
||||
|
@ -588,7 +590,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
logger.debug("Sim Prio [" + depth + "] -- repeated action: " + action.toString());
|
||||
continue;
|
||||
}
|
||||
if (!sim.gameOver(null) && action.isUsesStack()) {
|
||||
if (!sim.checkIfGameIsOver() && action.isUsesStack()) {
|
||||
// only pass if the last action uses the stack
|
||||
UUID nextPlayerId = sim.getPlayerList().get();
|
||||
do {
|
||||
|
@ -765,14 +767,9 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
return super.choose(outcome, choice, game);
|
||||
}
|
||||
if (!choice.isChosen()) {
|
||||
for (String achoice : choices) {
|
||||
choice.setChoice(achoice);
|
||||
if (choice.isChosen()) {
|
||||
choices.clear();
|
||||
return true;
|
||||
}
|
||||
if(!choice.setChoiceByAnswers(choices, true)){
|
||||
choice.setRandomChoice();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -864,7 +861,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
|||
break;
|
||||
case CLEANUP:
|
||||
game.getPhase().getStep().beginStep(game, activePlayerId);
|
||||
if (!game.checkStateAndTriggered() && !game.gameOver(null)) {
|
||||
if (!game.checkStateAndTriggered() && !game.checkIfGameIsOver()) {
|
||||
game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext());
|
||||
game.getTurn().setPhase(new BeginningPhase());
|
||||
game.getPhase().setStep(new UntapStep());
|
||||
|
|