From 56526d5413587d14c58cb236a2853762b7d2f347 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 24 Jun 2018 21:13:35 +1000 Subject: [PATCH] Copy Paste image source --- .../card/dl/sources/CopyPasteImageSource.java | 255 ++++++++++++++++++ .../sources/CopyPasteImageSourceDialog.form | 79 ++++++ .../sources/CopyPasteImageSourceDialog.java | 182 +++++++++++++ .../plugins/card/images/DownloadPictures.java | 3 +- 4 files changed, 518 insertions(+), 1 deletion(-) create mode 100644 Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java create mode 100644 Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form create mode 100644 Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java new file mode 100644 index 000000000000..0fc6561b9782 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java @@ -0,0 +1,255 @@ +package org.mage.plugins.card.dl.sources; + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JOptionPane; +import mage.cards.Sets; +import org.mage.plugins.card.images.CardDownloadData; + +/** + * + * @author spjspj + */ +public enum CopyPasteImageSource implements CardImageSource { + + instance; + + private Set supportedSets = new LinkedHashSet(); + private Set missingCards = new LinkedHashSet(); + HashMap singleLinks = null; + boolean loadedFromDialog = false; + boolean viewMissingCards = true; + HashMap singleLinksDone = null; + private static int maxTimes = 2; + + @Override + public String getSourceName() { + return ""; + } + + @Override + public float getAverageSize() { + return 260.7f; + } + + @Override + public String getNextHttpImageUrl() { + if (singleLinks == null) { + setupLinks(); + } + + for (String key : singleLinksDone.keySet()) { + if (singleLinksDone.get(key) < maxTimes) { + singleLinksDone.put(key, maxTimes); + return key; + } + } + if (maxTimes < 2) { + maxTimes++; + } + for (String key : singleLinksDone.keySet()) { + if (singleLinksDone.get(key) < maxTimes) { + singleLinksDone.put(key, maxTimes); + return key; + } + } + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + String copy = httpImageUrl; + if (copy != null) { + return singleLinks.get(copy); + } + return null; + } + + @Override + public CardImageUrls generateURL(CardDownloadData card) throws Exception { + if (singleLinks == null) { + setupLinks(); + } + String url = singleLinks.get(card.getSet() + "/" + card.getName()); + if (url != null && url.length() > 0) { + return new CardImageUrls(url); + } + url = singleLinks.get(card.getSet() + "/" + card.getName() + "." + card.getCollectorId()); + if (url != null && url.length() > 0) { + return new CardImageUrls(url); + } + return null; + } + + int ls_size_mc = 0; + int ls_size_ss = 0; + int ls_size_sl = 0; + int num_nos = 0; + + private boolean isDifferent() { + boolean isdiff = false; + if (ls_size_mc != missingCards.size()) { + ls_size_mc = missingCards.size(); + isdiff = true; + } + if (ls_size_ss != supportedSets.size()) { + ls_size_ss = supportedSets.size(); + isdiff = true; + } + if (ls_size_sl != singleLinks.size()) { + ls_size_sl = singleLinks.size(); + isdiff = true; + } + num_nos++; + if (num_nos > 2) { + num_nos = 0; + isdiff = true; + } + return isdiff; + } + + private void setupLinks() { + if (singleLinks != null && loadedFromDialog) { + if (!viewMissingCards) { + if (isDifferent() && JOptionPane.showConfirmDialog(null, + "View your missing cards and reset the list of card images to download again?", + "View missing cards (found " + missingCards.size() + ") / Reset URLs to download ", JOptionPane.YES_NO_OPTION) + == JOptionPane.YES_OPTION) { + viewMissingCards = true; + singleLinks.clear(); + loadedFromDialog = false; + supportedSets.clear(); + } else { + return; + } + } + if (!(viewMissingCards && missingCards.size() > 0)) { + return; + } + } + singleLinks = new HashMap<>(); + loadedFromDialog = false; + + final CopyPasteImageSourceDialog dialog = new CopyPasteImageSourceDialog(); + dialog.pack(); + int count = 0; + if (viewMissingCards && missingCards.size() > 0 && singleLinks.size() == 0) { + viewMissingCards = false; + String displayMissingCardsStr = "Up to the first 20 cards are:\n"; + String missingCardsStr = ""; + if (this.missingCards != null) { + for (String card : this.missingCards) { + if (count < 20) { + displayMissingCardsStr = displayMissingCardsStr + card + "\n"; + } + missingCardsStr = missingCardsStr + card + "\n"; + + count++; + } + } + StringSelection stringSelection = new StringSelection(missingCardsStr); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(stringSelection, null); + + if (isDifferent() && JOptionPane.showConfirmDialog(null, + displayMissingCardsStr + "\n\nReset the list again?\n(NB: The full list has been copied to the clipboard)", + "Your missing cards (found " + missingCards.size() + "): ", JOptionPane.YES_NO_OPTION) + == JOptionPane.YES_OPTION) { + viewMissingCards = true; + singleLinks.clear(); + loadedFromDialog = false; + supportedSets.clear(); + } else { + return; + } + } + dialog.setVisible(true); + String[] lines = dialog.getPastedData().split(System.getProperty("line.separator")); + + for (String line : lines) { + // Break into >> "\1", "\2" + Pattern regex = Pattern.compile("\\s*\"(.*?)/(.*?)\"\\s*,\\s*\"(.*?)\""); + Matcher regexMatcher = regex.matcher(line); + while (regexMatcher.find()) { + String setCode = regexMatcher.group(1); + String cardName = regexMatcher.group(2); + String imageURL = regexMatcher.group(3); + supportedSets.add(setCode); + singleLinks.put(setCode + "/" + cardName, imageURL); + isDifferent(); + } + } + + loadedFromDialog = true; + if (lines.length == 0) { + loadedFromDialog = false; + viewMissingCards = true; + } + } + + @Override + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { + try { + return generateURL(card); + } catch (Exception ex) { + } + return null; + } + + @Override + public int getTotalImages() { + if (singleLinks == null) { + setupLinks(); + } + if (singleLinks != null) { + return singleLinks.size(); + } + return -1; + } + + @Override + public boolean isTokenSource() { + return false; + } + + @Override + public ArrayList getSupportedSets() { + setupLinks(); + ArrayList supportedSetsCopy = new ArrayList<>(); + if (supportedSets.size() == 0) { + for (String setCode : Sets.getInstance().keySet()) { + supportedSets.add(setCode); + } + } + + supportedSetsCopy.addAll(supportedSets); + return supportedSetsCopy; + } + + @Override + public void doPause(String httpImageUrl) { + } + + @Override + public boolean isImageProvided(String setCode, String cardName) { + missingCards.add(setCode + "/" + cardName); + + if (singleLinks != null) { + return singleLinks.containsKey(setCode + "/" + cardName) || singleLinks.containsKey(setCode + "/" + cardName + "-a"); + } + return false; + } + + @Override + public boolean isSetSupportedComplete(String setCode) { + return false; + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form new file mode 100644 index 000000000000..fe9fa3cf9bdd --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form @@ -0,0 +1,79 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java new file mode 100644 index 000000000000..b64d7cc81053 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java @@ -0,0 +1,182 @@ +package org.mage.plugins.card.dl.sources; + +import mage.util.StreamUtils; + +import java.awt.*; +import java.awt.event.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Set; +import javax.swing.*; + +public class CopyPasteImageSourceDialog extends JDialog { + + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JEditorPane txtDeckList; + + private String tmpPath; + + public CopyPasteImageSourceDialog() { + initComponents(); + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + buttonOK.addActionListener(e -> onOK()); + buttonCancel.addActionListener(e -> onCancel()); + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // Close on "ESC" + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + BufferedWriter bw = null; + try { + File temp = File.createTempFile("import_images_from_url", ".txt"); + bw = new BufferedWriter(new FileWriter(temp)); + bw.write(txtDeckList.getText()); + tmpPath = temp.getPath(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + StreamUtils.closeQuietly(bw); + } + + dispose(); + } + + private void onCancel() { + dispose(); + } + + public String getTmpPath() { + return tmpPath; + } + + private void initComponents() { + contentPane = new JPanel(); + JPanel panel1 = new JPanel(); + JPanel panel2 = new JPanel(); + buttonOK = new JButton(); + buttonCancel = new JButton(); + JPanel panel3 = new JPanel(); + txtDeckList = new JEditorPane(); + + { + contentPane.setMinimumSize(new Dimension(540, 450)); + + contentPane.setBorder(new javax.swing.border.CompoundBorder( + new javax.swing.border.TitledBorder(new javax.swing.border.EmptyBorder(0, 0, 0, 0), + "Download Images from Copy/Pasted Text", javax.swing.border.TitledBorder.CENTER, + javax.swing.border.TitledBorder.TOP, new java.awt.Font("Dialog", java.awt.Font.PLAIN, 12), + java.awt.Color.BLACK), contentPane.getBorder())); + + contentPane.addPropertyChangeListener(e -> { + if ("border".equals(e.getPropertyName())) { + throw new RuntimeException(); + } + }); + + contentPane.addPropertyChangeListener(e -> { + if ("border".equals(e.getPropertyName())) { + throw new RuntimeException(); + } + }); + + contentPane.setLayout(new GridBagLayout()); + ((GridBagLayout) contentPane.getLayout()).columnWidths = new int[]{0, 0}; + ((GridBagLayout) contentPane.getLayout()).rowHeights = new int[]{0, 0, 0}; + ((GridBagLayout) contentPane.getLayout()).columnWeights = new double[]{0.01, 1.0E-4}; + ((GridBagLayout) contentPane.getLayout()).rowWeights = new double[]{0.01, 0.0, 1.0E-4}; + + { + panel1.setLayout(new GridBagLayout()); + ((GridBagLayout) panel1.getLayout()).columnWidths = new int[]{0, 0, 0}; + ((GridBagLayout) panel1.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel1.getLayout()).columnWeights = new double[]{0.0, 0.01, 1.0E-4}; + ((GridBagLayout) panel1.getLayout()).rowWeights = new double[]{0.01, 1.0E-4}; + + { + panel2.setLayout(new GridBagLayout()); + ((GridBagLayout) panel2.getLayout()).columnWidths = new int[]{0, 4, 0, 0}; + ((GridBagLayout) panel2.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel2.getLayout()).columnWeights = new double[]{0.01, 0.0, 0.01, 1.0E-4}; + ((GridBagLayout) panel2.getLayout()).rowWeights = new double[]{0.0, 1.0E-4}; + + //---- buttonOK ---- + buttonOK.setText("Download from URLs"); + panel2.add(buttonOK, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, + new Insets(0, 0, 0, 0), 0, 0)); + + //---- buttonCancel ---- + buttonCancel.setText("Cancel"); + panel2.add(buttonCancel, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, + new Insets(0, 0, 0, 0), 0, 0)); + } + panel1.add(panel2, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + } + contentPane.add(panel1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + + { + panel3.setLayout(new GridBagLayout()); + ((GridBagLayout) panel3.getLayout()).columnWidths = new int[]{0, 0}; + ((GridBagLayout) panel3.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel3.getLayout()).columnWeights = new double[]{0.0, 1.0E-4}; + ((GridBagLayout) panel3.getLayout()).rowWeights = new double[]{1.0, 1.0E-4}; + + txtDeckList.setMinimumSize(new Dimension(250, 400)); + txtDeckList.setPreferredSize(new Dimension(550, 400)); + + txtDeckList.setText("// Example follows. \nNB: **DELETE ALL TEXT AND GO SELECT THIS SOURCE AGAIN TO SEE THE NAMES CARDS YOU'RE MISSING IMAGES FOR!!!***\n\"SWS/Might of the Wild\", \"http://i.imgur.com/eNXOdxp.jpg\"\n\"PTC/Wolf of Devil's Breach\", \"https://img.scryfall.com/cards/large/en/psoi/192s.jpg\"\n\nExpected columns: Name of Card (Set Trigraph\\Name), URL of image\n\n\n"); + + JScrollPane txtScrollableDeckList = new JScrollPane(txtDeckList); + panel3.add(txtScrollableDeckList, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + } + contentPane.add(panel3, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 5, 0), 0, 0)); + } + } + + Set missingCards = null; + + public void addMissingCards(Set missingCards) { + this.missingCards = missingCards; + String missingCardsStr = ""; + boolean found = false; + if (this.missingCards != null) { + for (String card : this.missingCards) { + found = true; + missingCardsStr = missingCardsStr + card + "\n"; + } + } + if (found == false) { + missingCardsStr = "\n\nNote: Leave blank to see your missing card names!\n"; + } + txtDeckList.setText(txtDeckList.getText() + "\n\nYour missing card images are:\n" + missingCardsStr); + } + + public String getPastedData() { + return txtDeckList.getText(); + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 0e9556dd902d..7be47db2d1f5 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -84,7 +84,8 @@ enum DownloadSources { MAGIDEX("4. magidex.com - high quality CARDS", MagidexImageSource.instance), GRAB_BAG("5. GrabBag - STAR WARS cards and tokens", GrabbagImageSource.instance), MYTHICSPOILER("6. mythicspoiler.com", MythicspoilerComSource.instance), - ALTERNATIVE("7. alternative.mtg.onl", AltMtgOnlTokensImageSource.instance); + ALTERNATIVE("7. alternative.mtg.onl", AltMtgOnlTokensImageSource.instance), + COPYPASTE("8. Copy and Paste Image URLs", CopyPasteImageSource.instance); // MTG_ONL("mtg.onl", MtgOnlTokensImageSource.instance), Not working correctly yet // MAGICCARDS("magiccards.info", MagicCardsImageSource.instance)