diff --git a/.gitattributes b/.gitattributes index fd5c0e576e5..c77f47b9f0f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1254,6 +1254,7 @@ forge-gui-mobile/src/forge/card/GameEntityPicker.java -text forge-gui-mobile/src/forge/deck/AddBasicLandsDialog.java -text forge-gui-mobile/src/forge/deck/FDeckChooser.java -text forge-gui-mobile/src/forge/deck/FDeckEditor.java -text +forge-gui-mobile/src/forge/deck/FDeckImportDialog.java -text forge-gui-mobile/src/forge/deck/FDeckViewer.java -text forge-gui-mobile/src/forge/deck/FSideboardDialog.java -text forge-gui-mobile/src/forge/deck/FVanguardChooser.java -text @@ -17594,6 +17595,7 @@ forge-gui/src/main/java/forge/control/WatchLocalGame.java -text forge-gui/src/main/java/forge/control/package-info.java -text forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java -text forge-gui/src/main/java/forge/deck/DeckGeneratorTheme.java -text +forge-gui/src/main/java/forge/deck/DeckImportController.java -text forge-gui/src/main/java/forge/deck/DeckProxy.java -text forge-gui/src/main/java/forge/deck/DeckType.java -text forge-gui/src/main/java/forge/deck/DeckgenUtil.java -text diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index 066ec9c4752..d362b4e72df 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -11,7 +11,6 @@ import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardLists; import forge.game.card.CardPredicates; -import forge.game.card.CounterType; import forge.game.cost.Cost; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; diff --git a/forge-core/src/main/java/forge/deck/Deck.java b/forge-core/src/main/java/forge/deck/Deck.java index 9a0f7526920..cf596b3b582 100644 --- a/forge-core/src/main/java/forge/deck/Deck.java +++ b/forge-core/src/main/java/forge/deck/Deck.java @@ -206,11 +206,23 @@ public class Deck extends DeckBase implements Iterable, In public final String getBestFileName() { return this.getName().replaceAll("[^-_$#@.,{[()]} a-zA-Z0-9]", ""); } + + public abstract boolean isEmpty(); } diff --git a/forge-core/src/main/java/forge/deck/DeckGroup.java b/forge-core/src/main/java/forge/deck/DeckGroup.java index bfaae6d6585..8a4bd32b91e 100644 --- a/forge-core/src/main/java/forge/deck/DeckGroup.java +++ b/forge-core/src/main/java/forge/deck/DeckGroup.java @@ -146,5 +146,10 @@ public class DeckGroup extends DeckBase { public Deck apply(DeckGroup arg1) { return arg1.getHumanDeck(); } - }; + }; + + @Override + public boolean isEmpty() { + return humanDeck == null || humanDeck.isEmpty(); + } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java index 4acbfbc78d4..10bf46368b6 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java @@ -19,31 +19,20 @@ package forge.screens.deckeditor; import forge.deck.Deck; import forge.deck.DeckBase; +import forge.deck.DeckImportController; import forge.deck.DeckRecognizer; import forge.deck.DeckRecognizer.TokenType; -import forge.deck.DeckSection; import forge.item.InventoryItem; -import forge.item.PaperCard; -import forge.model.FModel; import forge.screens.deckeditor.controllers.ACEditorBase; import forge.toolbox.*; import forge.view.FDialog; -import org.apache.commons.lang3.StringUtils; - import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import javax.swing.text.BadLocationException; -import javax.swing.text.Element; -import javax.swing.text.ElementIterator; - import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; -import java.text.DateFormatSymbols; -import java.util.ArrayList; -import java.util.Calendar; import java.util.List; /** @@ -94,18 +83,13 @@ public class DeckImport ex private final FComboBox monthDropdown = new FComboBox(); //don't need wrappers since skin can't change while this dialog is open private final FComboBox yearDropdown = new FComboBox(); - /** The tokens. */ - private final List tokens = new ArrayList(); - + private final DeckImportController controller; private final ACEditorBase host; - /** - * Instantiates a new deck import. - * - * @param g - * the g - */ + public DeckImport(final ACEditorBase g, boolean allowCardsFromAllSets) { + this.controller = new DeckImportController(!g.getDeckController().isEmpty(), + newEditionCheck, dateTimeCheck, onlyCoreExpCheck, monthDropdown, yearDropdown); this.host = g; final int wWidth = 700; @@ -130,11 +114,10 @@ public class DeckImport ex this.add(monthDropdown, "cell 0 3, w 20%, ax left, split 2, pad 0 4 0 0"); this.add(yearDropdown, "w 15%"); - fillDateDropdowns(); this.onlyCoreExpCheck.setSelected(!allowCardsFromAllSets); this.add(this.onlyCoreExpCheck, "cell 0 4, w 50%, ax c"); - + this.add(this.scrollOutput, "cell 1 0, w 50%, growy, pushy"); this.add(this.summaryMain, "cell 1 1, label"); this.add(this.summarySide, "cell 1 2, label"); @@ -153,11 +136,9 @@ public class DeckImport ex @SuppressWarnings("unchecked") @Override public void actionPerformed(final ActionEvent e) { - final String warning = "This will replace contents of your currently open deck with whatever you are importing. Proceed?"; - if (!FOptionPane.showConfirmDialog(warning, "Replacing old deck")) { - return; - } - final Deck toSet = DeckImport.this.buildDeck(); + final Deck toSet = controller.accept(); + if (toSet == null) { return; } + DeckImport.this.host.getDeckController().setModel((TModel) toSet); DeckImport.this.processWindowEvent(new WindowEvent(DeckImport.this, WindowEvent.WINDOW_CLOSING)); } @@ -188,63 +169,54 @@ public class DeckImport ex } /** - * TODO: Write javadoc for this method. + * The Class OnChangeTextUpdate. */ - private void fillDateDropdowns() { - DateFormatSymbols dfs = new DateFormatSymbols(); - monthDropdown.removeAllItems(); - String[] months = dfs.getMonths(); - for(String monthName : months) - if(!StringUtils.isBlank(monthName)) - monthDropdown.addItem(monthName); - int yearNow = Calendar.getInstance().get(Calendar.YEAR); - for(int i = yearNow; i >= 1993; i--) - yearDropdown.addItem(Integer.valueOf(i)); + protected class OnChangeTextUpdate implements DocumentListener { + private void onChange() { + parseAndDisplay(); + } + + @Override + public final void insertUpdate(final DocumentEvent e) { + this.onChange(); + } + + @Override + public final void removeUpdate(final DocumentEvent e) { + this.onChange(); + } + + @Override + public void changedUpdate(final DocumentEvent e) { + } // Happend only on ENTER pressed } - private void readInput() { - this.tokens.clear(); - final ElementIterator it = new ElementIterator(this.txtInput.getDocument().getDefaultRootElement()); - Element e; - - DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards()); - if (dateTimeCheck.isSelected()) { - recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), (Integer)yearDropdown.getSelectedItem()); - } - while ((e = it.next()) != null) { - if (!e.isLeaf()) { - continue; - } - final int rangeStart = e.getStartOffset(); - final int rangeEnd = e.getEndOffset(); - try { - final String line = this.txtInput.getText(rangeStart, rangeEnd - rangeStart); - this.tokens.add(recognizer.recognizeLine(line)); - } - catch (final BadLocationException ex) { - } - } + private void parseAndDisplay() { + List tokens = controller.parseInput(txtInput.getText()); + displayTokens(tokens); + updateSummaries(tokens); } - private void displayTokens() { - if(this.tokens.isEmpty()) - this.htmlOutput.setText(HTML_WELCOME_TEXT); + private void displayTokens(List tokens) { + if (tokens.isEmpty()) { + htmlOutput.setText(HTML_WELCOME_TEXT); + } else { final StringBuilder sbOut = new StringBuilder(""); sbOut.append(DeckImport.STYLESHEET); - for (final DeckRecognizer.Token t : this.tokens) { - sbOut.append(this.makeHtmlViewOfToken(t)); + for (final DeckRecognizer.Token t : tokens) { + sbOut.append(makeHtmlViewOfToken(t)); } sbOut.append(""); - this.htmlOutput.setText(sbOut.toString()); + htmlOutput.setText(sbOut.toString()); } } - private void updateSummaries() { + private void updateSummaries(List tokens) { final int[] cardsOk = new int[2]; final int[] cardsUnknown = new int[2]; int idx = 0; - for (final DeckRecognizer.Token t : this.tokens) { + for (final DeckRecognizer.Token t : tokens) { if (t.getType() == TokenType.KnownCard) { cardsOk[idx] += t.getNumber(); } @@ -255,81 +227,9 @@ public class DeckImport ex idx = 1; } } - this.summaryMain.setText(String.format("Main: %d cards recognized, %d unknown cards", cardsOk[0], cardsUnknown[0])); - this.summarySide.setText(String.format("Sideboard: %d cards recognized, %d unknown cards", cardsOk[1], cardsUnknown[1])); - this.cmdAccept.setEnabled(cardsOk[0] > 0); - } - - private Deck buildDeck() { - final Deck result = new Deck(); - boolean isMain = true; - for (final DeckRecognizer.Token t : this.tokens) { - final DeckRecognizer.TokenType type = t.getType(); - if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) { - isMain = false; - } - if (type != DeckRecognizer.TokenType.KnownCard) { - continue; - } - final PaperCard crd = t.getCard(); - if (isMain) { - result.getMain().add(crd, t.getNumber()); - } - else { - result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber()); - } - } - return result; - } - - protected void parseAndDisplay() { - readInput(); - displayTokens(); - updateSummaries(); - } - - /** - * The Class OnChangeTextUpdate. - */ - protected class OnChangeTextUpdate implements DocumentListener { - private void onChange() { - DeckImport.this.parseAndDisplay(); - } - - /* - * (non-Javadoc) - * - * @see - * javax.swing.event.DocumentListener#insertUpdate(javax.swing.event - * .DocumentEvent) - */ - @Override - public final void insertUpdate(final DocumentEvent e) { - this.onChange(); - } - - /* - * (non-Javadoc) - * - * @see - * javax.swing.event.DocumentListener#removeUpdate(javax.swing.event - * .DocumentEvent) - */ - @Override - public final void removeUpdate(final DocumentEvent e) { - this.onChange(); - } - - /* - * (non-Javadoc) - * - * @see - * javax.swing.event.DocumentListener#changedUpdate(javax.swing.event - * .DocumentEvent) - */ - @Override - public void changedUpdate(final DocumentEvent e) { - } // Happend only on ENTER pressed + summaryMain.setText(String.format("Main: %d cards recognized, %d unknown cards", cardsOk[0], cardsUnknown[0])); + summarySide.setText(String.format("Sideboard: %d cards recognized, %d unknown cards", cardsOk[1], cardsUnknown[1])); + cmdAccept.setEnabled(cardsOk[0] > 0); } private String makeHtmlViewOfToken(final DeckRecognizer.Token token) { @@ -345,9 +245,7 @@ public class DeckImport ex case Comment: return String.format("
%s
", token.getText()); default: - break; + return ""; } - return ""; } - } diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java index 9fb546949fe..bf08a0b1c95 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java @@ -72,6 +72,10 @@ public class DeckController { return this.modelPath; } + public boolean isEmpty() { + return model == null || model.isEmpty(); + } + /** * Sets the model. * diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index e17aab4fb4f..ebdc5df81d8 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -319,7 +319,6 @@ public enum CSubmenuPreferences implements ICDoc { private void addComboBoxListener(final FComboBox comboBox, final ForgePreferences.FPref setting) { comboBox.addItemListener(new ItemListener() { - @SuppressWarnings("unchecked") @Override public void itemStateChanged(final ItemEvent e) { E selectedType = (E) comboBox.getSelectedItem(); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FComboBox.java b/forge-gui-desktop/src/main/java/forge/toolbox/FComboBox.java index 9fb8fecb55b..2244493d70f 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FComboBox.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FComboBox.java @@ -94,6 +94,12 @@ public class FComboBox extends SkinnedComboBox implements IComboBox { return maxWidth + 28; //leave room for arrow and padding } + @SuppressWarnings("unchecked") + @Override + public E getSelectedItem() { + return (E)super.getSelectedItem(); + } + @Override protected void paintComponent(Graphics g) { super.paintComponent(g); diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index dbad4d26f8f..623ba5e451d 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -306,6 +306,27 @@ public class FDeckEditor extends TabPageScreen { setSelectedPage(getMainDeckPage()); //select main deck page if needed so main deck if visible below dialog } })); + if (!isLimitedEditor()) { + addItem(new FMenuItem("Import Deck", FSkinImage.OPEN, new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + FDeckImportDialog dialog = new FDeckImportDialog(deck.isEmpty(), new Callback() { + @Override + public void run(Deck importedDeck) { + getMainDeckPage().setCards(importedDeck.getMain()); + if (getSideboardPage() != null) { + getSideboardPage().setCards(importedDeck.getOrCreate(DeckSection.Sideboard)); + } + if (getCommanderPage() != null) { + getCommanderPage().setCards(importedDeck.getOrCreate(DeckSection.Commander)); + } + } + }); + dialog.show(); + setSelectedPage(getMainDeckPage()); //select main deck page if needed so main deck if visible below dialog + } + })); + } if (allowRename()) { addItem(new FMenuItem("Rename Deck", FSkinImage.EDIT, new FEventHandler() { @Override diff --git a/forge-gui-mobile/src/forge/deck/FDeckImportDialog.java b/forge-gui-mobile/src/forge/deck/FDeckImportDialog.java new file mode 100644 index 00000000000..d23b0b47294 --- /dev/null +++ b/forge-gui-mobile/src/forge/deck/FDeckImportDialog.java @@ -0,0 +1,80 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.deck; + +import forge.toolbox.FCheckBox; +import forge.toolbox.FComboBox; +import forge.toolbox.FDialog; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; +import forge.toolbox.FOptionPane; +import forge.toolbox.FTextArea; +import forge.util.Callback; + + +public class FDeckImportDialog extends FDialog { + private final Callback callback; + + private final FTextArea txtInput = add(new FTextArea(true)); + private final FCheckBox newEditionCheck = new FCheckBox("Import latest version of card", true); + private final FCheckBox dateTimeCheck = new FCheckBox("Use only sets released before:", false); + private final FCheckBox onlyCoreExpCheck = new FCheckBox("Use only core and expansion sets", true); + + private final FComboBox monthDropdown = new FComboBox(); //don't need wrappers since skin can't change while this dialog is open + private final FComboBox yearDropdown = new FComboBox(); + + private final DeckImportController controller; + + public FDeckImportDialog(final boolean replacingDeck, final Callback callback0) { + super("Import Deck", 2); + + callback = callback0; + controller = new DeckImportController(replacingDeck, newEditionCheck, dateTimeCheck, onlyCoreExpCheck, monthDropdown, yearDropdown); + + initButton(0, "OK", new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + controller.parseInput(txtInput.getText()); + Deck deck = controller.accept(); + if (deck == null) { return; } + + hide(); + callback.run(deck); + } + }); + initButton(1, "Cancel", new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + hide(); + } + }); + } + + @Override + protected float layoutAndGetHeight(float width, float maxHeight) { + float padding = FOptionPane.PADDING; + float x = padding; + float y = padding; + float w = width - 2 * padding; + float h = maxHeight - 2 * padding; + + txtInput.setBounds(x, y, w, h); + + return maxHeight; + } +} diff --git a/forge-gui/src/main/java/forge/deck/DeckImportController.java b/forge-gui/src/main/java/forge/deck/DeckImportController.java new file mode 100644 index 00000000000..73826a9a366 --- /dev/null +++ b/forge-gui/src/main/java/forge/deck/DeckImportController.java @@ -0,0 +1,93 @@ +package forge.deck; + +import java.text.DateFormatSymbols; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import forge.interfaces.ICheckBox; +import forge.interfaces.IComboBox; +import forge.item.PaperCard; +import forge.model.FModel; +import forge.util.gui.SOptionPane; + +public class DeckImportController { + private final boolean replacingDeck; + private final ICheckBox newEditionCheck, dateTimeCheck, onlyCoreExpCheck; + private final IComboBox monthDropdown; + private final IComboBox yearDropdown; + private final List tokens = new ArrayList(); + + public DeckImportController(boolean replacingDeck0, ICheckBox newEditionCheck0, ICheckBox dateTimeCheck0, ICheckBox onlyCoreExpCheck0, IComboBox monthDropdown0, IComboBox yearDropdown0) { + replacingDeck = replacingDeck0; + newEditionCheck = newEditionCheck0; + dateTimeCheck = dateTimeCheck0; + onlyCoreExpCheck = onlyCoreExpCheck0; + monthDropdown = monthDropdown0; + yearDropdown = yearDropdown0; + + fillDateDropdowns(); + } + + private void fillDateDropdowns() { + DateFormatSymbols dfs = new DateFormatSymbols(); + monthDropdown.removeAllItems(); + String[] months = dfs.getMonths(); + for (String monthName : months) { + if (!StringUtils.isBlank(monthName)) { + monthDropdown.addItem(monthName); + } + } + int yearNow = Calendar.getInstance().get(Calendar.YEAR); + for (int i = yearNow; i >= 1993; i--) { + yearDropdown.addItem(Integer.valueOf(i)); + } + } + + public List parseInput(String input) { + tokens.clear(); + + DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards()); + if (dateTimeCheck.isSelected()) { + recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem()); + } + String[] lines = input.split("\n"); + for (String line : lines) { + tokens.add(recognizer.recognizeLine(line)); + } + return tokens; + } + + public Deck accept() { + if (tokens.isEmpty()) { return null; } + + if (replacingDeck) { + final String warning = "This will replace contents of the current deck with whatever you are importing.\n\nProceed?"; + if (!SOptionPane.showConfirmDialog(warning, "Replace Current Deck", "Replace", "Cancel")) { + return null; + } + } + + final Deck result = new Deck(); + boolean isMain = true; + for (final DeckRecognizer.Token t : tokens) { + final DeckRecognizer.TokenType type = t.getType(); + if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) { + isMain = false; + } + if (type != DeckRecognizer.TokenType.KnownCard) { + continue; + } + final PaperCard crd = t.getCard(); + if (isMain) { + result.getMain().add(crd, t.getNumber()); + } + else { + result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber()); + } + } + return result; + } +} diff --git a/forge-gui/src/main/java/forge/interfaces/IComboBox.java b/forge-gui/src/main/java/forge/interfaces/IComboBox.java index 531270512b8..8d51970cbd9 100644 --- a/forge-gui/src/main/java/forge/interfaces/IComboBox.java +++ b/forge-gui/src/main/java/forge/interfaces/IComboBox.java @@ -9,4 +9,6 @@ public interface IComboBox { void setSelectedIndex(int index); void addItem(E item); void removeAllItems(); + int getSelectedIndex(); + E getSelectedItem(); } diff --git a/forge-gui/src/main/java/forge/limited/CustomLimited.java b/forge-gui/src/main/java/forge/limited/CustomLimited.java index 090fafeef4e..fab9b0d1d94 100644 --- a/forge-gui/src/main/java/forge/limited/CustomLimited.java +++ b/forge-gui/src/main/java/forge/limited/CustomLimited.java @@ -93,7 +93,6 @@ public class CustomLimited extends DeckBase { * @return the custom limited */ public static CustomLimited parse(final List dfData, final IStorage cubes) { - final FileSection data = FileSection.parse(dfData, ":"); List> slots = new ArrayList>(); @@ -117,8 +116,6 @@ public class CustomLimited extends DeckBase { return cd; } - - /** * Gets the num packs. * @@ -177,4 +174,9 @@ public class CustomLimited extends DeckBase { public boolean isSingleton() { return singleton; } + + @Override + public boolean isEmpty() { + return cardPool.isEmpty(); + } }