diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index 83e3d152dd..8a312223d6 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -121,10 +121,16 @@ - - - - + + + + + + + + + + @@ -133,7 +139,10 @@ - + + + + @@ -176,6 +185,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 5eabe7d720..eeb58e8d05 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -91,6 +91,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_SHOW_TOOLTIPS_DELAY = "showTooltipsDelay"; public static final String KEY_SHOW_CARD_NAMES = "showCardNames"; + public static final String KEY_SHOW_FULL_IMAGE_PATH = "showFullImagePath"; public static final String KEY_PERMANENTS_IN_ONE_PILE = "nonLandPermanentsInOnePile"; public static final String KEY_SHOW_PLAYER_NAMES_PERMANENTLY = "showPlayerNamesPermanently"; public static final String KEY_SHOW_ABILITY_PICKER_FORCED = "showAbilityPicker"; @@ -399,6 +400,7 @@ public class PreferencesDialog extends javax.swing.JDialog { tabMain = new javax.swing.JPanel(); main_card = new javax.swing.JPanel(); showCardName = new javax.swing.JCheckBox(); + showFullImagePath = new javax.swing.JCheckBox(); tooltipDelayLabel = new javax.swing.JLabel(); tooltipDelay = new javax.swing.JSlider(); main_game = new javax.swing.JPanel(); @@ -613,28 +615,48 @@ public class PreferencesDialog extends javax.swing.JDialog { tooltipDelay.setToolTipText("The time the appearance of the tooltip window for a card is delayed.
\nIf set to zero, the tooltip window won't be shown at all."); tooltipDelay.setValue(300); + showFullImagePath.setSelected(false); + showFullImagePath.setToolTipText("Show the path Xmage is expecting for this card's image (only displays if missing)"); + showFullImagePath.setActionCommand(""); + showFullImagePath.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + showFullImagePath.setLabel("Display image path for missing images"); + showFullImagePath.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showFullImagePathActionPerformed(evt); + } + }); + org.jdesktop.layout.GroupLayout main_cardLayout = new org.jdesktop.layout.GroupLayout(main_card); main_card.setLayout(main_cardLayout); main_cardLayout.setHorizontalGroup( main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(main_cardLayout.createSequentialGroup() .add(6, 6, 6) - .add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) - .add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE) - .add(org.jdesktop.layout.GroupLayout.LEADING, showCardName) - .add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) + .add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE) + .add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .add(main_cardLayout.createSequentialGroup() + .add(showCardName) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(showFullImagePath))) .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); main_cardLayout.setVerticalGroup( main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(main_cardLayout.createSequentialGroup() - .add(showCardName) + .add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(showCardName) + .add(showFullImagePath)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(tooltipDelayLabel) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); + showFullImagePath.getAccessibleContext().setAccessibleName("Display image path for missing images"); + showFullImagePath.getAccessibleContext().setAccessibleDescription("Show the path Xmage is expecting for this card's image (only displays if missing)"); + main_game.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Game")); nonLandPermanentsInOnePile.setSelected(true); @@ -720,7 +742,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(cbAllowRequestToShowHandCards, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(cbShowStormCounter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(cbAskMoveToGraveOrder, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(255, Short.MAX_VALUE)) ); main_gameLayout.setVerticalGroup( main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2679,6 +2701,7 @@ public class PreferencesDialog extends javax.swing.JDialog { // main save(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.showFullImagePath, KEY_SHOW_FULL_IMAGE_PATH, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true", "false", UPDATE_CACHE_POLICY); @@ -3119,6 +3142,9 @@ public class PreferencesDialog extends javax.swing.JDialog { }); }//GEN-LAST:event_bttnResetControlsActionPerformed + private void showFullImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showFullImagePathActionPerformed + }//GEN-LAST:event_showFullImagePathActionPerformed + private void showProxySettings() { Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem(); switch (proxyType) { @@ -3222,6 +3248,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private static void loadPhases(Preferences prefs) { load(prefs, dialog.tooltipDelay, KEY_SHOW_TOOLTIPS_DELAY, "300"); load(prefs, dialog.showCardName, KEY_SHOW_CARD_NAMES, "true"); + load(prefs, dialog.showFullImagePath, KEY_SHOW_FULL_IMAGE_PATH, "true"); load(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true"); load(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true"); load(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true"); @@ -3898,6 +3925,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JButton saveButton; private javax.swing.JCheckBox showAbilityPickerForced; private javax.swing.JCheckBox showCardName; + private javax.swing.JCheckBox showFullImagePath; private javax.swing.JCheckBox showPlayerNamesPermanently; private javax.swing.JSlider sliderCardSizeHand; private javax.swing.JSlider sliderCardSizeMaxBattlefield; diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java index 01c7a6db23..8a81a208d2 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java @@ -31,7 +31,8 @@ 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 + * Class for drawing the mage card object by using a form based JComponent + * approach * * @author arcane, nantuko, noxx, stravant */ @@ -68,10 +69,13 @@ public class CardPanelComponentImpl extends CardPanel { private final GlowText titleText; private final GlowText ptText; + private final JLabel fullImageText; + private String fullImagePath = null; private boolean hasImage = false; private boolean displayTitleAnyway; + private boolean displayFullImagePath; private final static Map IMAGE_CACHE; @@ -202,7 +206,7 @@ public class CardPanelComponentImpl extends CardPanel { counterPanel.setVisible(false); } - + // Ability icon if (newGameCard.isAbility()) { if (newGameCard.getAbilityType() == AbilityType.TRIGGERED) { @@ -211,13 +215,14 @@ public class CardPanelComponentImpl extends CardPanel { setTypeIcon(ImageManagerImpl.instance.getActivatedAbilityImage(), "Activated Ability"); } } - + // Token icon if (this.gameCard.isToken()) { setTypeIcon(ImageManagerImpl.instance.getTokenIconImage(), "Token Permanent"); } displayTitleAnyway = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_CARD_NAMES, "true").equals("true"); + displayFullImagePath = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_FULL_IMAGE_PATH, "true").equals("true"); // Title Text titleText = new GlowText(); @@ -229,6 +234,12 @@ public class CardPanelComponentImpl extends CardPanel { titleText.setWrap(true); add(titleText); + // Full path to image text + fullImageText = new JLabel(); + fullImageText.setText(fullImagePath); + fullImageText.setForeground(Color.BLACK); + add(fullImageText); + // PT Text ptText = new GlowText(); if (gameCard.isCreature()) { @@ -300,10 +311,19 @@ public class CardPanelComponentImpl extends CardPanel { doLayout(); } + private void setFullPath(String fullImagePath) { + this.fullImagePath = fullImagePath; + this.fullImagePath = this.fullImagePath.replaceAll("\\\\", "\\\\
"); + this.fullImagePath = this.fullImagePath.replaceAll("/", "/
"); + this.fullImagePath = "" + this.fullImagePath + ""; + fullImageText.setText(!displayFullImagePath ? "" : this.fullImagePath); + doLayout(); + } + @Override public void transferResources(final CardPanel panelAbstract) { if (panelAbstract instanceof CardPanelComponentImpl) { - CardPanelComponentImpl panel = (CardPanelComponentImpl)panelAbstract; + CardPanelComponentImpl panel = (CardPanelComponentImpl) panelAbstract; synchronized (panel.imagePanel) { if (panel.imagePanel.hasImage()) { setImage(panel.imagePanel.getSrcImage()); @@ -321,7 +341,7 @@ public class CardPanelComponentImpl extends CardPanel { this.titleText.setGlowColor(Color.black); } } - + @Override protected void paintCard(Graphics2D g2d) { float alpha = getAlpha(); @@ -333,9 +353,9 @@ public class CardPanelComponentImpl extends CardPanel { g2d.drawImage( IMAGE_CACHE.get( new Key(getWidth(), getHeight(), getCardWidth(), getCardHeight(), getCardXOffset(), getCardYOffset(), - hasImage, isSelected(), isChoosable(), gameCard.isPlayable(), gameCard.isCanAttack())), + hasImage, isSelected(), isChoosable(), gameCard.isPlayable(), gameCard.isCanAttack())), 0, 0, null); - g2d.dispose(); + g2d.dispose(); } private static BufferedImage createImage(Key key) { @@ -414,7 +434,7 @@ public class CardPanelComponentImpl extends CardPanel { @Override public void doLayout() { super.doLayout(); - + int cardWidth = getCardWidth(); int cardHeight = getCardHeight(); int cardXOffset = getCardXOffset(); @@ -456,6 +476,7 @@ public class CardPanelComponentImpl extends CardPanel { boolean showText = (!isAnimationPanel() && fontHeight < 12); titleText.setVisible(showText); ptText.setVisible(showText); + fullImageText.setVisible(fullImagePath != null); if (showText) { int fontSize = cardHeight / 11; @@ -465,6 +486,9 @@ public class CardPanelComponentImpl extends CardPanel { int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset(); titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY); + fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10)); + fullImageText.setBounds(cardXOffset, cardYOffset + titleY, cardWidth, cardHeight - titleY); + ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); Dimension ptSize = ptText.getPreferredSize(); ptText.setSize(ptSize.width, ptSize.height); @@ -486,7 +510,7 @@ public class CardPanelComponentImpl extends CardPanel { public void setCardBounds(int x, int y, int cardWidth, int cardHeight) { // Call to super super.setCardBounds(x, y, cardWidth, cardHeight); - + // Update image if (imagePanel != null && imagePanel.getSrcImage() != null) { updateArtImage(); @@ -496,7 +520,7 @@ public class CardPanelComponentImpl extends CardPanel { @Override public void setAlpha(float alpha) { super.setAlpha(alpha); - + // Update components if (alpha == 0) { this.ptText.setVisible(false); @@ -529,6 +553,9 @@ public class CardPanelComponentImpl extends CardPanel { } else { srcImage = ImageCache.getThumbnail(gameCard); } + if (srcImage == null) { + setFullPath(ImageCache.getFilePath(gameCard, getCardWidth())); + } UI.invokeLater(() -> { if (stamp == updateArtImageStamp) { hasImage = srcImage != null; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java index 05ad7b0747..3f033bdaec 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java @@ -157,6 +157,53 @@ public final class ImageCache { }); } + public static String getFilePath(CardView card, int width) { + String key = getKey(card, card.getName(), Integer.toString(width)); + boolean usesVariousArt = false; + if (key.matches(".*#usesVariousArt.*")) { + usesVariousArt = true; + key = key.replace("#usesVariousArt", ""); + } + boolean thumbnail = false; + if (key.matches(".*#thumb.*")) { + thumbnail = true; + key = key.replace("#thumb", ""); + } + Matcher m = KEY_PATTERN.matcher(key); + + if (m.matches()) { + String name = m.group(1); + String set = m.group(2); + Integer type = Integer.parseInt(m.group(3)); + String collectorId = m.group(4); + if (collectorId.equals("null")) { + collectorId = "0"; + } + String tokenSetCode = m.group(5); + String tokenDescriptor = m.group(6); + + CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor); + + 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; + } + } else { + path = CardImageUtils.generateImagePath(info); + } + + if (thumbnail && path.endsWith(".jpg")) { + return buildThumbnailPath(path); + } + return path; + } + + return ""; + } + private ImageCache() { }