From 04cb20f46addb1ba42fc644fff0164d6f5a3db5a Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 21 Mar 2019 19:17:41 +0400 Subject: [PATCH] UI: improved deck editor exports: * added deck export to files (#4243); * fixed wrong card sorting in deck files after save (#3719); --- .../deck/generator/DeckGeneratorDialog.java | 27 +- .../client/deckeditor/DeckEditorPanel.java | 299 +++++++++--------- .../client/dialog/NewTournamentDialog.java | 29 +- .../mage/client/table/NewPlayerPanel.java | 31 +- .../java/mage/cards/decks/DeckFileFilter.java | 40 +++ .../java/mage/cards/decks/DeckFormats.java | 53 +++- .../mage/cards/decks/DeckFormatsTest.java | 45 +++ .../cards/decks/exporter/DckExporter.java | 82 ----- .../cards/decks/exporter/DeckExporter.java | 11 +- ...tgoExporter.java => MtgoDeckExporter.java} | 22 +- .../decks/exporter/XmageDeckExporter.java | 113 +++++++ .../cards/decks/exporter/DckExporterTest.java | 31 -- ...terTest.java => MtgoDeckExporterTest.java} | 4 +- .../decks/exporter/XmageDeckExporterTest.java | 35 ++ 14 files changed, 482 insertions(+), 340 deletions(-) create mode 100644 Mage/src/main/java/mage/cards/decks/DeckFileFilter.java create mode 100644 Mage/src/main/java/mage/cards/decks/DeckFormatsTest.java delete mode 100644 Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java rename Mage/src/main/java/mage/cards/decks/exporter/{MtgoExporter.java => MtgoDeckExporter.java} (66%) create mode 100644 Mage/src/main/java/mage/cards/decks/exporter/XmageDeckExporter.java delete mode 100644 Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java rename Mage/src/test/java/mage/cards/decks/exporter/{MtgoExporterTest.java => MtgoDeckExporterTest.java} (91%) create mode 100644 Mage/src/test/java/mage/cards/decks/exporter/XmageDeckExporterTest.java diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java index 1665bc2309..11778ac269 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java @@ -1,16 +1,5 @@ - package mage.client.deck.generator; -import java.awt.*; -import java.awt.event.ActionListener; -import java.awt.event.ItemListener; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; -import javax.swing.*; -import javax.swing.border.CompoundBorder; -import javax.swing.border.EmptyBorder; -import javax.swing.border.EtchedBorder; import mage.cards.decks.Deck; import mage.client.MageFrame; import mage.client.dialog.PreferencesDialog; @@ -18,10 +7,20 @@ import mage.client.util.gui.ColorsChooser; import mage.client.util.gui.FastSearchUtil; import mage.client.util.sets.ConstructedFormats; -import static mage.cards.decks.DeckFormats.DCK; +import javax.swing.*; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import java.awt.*; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static mage.cards.decks.DeckFormats.XMAGE; /** - * * @author Simown */ public class DeckGeneratorDialog { @@ -329,7 +328,7 @@ public class DeckGeneratorDialog { tmp.getParentFile().mkdirs(); tmp.createNewFile(); deck.setName(deckName); - DCK.getExporter().writeDeck(tmp.getAbsolutePath(), deck.getDeckCardLists()); + XMAGE.getExporter().writeDeck(tmp.getAbsolutePath(), deck.getDeckCardLists()); cleanUp(); return tmp.getAbsolutePath(); } catch (Exception e) { diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index ccbc588f55..d828a7d855 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -1,9 +1,7 @@ package mage.client.deckeditor; import mage.cards.Card; -import mage.cards.decks.Deck; -import mage.cards.decks.DeckCardLists; -import mage.cards.decks.DnDDeckTargetListener; +import mage.cards.decks.*; import mage.cards.decks.importer.DeckImporter; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -39,7 +37,7 @@ import java.util.List; import java.util.*; import java.util.concurrent.*; -import static mage.cards.decks.DeckFormats.DCK; +import static mage.cards.decks.DeckFormats.XMAGE; /** * @author BetaSteward_at_googlemail.com, JayDi85 @@ -49,6 +47,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(DeckEditorPanel.class); private final JFileChooser fcSelectDeck; private final JFileChooser fcImportDeck; + private final JFileChooser fcExportDeck; private Deck deck = new Deck(); private final Map temporaryCards = new HashMap<>(); // Cards dragged out of one part of the view into another private boolean isShowCardInfo = false; @@ -65,10 +64,12 @@ public class DeckEditorPanel extends javax.swing.JPanel { fcSelectDeck = new JFileChooser(); fcSelectDeck.setAcceptAllFileFilterUsed(false); - fcSelectDeck.addChoosableFileFilter(new DeckFilter()); + fcSelectDeck.addChoosableFileFilter(new DeckFileFilter("dck", "XMage's deck files (*.dck)")); fcImportDeck = new JFileChooser(); fcImportDeck.setAcceptAllFileFilterUsed(false); fcImportDeck.addChoosableFileFilter(new ImportFilter()); + fcExportDeck = new JFileChooser(); + fcExportDeck.setAcceptAllFileFilterUsed(false); deckArea.setOpaque(false); panelLeft.setOpaque(false); @@ -747,7 +748,43 @@ public class DeckEditorPanel extends javax.swing.JPanel { } private void exportToFile(java.awt.event.ActionEvent evt) { - // TODO + // all available export formats + fcExportDeck.resetChoosableFileFilters(); + for (FileFilter filter : DeckFormats.getFileFilters()) { + fcExportDeck.addChoosableFileFilter(filter); + } + + String lastFolder = MageFrame.getPreferences().get("lastExportFolder", ""); + if (!lastFolder.isEmpty()) { + fcExportDeck.setCurrentDirectory(new File(lastFolder)); + } + int ret = fcExportDeck.showSaveDialog(this); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fcExportDeck.getSelectedFile(); + + // default ext for file + String needFileName = file.getAbsolutePath(); + String needFileExt = DeckFormats.getDefaultFileExtForFilter(fcExportDeck.getFileFilter()); + if (!needFileExt.isEmpty() && !needFileName.toLowerCase(Locale.ENGLISH).endsWith("." + needFileExt)) { + needFileName += "." + needFileExt; + } + + MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); + try { + DeckFormats.writeDeck(needFileName, deck.getDeckCardLists()); + + try { + MageFrame.getPreferences().put("lastExportFolder", file.getCanonicalPath()); + } catch (IOException ex) { + logger.error("Error on save last used export folder: " + ex.getMessage()); + } + } catch (Exception ex) { + logger.fatal(ex); + } finally { + MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + } + fcExportDeck.setSelectedFile(null); } private void exportToClipboard(java.awt.event.ActionEvent evt) { @@ -845,21 +882,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckNameLayout = new javax.swing.GroupLayout(panelDeckName); panelDeckName.setLayout(panelDeckNameLayout); panelDeckNameLayout.setHorizontalGroup( - panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckNameLayout.createSequentialGroup() - .addContainerGap() - .addComponent(lblDeckName) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 175, Short.MAX_VALUE) - .addContainerGap()) + panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckNameLayout.createSequentialGroup() + .addContainerGap() + .addComponent(lblDeckName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 175, Short.MAX_VALUE) + .addContainerGap()) ); panelDeckNameLayout.setVerticalGroup( - panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckNameLayout.createSequentialGroup() - .addGroup(panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblDeckName)) - .addGap(0, 0, 0)) + panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckNameLayout.createSequentialGroup() + .addGroup(panelDeckNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblDeckName)) + .addGap(0, 0, 0)) ); panelDeck.add(panelDeckName); @@ -888,21 +925,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckCreateLayout = new javax.swing.GroupLayout(panelDeckCreate); panelDeckCreate.setLayout(panelDeckCreateLayout); panelDeckCreateLayout.setHorizontalGroup( - panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckCreateLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnNew, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnGenDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(40, Short.MAX_VALUE)) + panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckCreateLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnNew, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnGenDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(40, Short.MAX_VALUE)) ); panelDeckCreateLayout.setVerticalGroup( - panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckCreateLayout.createSequentialGroup() - .addGap(5, 5, 5) - .addGroup(panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnGenDeck, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) - .addComponent(btnNew, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) + panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckCreateLayout.createSequentialGroup() + .addGap(5, 5, 5) + .addGroup(panelDeckCreateLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnGenDeck, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) + .addComponent(btnNew, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) ); panelDeck.add(panelDeckCreate); @@ -931,21 +968,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckLoadLayout = new javax.swing.GroupLayout(panelDeckLoad); panelDeckLoad.setLayout(panelDeckLoadLayout); panelDeckLoadLayout.setHorizontalGroup( - panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckLoadLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnImport, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(40, Short.MAX_VALUE)) + panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckLoadLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnImport, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(40, Short.MAX_VALUE)) ); panelDeckLoadLayout.setVerticalGroup( - panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckLoadLayout.createSequentialGroup() - .addContainerGap() - .addGroup(panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(btnImport, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) + panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckLoadLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelDeckLoadLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(btnImport, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) ); panelDeck.add(panelDeckLoad); @@ -974,21 +1011,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckSaveLayout = new javax.swing.GroupLayout(panelDeckSave); panelDeckSave.setLayout(panelDeckSaveLayout); panelDeckSaveLayout.setHorizontalGroup( - panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckSaveLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnSave, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnExport, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(40, Short.MAX_VALUE)) + panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckSaveLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnSave, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnExport, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(40, Short.MAX_VALUE)) ); panelDeckSaveLayout.setVerticalGroup( - panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckSaveLayout.createSequentialGroup() - .addContainerGap() - .addGroup(panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnSave, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) - .addComponent(btnExport, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) + panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckSaveLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelDeckSaveLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(btnSave, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) + .addComponent(btnExport, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE))) ); panelDeck.add(panelDeckSave); @@ -1019,24 +1056,24 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckDraftLayout = new javax.swing.GroupLayout(panelDeckDraft); panelDeckDraft.setLayout(panelDeckDraftLayout); panelDeckDraftLayout.setHorizontalGroup( - panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckDraftLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnSubmit, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnSubmitTimer, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(40, Short.MAX_VALUE)) + panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckDraftLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnSubmit, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSubmitTimer, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(40, Short.MAX_VALUE)) ); panelDeckDraftLayout.setVerticalGroup( - panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckDraftLayout.createSequentialGroup() - .addContainerGap() - .addGroup(panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckDraftLayout.createSequentialGroup() - .addComponent(btnSubmit, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(btnSubmitTimer, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) - .addGap(0, 0, 0)) + panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckDraftLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelDeckDraftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckDraftLayout.createSequentialGroup() + .addComponent(btnSubmit, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(btnSubmitTimer, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) + .addGap(0, 0, 0)) ); panelDeck.add(panelDeckDraft); @@ -1056,18 +1093,18 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckLandsLayout = new javax.swing.GroupLayout(panelDeckLands); panelDeckLands.setLayout(panelDeckLandsLayout); panelDeckLandsLayout.setHorizontalGroup( - panelDeckLandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckLandsLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnAddLand, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(146, Short.MAX_VALUE)) + panelDeckLandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckLandsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnAddLand, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(146, Short.MAX_VALUE)) ); panelDeckLandsLayout.setVerticalGroup( - panelDeckLandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckLandsLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnAddLand, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) - .addGap(0, 0, 0)) + panelDeckLandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckLandsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnAddLand, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE) + .addGap(0, 0, 0)) ); panelDeck.add(panelDeckLands); @@ -1091,21 +1128,21 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelDeckExitLayout = new javax.swing.GroupLayout(panelDeckExit); panelDeckExit.setLayout(panelDeckExitLayout); panelDeckExitLayout.setHorizontalGroup( - panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelDeckExitLayout.createSequentialGroup() - .addContainerGap() - .addComponent(btnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtTimeRemaining, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(40, Short.MAX_VALUE)) + panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelDeckExitLayout.createSequentialGroup() + .addContainerGap() + .addComponent(btnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtTimeRemaining, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(40, Short.MAX_VALUE)) ); panelDeckExitLayout.setVerticalGroup( - panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelDeckExitLayout.createSequentialGroup() - .addGap(0, 11, Short.MAX_VALUE) - .addGroup(panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(txtTimeRemaining, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))) + panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelDeckExitLayout.createSequentialGroup() + .addGap(0, 11, Short.MAX_VALUE) + .addGroup(panelDeckExitLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtTimeRemaining, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))) ); panelDeck.add(panelDeckExit); @@ -1113,35 +1150,35 @@ public class DeckEditorPanel extends javax.swing.JPanel { javax.swing.GroupLayout panelLeftLayout = new javax.swing.GroupLayout(panelLeft); panelLeft.setLayout(panelLeftLayout); panelLeftLayout.setHorizontalGroup( - panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelLeftLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addGroup(panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(panelDeck, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelLeftLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelDeck, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) ); panelLeftLayout.setVerticalGroup( - panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelLeftLayout.createSequentialGroup() - .addComponent(panelDeck, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap()) + panelLeftLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelLeftLayout.createSequentialGroup() + .addComponent(panelDeck, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(panelLeft, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(panelRight, javax.swing.GroupLayout.DEFAULT_SIZE, 890, Short.MAX_VALUE)) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(panelLeft, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelRight, javax.swing.GroupLayout.DEFAULT_SIZE, 890, Short.MAX_VALUE)) ); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(panelLeft, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(panelRight, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 808, Short.MAX_VALUE) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelLeft, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelRight, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 808, Short.MAX_VALUE) ); }// //GEN-END:initComponents @@ -1179,7 +1216,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { DeckCardLists cardLists = deck.getDeckCardLists(); cardLists.setCardLayout(deckArea.getCardLayout()); cardLists.setSideboardLayout(deckArea.getSideboardLayout()); - DCK.getExporter().writeDeck(fileName, cardLists); + XMAGE.getExporter().writeDeck(fileName, cardLists); } catch (IOException ex) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage() + "\nTry ensuring that the selected directory is writable.", "Error saving deck", JOptionPane.ERROR_MESSAGE); } finally { @@ -1361,30 +1398,6 @@ public class DeckEditorPanel extends javax.swing.JPanel { // End of variables declaration//GEN-END:variables } -class DeckFilter extends FileFilter { - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - - String ext = null; - String s = f.getName(); - int i = s.lastIndexOf('.'); - - if (i > 0 && i < s.length() - 1) { - ext = s.substring(i + 1).toLowerCase(Locale.ENGLISH); - } - return (ext != null) && ext.equals("dck"); - } - - @Override - public String getDescription() { - return "XMage's deck files (*.dck)"; - } -} - class ImportFilter extends FileFilter { @Override @@ -1413,7 +1426,7 @@ class ImportFilter extends FileFilter { @Override public String getDescription() { - return "*.dec | *.mwDeck | *.txt | *.dek | *.cod | *.o8d"; + return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d)"; } } diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 0aa0898fce..7adab1e325 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -18,6 +18,7 @@ import java.util.UUID; import javax.swing.*; import javax.swing.filechooser.FileFilter; import mage.cards.decks.Deck; +import mage.cards.decks.DeckFileFilter; import mage.cards.decks.importer.DeckImporter; import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionRepository; @@ -709,7 +710,7 @@ public class NewTournamentDialog extends MageDialog { if (fcSelectDeck == null) { fcSelectDeck = new JFileChooser(); fcSelectDeck.setAcceptAllFileFilterUsed(false); - fcSelectDeck.addChoosableFileFilter(new DeckFilter()); + fcSelectDeck.addChoosableFileFilter(new DeckFileFilter("dck", "XMage's deck files (*.dck)")); } String lastFolder = MageFrame.getPreferences().get("lastDeckFolder", ""); if (!lastFolder.isEmpty()) { @@ -1257,28 +1258,4 @@ public class NewTournamentDialog extends MageDialog { private org.jdesktop.beansbinding.BindingGroup bindingGroup; // End of variables declaration//GEN-END:variables -} - -class DeckFilter extends FileFilter { - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - - String ext = null; - String s = f.getName(); - int i = s.lastIndexOf('.'); - - if (i > 0 && i < s.length() - 1) { - ext = s.substring(i + 1).toLowerCase(Locale.ENGLISH); - } - return (ext == null) ? false : ext.equals("dck"); - } - - @Override - public String getDescription() { - return "XMage's deck files (*.dck)"; - } -} +} \ No newline at end of file diff --git a/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java index 612de6217f..c735906900 100644 --- a/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java @@ -12,6 +12,8 @@ import java.io.IOException; import java.util.Locale; import javax.swing.*; import javax.swing.filechooser.FileFilter; + +import mage.cards.decks.DeckFileFilter; import mage.client.MageFrame; import mage.client.deck.generator.DeckGenerator; import mage.client.util.Config; @@ -31,7 +33,7 @@ public class NewPlayerPanel extends javax.swing.JPanel { initComponents(); fcSelectDeck = new JFileChooser(); fcSelectDeck.setAcceptAllFileFilterUsed(false); - fcSelectDeck.addChoosableFileFilter(new DeckFilter()); + fcSelectDeck.addChoosableFileFilter(new DeckFileFilter("dck", "XMage's deck files (*.dck)")); String deckPath = MageFrame.getPreferences().get("defaultDeckPath", ""); if (deckPath.isEmpty()) { if (Config.defaultDeckPath != null) { @@ -197,29 +199,4 @@ public class NewPlayerPanel extends javax.swing.JPanel { private javax.swing.JTextField txtPlayerName; // End of variables declaration//GEN-END:variables -} - -class DeckFilter extends FileFilter { - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - - String ext = null; - String s = f.getName(); - int i = s.lastIndexOf('.'); - - if (i > 0 && i < s.length() - 1) { - ext = s.substring(i + 1).toLowerCase(Locale.ENGLISH); - } - return (ext == null) ? false : ext.equals("dck"); - } - - @Override - public String getDescription() { - return "XMage's deck files (*.dck)"; - } - -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/cards/decks/DeckFileFilter.java b/Mage/src/main/java/mage/cards/decks/DeckFileFilter.java new file mode 100644 index 0000000000..d7ca6415ed --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/DeckFileFilter.java @@ -0,0 +1,40 @@ +package mage.cards.decks; + +import javax.swing.filechooser.FileFilter; +import java.io.File; +import java.util.Locale; + +/** + * @author JayDi85 + */ +public class DeckFileFilter extends FileFilter { + + private final String ext; + private final String description; + + public DeckFileFilter(String ext, String description) { + this.ext = ext.toLowerCase(Locale.ENGLISH); + this.description = description; + } + + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + + String fileExt = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + fileExt = s.substring(i + 1).toLowerCase(Locale.ENGLISH); + } + return (fileExt != null) && fileExt.equals(this.ext); + } + + @Override + public String getDescription() { + return description; + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/cards/decks/DeckFormats.java b/Mage/src/main/java/mage/cards/decks/DeckFormats.java index 272baf4956..5d815f62c4 100644 --- a/Mage/src/main/java/mage/cards/decks/DeckFormats.java +++ b/Mage/src/main/java/mage/cards/decks/DeckFormats.java @@ -1,16 +1,20 @@ package mage.cards.decks; -import mage.cards.decks.exporter.DckExporter; import mage.cards.decks.exporter.DeckExporter; -import mage.cards.decks.exporter.MtgoExporter; +import mage.cards.decks.exporter.MtgoDeckExporter; +import mage.cards.decks.exporter.XmageDeckExporter; +import javax.swing.filechooser.FileFilter; import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; import java.util.Optional; public enum DeckFormats { - DCK(new DckExporter()), - MTGO(new MtgoExporter()); + XMAGE(new XmageDeckExporter()), + MTGO(new MtgoDeckExporter()); private final DeckExporter exporter; @@ -23,24 +27,47 @@ public enum DeckFormats { } public static Optional getFormatForExtension(String filename) { - return getExtension(filename).map(c -> { - try { - return DeckFormats.valueOf(c); - } catch (IllegalArgumentException e) { - return null; + String exp = getExtension(filename).orElse(""); + for (DeckFormats df : values()) { + if (!exp.isEmpty() && df.getExporter().getDefaultFileExt().equals(exp)) { + return Optional.of(df); } - }); + } + return Optional.empty(); } public static Optional getExtension(String filename) { int i = filename.lastIndexOf('.'); - if (i > 0) { - return Optional.of(filename.substring(i+1).toUpperCase()); + if (i > 0 && i < filename.length() - 1) { + return Optional.of(filename.substring(i + 1).toLowerCase(Locale.ENGLISH)); } else { return Optional.empty(); } } + public static Optional getFormatForFilter(FileFilter filter) { + for (DeckFormats df : values()) { + if (df.getExporter().getFileFilter().equals(filter)) { + return Optional.of(df); + } + } + return Optional.empty(); + } + + public static String getDefaultFileExtForFilter(FileFilter filter) { + return getFormatForFilter(filter) + .map(df -> df.getExporter().getDefaultFileExt()) + .orElse(""); + } + + public static List getFileFilters() { + List res = new ArrayList<>(); + for (DeckFormats df : values()) { + res.add(df.getExporter().getFileFilter()); + } + return res; + } + public static void writeDeck(String file, DeckCardLists deck) throws IOException { writeDeck(new File(file), deck); } @@ -65,7 +92,7 @@ public enum DeckFormats { } public static void writeDeck(File file, DeckCardLists deck, DeckExporter exporter) throws IOException { - try (FileOutputStream out = new FileOutputStream(file)){ + try (FileOutputStream out = new FileOutputStream(file)) { writeDeck(out, deck, exporter); } } diff --git a/Mage/src/main/java/mage/cards/decks/DeckFormatsTest.java b/Mage/src/main/java/mage/cards/decks/DeckFormatsTest.java new file mode 100644 index 0000000000..79adf56e0a --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/DeckFormatsTest.java @@ -0,0 +1,45 @@ +package mage.cards.decks; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author JayDi85 + */ +public class DeckFormatsTest { + + @Test + public void test_FormatsExt() { + Map extList = new HashMap<>(); + for (DeckFormats df : DeckFormats.values()) { + // 1. must be unique + if (extList.containsKey(df.getExporter().getDefaultFileExt())) { + Assert.fail("Default ext must be unique for each format: " + df.getExporter().getDescription()); + } else { + extList.putIfAbsent(df.getExporter().getDefaultFileExt(), df); + } + // 2. must work with files + String fileName = "C:\\xmage\\deck" + "." + df.getExporter().getDefaultFileExt(); + Assert.assertTrue("Must support lower ext: " + df.getExporter().getDescription(), DeckFormats.getFormatForExtension(fileName.toLowerCase()).isPresent()); + Assert.assertTrue("Must support upper ext: " + df.getExporter().getDescription(), DeckFormats.getFormatForExtension(fileName.toUpperCase()).isPresent()); + } + + // 3. wrong ext + Assert.assertFalse("Must not find empty ext", DeckFormats.getFormatForExtension("deck").isPresent()); + Assert.assertFalse("Must not find . ext", DeckFormats.getFormatForExtension("deck.").isPresent()); + Assert.assertFalse("Must not find unknown ext", DeckFormats.getFormatForExtension("deck.xxx").isPresent()); + + // 3. double ext + String fileName = "C:\\xmage\\deck" + + "." + DeckFormats.XMAGE.getExporter().getDefaultFileExt() + + "." + DeckFormats.MTGO.getExporter().getDefaultFileExt(); + Assert.assertEquals("Must find mtgo", DeckFormats.getFormatForExtension(fileName).get(), DeckFormats.MTGO); + fileName = "C:\\xmage\\deck" + + "." + DeckFormats.MTGO.getExporter().getDefaultFileExt() + + "." + DeckFormats.XMAGE.getExporter().getDefaultFileExt(); + Assert.assertEquals("Must find xmage", DeckFormats.getFormatForExtension(fileName).get(), DeckFormats.XMAGE); + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java deleted file mode 100644 index 2a9af7a276..0000000000 --- a/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java +++ /dev/null @@ -1,82 +0,0 @@ -package mage.cards.decks.exporter; - -import mage.cards.decks.DeckCardInfo; -import mage.cards.decks.DeckCardLayout; -import mage.cards.decks.DeckCardLists; - -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class DckExporter extends DeckExporter { - - public void writeDeck(PrintWriter out, DeckCardLists deck) { - Map deckCards = new HashMap<>(); - Map sideboard = new HashMap<>(); - - if (deck.getName() != null && !deck.getName().isEmpty()) { - out.println("NAME:" + deck.getName()); - } - if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) { - out.println("AUTHOR:" + deck.getAuthor()); - } - for (DeckCardInfo deckCardInfo : deck.getCards()) { - if (deckCards.containsKey(deckCardInfo.getCardKey())) { - deckCards.put(deckCardInfo.getCardKey(), deckCards.get(deckCardInfo.getCardKey()).increaseQuantity()); - } else { - deckCards.put(deckCardInfo.getCardKey(), deckCardInfo); - } - } - - for (DeckCardInfo deckCardInfo : deck.getSideboard()) { - if (sideboard.containsKey(deckCardInfo.getCardKey())) { - sideboard.put(deckCardInfo.getCardKey(), sideboard.get(deckCardInfo.getCardKey()).increaseQuantity()); - } else { - sideboard.put(deckCardInfo.getCardKey(), deckCardInfo); - } - } - - // Write out all of the cards - for (Map.Entry entry : deckCards.entrySet()) { - out.printf("%d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); - } - for (Map.Entry entry : sideboard.entrySet()) { - out.printf("SB: %d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); - } - - // Write out the layout - out.print("LAYOUT MAIN:"); - writeCardLayout(out, deck.getCardLayout()); - out.println(""); - out.print("LAYOUT SIDEBOARD:"); - writeCardLayout(out, deck.getSideboardLayout()); - out.println(""); - } - - private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) { - if (layout == null) { - return; - } - List>> cardGrid = layout.getCards(); - int height = cardGrid.size(); - int width = (height > 0) ? cardGrid.get(0).size() : 0; - out.print("(" + height + ',' + width + ')'); - out.print(layout.getSettings()); - out.print("|"); - for (List> row : cardGrid) { - for (List stack : row) { - out.print("("); - for (int i = 0; i < stack.size(); ++i) { - DeckCardInfo info = stack.get(i); - out.printf("[%s:%s]", info.getSetCode(), info.getCardNum()); - if (i != stack.size() - 1) { - out.print(","); - } - } - out.print(")"); - } - } - } - -} diff --git a/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java index 57960bef3a..d9a4b8ab40 100644 --- a/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java +++ b/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java @@ -3,7 +3,11 @@ package mage.cards.decks.exporter; import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckFormats; -import java.io.*; +import javax.swing.filechooser.FileFilter; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; public abstract class DeckExporter { @@ -21,4 +25,9 @@ public abstract class DeckExporter { public abstract void writeDeck(PrintWriter out, DeckCardLists deck); + public abstract FileFilter getFileFilter(); + + public abstract String getDefaultFileExt(); + + public abstract String getDescription(); } diff --git a/Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/MtgoDeckExporter.java similarity index 66% rename from Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java rename to Mage/src/main/java/mage/cards/decks/exporter/MtgoDeckExporter.java index 41d3e39139..e6bc6d7083 100644 --- a/Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java +++ b/Mage/src/main/java/mage/cards/decks/exporter/MtgoDeckExporter.java @@ -2,12 +2,18 @@ package mage.cards.decks.exporter; import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardLists; +import mage.cards.decks.DeckFileFilter; +import javax.swing.filechooser.FileFilter; import java.io.PrintWriter; import java.util.List; import java.util.TreeMap; -public class MtgoExporter extends DeckExporter { +public class MtgoDeckExporter extends DeckExporter { + + private final String ext = "dek"; + private final String description = "MTGO's deck format (*.dek)"; + private final FileFilter fileFilter = new DeckFileFilter(ext, description); @Override public void writeDeck(PrintWriter out, DeckCardLists deck) { @@ -40,4 +46,18 @@ public class MtgoExporter extends DeckExporter { return counts; } + @Override + public FileFilter getFileFilter() { + return fileFilter; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getDefaultFileExt() { + return ext; + } } diff --git a/Mage/src/main/java/mage/cards/decks/exporter/XmageDeckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/XmageDeckExporter.java new file mode 100644 index 0000000000..c3e18fe023 --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/exporter/XmageDeckExporter.java @@ -0,0 +1,113 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLayout; +import mage.cards.decks.DeckCardLists; +import mage.cards.decks.DeckFileFilter; + +import javax.swing.filechooser.FileFilter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class XmageDeckExporter extends DeckExporter { + + private final String ext = "dck"; + private final String description = "XMage's deck format (*.dck)"; + private final FileFilter fileFilter = new DeckFileFilter(ext, description); + + @Override + public void writeDeck(PrintWriter out, DeckCardLists deck) { + List deckMain = new ArrayList<>(); + List deckSideboard = new ArrayList<>(); + Map amount = new HashMap<>(); + + // info + if (deck.getName() != null && !deck.getName().isEmpty()) { + out.println("NAME:" + deck.getName()); + } + if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) { + out.println("AUTHOR:" + deck.getAuthor()); + } + + // main + for (DeckCardInfo card : deck.getCards()) { + String code = "M@" + card.getCardKey(); + int curAmount = amount.getOrDefault(code, 0); + if (curAmount == 0) { + deckMain.add(card); + } + amount.put(code, curAmount + card.getQuantity()); + } + // sideboard + for (DeckCardInfo card : deck.getSideboard()) { + String code = "S@" + card.getCardKey(); + int curAmount = amount.getOrDefault(code, 0); + if (curAmount == 0) { + deckSideboard.add(card); + } + amount.put(code, curAmount + card.getQuantity()); + } + + // cards print + for (DeckCardInfo card : deckMain) { + out.printf("%d [%s:%s] %s%n", amount.get("M@" + card.getCardKey()), card.getSetCode(), card.getCardNum(), card.getCardName()); + } + for (DeckCardInfo card : deckSideboard) { + out.printf("SB: %d [%s:%s] %s%n", amount.get("S@" + card.getCardKey()), card.getSetCode(), card.getCardNum(), card.getCardName()); + } + + // layout print + if (deck.getCardLayout() != null) { + out.print("LAYOUT MAIN:"); + writeCardLayout(out, deck.getCardLayout()); + out.println(""); + out.print("LAYOUT SIDEBOARD:"); + writeCardLayout(out, deck.getSideboardLayout()); + out.println(""); + } + } + + private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) { + if (layout == null) { + return; + } + List>> cardGrid = layout.getCards(); + int height = cardGrid.size(); + int width = (height > 0) ? cardGrid.get(0).size() : 0; + out.print("(" + height + ',' + width + ')'); + out.print(layout.getSettings()); + out.print("|"); + for (List> row : cardGrid) { + for (List stack : row) { + out.print("("); + for (int i = 0; i < stack.size(); ++i) { + DeckCardInfo info = stack.get(i); + out.printf("[%s:%s]", info.getSetCode(), info.getCardNum()); + if (i != stack.size() - 1) { + out.print(","); + } + } + out.print(")"); + } + } + } + + @Override + public FileFilter getFileFilter() { + return fileFilter; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getDefaultFileExt() { + return ext; + } +} diff --git a/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java deleted file mode 100644 index 48d0c4d4cd..0000000000 --- a/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package mage.cards.decks.exporter; - -import mage.cards.decks.DeckCardInfo; -import mage.cards.decks.DeckCardLists; -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import static org.junit.Assert.assertEquals; - -public class DckExporterTest { - - @Test - public void writeDeck() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DeckCardLists deck = new DeckCardLists(); - deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2)); - deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3)); - deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); - DckExporter exporter = new DckExporter(); - exporter.writeDeck(baos, deck); - assertEquals("2 [1:RNA] Forest" + System.lineSeparator() + - "3 [2:RNA] Plains" + System.lineSeparator() + - "SB: 2 [3:RNA] Island" + System.lineSeparator() + - "LAYOUT MAIN:" + System.lineSeparator() + - "LAYOUT SIDEBOARD:" + System.lineSeparator(), - baos.toString()); - } - -} \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/MtgoDeckExporterTest.java similarity index 91% rename from Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java rename to Mage/src/test/java/mage/cards/decks/exporter/MtgoDeckExporterTest.java index 0bbbc7d599..3e69e753bd 100644 --- a/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java +++ b/Mage/src/test/java/mage/cards/decks/exporter/MtgoDeckExporterTest.java @@ -9,7 +9,7 @@ import java.io.IOException; import static org.junit.Assert.assertEquals; -public class MtgoExporterTest { +public class MtgoDeckExporterTest { @Test public void writeDeck() throws IOException { @@ -18,7 +18,7 @@ public class MtgoExporterTest { deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2)); deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3)); deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); - MtgoExporter exporter = new MtgoExporter(); + MtgoDeckExporter exporter = new MtgoDeckExporter(); exporter.writeDeck(baos, deck); assertEquals("2 Forest" + System.lineSeparator() + "3 Plains" + System.lineSeparator() + diff --git a/Mage/src/test/java/mage/cards/decks/exporter/XmageDeckExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/XmageDeckExporterTest.java new file mode 100644 index 0000000000..e54a2644b7 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/exporter/XmageDeckExporterTest.java @@ -0,0 +1,35 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class XmageDeckExporterTest { + + @Test + public void writeDeck() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DeckCardLists deck = new DeckCardLists(); + deck.getCards().add(new DeckCardInfo("Forest", "1", "RNA", 2)); + deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 3)); + deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 5)); // must combine + deck.getCards().add(new DeckCardInfo("Mountain", "3", "RNA", 1)); + deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 2)); + deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 5)); // must combine + deck.getSideboard().add(new DeckCardInfo("Mountain", "2", "RNA", 3)); + XmageDeckExporter exporter = new XmageDeckExporter(); + exporter.writeDeck(baos, deck); + assertEquals("2 [RNA:1] Forest" + System.lineSeparator() + + "8 [RNA:2] Plains" + System.lineSeparator() + + "1 [RNA:3] Mountain" + System.lineSeparator() + + "SB: 7 [RNA:1] Island" + System.lineSeparator() + + "SB: 3 [RNA:2] Mountain" + System.lineSeparator(), + baos.toString()); + } + +} \ No newline at end of file