Various new Drag & Drop deck editor improvements

* Shift-Click / Shift-Drag now work as expected as far as multi-selection
* Deck editor saves split pane split positions
* Card layout and sort settings are now saved along side the a deck when saving to the .dck format, so that you have back the exact same deck layout when you re-load the deck.
* Fixed the symbol image downloader to work around some of the large-size symbol images being missing on gatherer. Falls back to the medium sized images currently for those symbols.
This commit is contained in:
Mark Langen 2016-10-04 00:04:13 -06:00
parent 38cbf1a687
commit f6d50ce04f
11 changed files with 516 additions and 238 deletions

View file

@ -33,6 +33,7 @@ import java.io.PrintWriter;
import java.util.*;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLayout;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
@ -166,16 +167,47 @@ public class Sets extends HashMap<String, ExpansionSet> {
}
}
// Write out all of the cards
for (Map.Entry<String, DeckCardInfo> 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<String, DeckCardInfo> 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.print("\n");
out.print("LAYOUT SIDEBOARD:");
writeCardLayout(out, deck.getSideboardLayout());
out.print("\n");
}
finally {
out.close();
}
}
private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) {
List<List<List<DeckCardInfo>>> 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<List<DeckCardInfo>> row : cardGrid) {
for (List<DeckCardInfo> 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(")");
}
}
}
}

View file

@ -44,6 +44,8 @@ public class Deck implements Serializable {
private String name;
private final Set<Card> cards = new LinkedHashSet<>();
private final Set<Card> sideboard = new LinkedHashSet<>();
private DeckCardLayout cardsLayout;
private DeckCardLayout sideboardLayout;
private long deckHashCode = 0;
public static Deck load(DeckCardLists deckCardLists) throws GameException {
@ -57,6 +59,8 @@ public class Deck implements Serializable {
public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards) throws GameException {
Deck deck = new Deck();
deck.setName(deckCardLists.getName());
deck.cardsLayout = deckCardLists.getCardLayout();
deck.sideboardLayout = deckCardLists.getSideboardLayout();
List<String> deckCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo : deckCardLists.getCards()) {
Card card = createCard(deckCardInfo, mockCards);
@ -141,10 +145,18 @@ public class Deck implements Serializable {
return cards;
}
public DeckCardLayout getCardsLayout() {
return cardsLayout;
}
public Set<Card> getSideboard() {
return sideboard;
}
public DeckCardLayout getSideboardLayout() {
return sideboardLayout;
}
public long getDeckHashCode() {
return deckHashCode;
}

View file

@ -0,0 +1,24 @@
package mage.cards.decks;
import java.util.List;
/**
* Created by stravant@gmail.com on 2016-10-03.
*/
public class DeckCardLayout {
private List<List<List<DeckCardInfo>>> cards;
private String settings;
public DeckCardLayout(List<List<List<DeckCardInfo>>> cards, String settings) {
this.cards = cards;
this.settings = settings;
}
public List<List<List<DeckCardInfo>>> getCards() {
return cards;
}
public String getSettings() {
return settings;
}
}

View file

@ -42,6 +42,26 @@ public class DeckCardLists implements Serializable {
private List<DeckCardInfo> cards = new ArrayList<>();
private List<DeckCardInfo> sideboard = new ArrayList<>();
// Layout (if supported)
private DeckCardLayout cardLayout = null;
private DeckCardLayout sideboardLayout = null;
/**
* @return The layout of the cards
*/
public DeckCardLayout getCardLayout() {
return cardLayout;
}
public void setCardLayout(DeckCardLayout layout) {
this.cardLayout = layout;
}
public DeckCardLayout getSideboardLayout() {
return sideboardLayout;
}
public void setSideboardLayout(DeckCardLayout layout) {
this.sideboardLayout = layout;
}
/**
* @return the cards
*/

View file

@ -27,9 +27,12 @@
*/
package mage.cards.decks.importer;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLayout;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
@ -42,6 +45,12 @@ public class DckDeckImporter extends DeckImporter {
private static final Pattern pattern = Pattern.compile("(SB:)?\\s*(\\d*)\\s*\\[([^]:]+):([^]:]+)\\].*");
private static final Pattern layoutPattern = Pattern.compile("LAYOUT (\\w+):\\((\\d+),(\\d+)\\)([^|]+)\\|(.*)$");
private static final Pattern layoutStackPattern = Pattern.compile("\\(([^)]*)\\)");
private static final Pattern layoutStackEntryPattern = Pattern.compile("\\[(\\w+):(\\w+)]");
@Override
protected void readLine(String line, DeckCardLists deckList) {
@ -79,6 +88,56 @@ public class DckDeckImporter extends DeckImporter {
deckList.setName(line.substring(5, line.length()));
} else if (line.startsWith("AUTHOR:")) {
deckList.setAuthor(line.substring(7, line.length()));
} else if (line.startsWith("LAYOUT")) {
Matcher m2 = layoutPattern.matcher(line);
if (m2.find()) {
String target = m2.group(1);
int rows = Integer.parseInt(m2.group(2));
int cols = Integer.parseInt(m2.group(3));
String settings = m2.group(4);
String stackData = m2.group(5);
Matcher stackMatcher = layoutStackPattern.matcher(stackData);
//
List<List<List<DeckCardInfo>>> grid = new ArrayList<>();
int totalCardCount = 0;
for (int row = 0; row < rows; ++row) {
List<List<DeckCardInfo>> rowData = new ArrayList<>();
grid.add(rowData);
for (int col = 0; col < cols; ++col) {
List<DeckCardInfo> stack = new ArrayList<>();
rowData.add(stack);
if (stackMatcher.find()) {
String thisStackData = stackMatcher.group(1);
Matcher stackEntries = layoutStackEntryPattern.matcher(thisStackData);
while (stackEntries.find()) {
++totalCardCount;
stack.add(new DeckCardInfo("", stackEntries.group(2), stackEntries.group(1)));
}
} else {
sbMessage.append("Missing stack\n.");
}
}
}
//
DeckCardLayout layout = new DeckCardLayout(grid, settings);
int expectedCount = 0;
if (target.equals("MAIN")) {
deckList.setCardLayout(layout);
expectedCount = deckList.getCards().size();
} else if (target.equals("SIDEBOARD")) {
deckList.setSideboardLayout(layout);
expectedCount = deckList.getSideboard().size();
} else {
sbMessage.append("Bad target `" + target + "` for layout.\n");
}
//
if (totalCardCount != expectedCount) {
sbMessage.append("Layout mismatch: Expected " + expectedCount + " cards, but got " + totalCardCount + " in layout `" + target + "`\n.");
}
} else {
sbMessage.append("Malformed layout line");
}
}
}
}