From 3c2c793f5dc2ef47e293ed6447731b1e35143f74 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Sat, 24 Sep 2016 21:12:40 -0600 Subject: [PATCH] Drag n Drop Deck Editor WIP * Working standalone proof-of-concept application in DragCardGrid. * Still needs listener functionality in order to integrate it into the existing DeckEditorPanel class. --- .../client/cards/CardDraggerGlassPane.java | 170 ++++ .../java/mage/client/cards/DragCardGrid.java | 949 ++++++++++++++++++ .../mage/client/cards/DragCardSource.java | 14 + .../mage/client/cards/DragCardTarget.java | 17 + .../src/main/resources/editor_insert_col.png | Bin 0 -> 2093 bytes .../src/main/resources/editor_insert_row.png | Bin 0 -> 1900 bytes db/cards.h2.mv.db | Bin 0 -> 16384 bytes db/cards.h2.trace.db | 171 ++++ mageclient.log | 80 ++ 9 files changed, 1401 insertions(+) create mode 100644 Mage.Client/src/main/java/mage/client/cards/CardDraggerGlassPane.java create mode 100644 Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java create mode 100644 Mage.Client/src/main/java/mage/client/cards/DragCardSource.java create mode 100644 Mage.Client/src/main/java/mage/client/cards/DragCardTarget.java create mode 100644 Mage.Client/src/main/resources/editor_insert_col.png create mode 100644 Mage.Client/src/main/resources/editor_insert_row.png create mode 100644 db/cards.h2.mv.db create mode 100644 db/cards.h2.trace.db create mode 100644 mageclient.log diff --git a/Mage.Client/src/main/java/mage/client/cards/CardDraggerGlassPane.java b/Mage.Client/src/main/java/mage/client/cards/CardDraggerGlassPane.java new file mode 100644 index 00000000000..ac5efde71cd --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/CardDraggerGlassPane.java @@ -0,0 +1,170 @@ +package mage.client.cards; + +import mage.cards.MageCard; +import mage.client.plugins.impl.Plugins; +import mage.view.CardView; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.ArrayList; +import java.util.Collection; + +/** + * Created by StravantUser on 2016-09-22. + */ +public class CardDraggerGlassPane extends JPanel implements MouseListener, MouseMotionListener { + private DragCardSource source; + private Component dragComponent; + private JRootPane currentRoot; + private Component oldGlassPane; + private ArrayList currentCards; + private MageCard dragView; + private DragCardTarget currentDragTarget; + private boolean isDragging; + + public CardDraggerGlassPane(DragCardSource source) { + this.source = source; + + // Listen on self + setLayout(null); + setOpaque(false); + setVisible(true); + } + + public void beginDrag(Component c, MouseEvent e) { + // Start drag + if (isDragging) { + return; + } + isDragging = true; + + // Record what we are dragging on + dragComponent = c; + currentRoot = SwingUtilities.getRootPane(c); + + // Hook up events + c.addMouseListener(this); + c.addMouseMotionListener(this); + + // Switch glass pane to us + oldGlassPane = currentRoot.getGlassPane(); + setVisible(false); + currentRoot.setGlassPane(this); + setVisible(true); + revalidate(); + + // Event to local space + e = SwingUtilities.convertMouseEvent(c, e, this); + + // Get the cards to drag + currentCards = new ArrayList<>(source.dragCardList()); + + // Make a view for the first one and add it to us + dragView = Plugins.getInstance().getMageCard(currentCards.get(0), null, new Dimension(100, 140), null, true); + for (MouseListener l: dragView.getMouseListeners()) { + dragView.removeMouseListener(l); + } + for (MouseMotionListener l : dragView.getMouseMotionListeners()) { + dragView.removeMouseMotionListener(l); + } + this.add(dragView); + dragView.setLocation(e.getX(), e.getY()); + + // Notify the sounce + source.dragCardBegin(); + + // Update the target + currentDragTarget = null; + updateCurrentTarget(SwingUtilities.convertMouseEvent(c, e, currentRoot), false); + } + + // e is relative to currentRoot + private void updateCurrentTarget(MouseEvent e, boolean isEnding) { + Component mouseOver = SwingUtilities.getDeepestComponentAt(currentRoot.getContentPane(), e.getX(), e.getY()); + while (mouseOver != null) { + if (mouseOver instanceof DragCardTarget) { + DragCardTarget target = (DragCardTarget)mouseOver; + MouseEvent targetEvent = SwingUtilities.convertMouseEvent(currentRoot, e, mouseOver); + if (target != currentDragTarget) { + if (currentDragTarget != null) { + MouseEvent oldTargetEvent = SwingUtilities.convertMouseEvent(currentRoot, e, (Component) currentDragTarget); + currentDragTarget.dragCardExit(oldTargetEvent); + } + currentDragTarget = target; + currentDragTarget.dragCardEnter(targetEvent); + } + if (isEnding) { + currentDragTarget.dragCardExit(targetEvent); + currentDragTarget.dragCardDrop(targetEvent, source, currentCards); + } else { + currentDragTarget.dragCardMove(targetEvent); + } + return; + } + mouseOver = mouseOver.getParent(); + } + if (currentDragTarget != null) { + MouseEvent oldTargetEvent = SwingUtilities.convertMouseEvent(currentRoot, e, (Component)currentDragTarget); + currentDragTarget.dragCardExit(oldTargetEvent); + } + currentDragTarget = null; + } + + public boolean isDragging() { + return isDragging; + } + + /** + * Mouse released -> we are done the drag + */ + @Override + public void mouseReleased(MouseEvent e) { + // No longer dragging + isDragging = false; + + // Remove listeners + dragComponent.removeMouseListener(this); + dragComponent.removeMouseMotionListener(this); + + // Convert the event into root coords + e = SwingUtilities.convertMouseEvent(dragComponent, e, currentRoot); + + // Switch back glass pane + currentRoot.setGlassPane(oldGlassPane); + + // Remove the drag card + this.remove(dragView); + + // Update the target, and do the drop + updateCurrentTarget(e, true); + + // Let the drag source know + source.dragCardEnd(currentDragTarget); + } + + @Override + public void mouseDragged(MouseEvent e) { + // Update the view + MouseEvent glassE = SwingUtilities.convertMouseEvent(dragComponent, e, this); + dragView.setLocation(glassE.getX(), glassE.getY()); + dragView.repaint(); + + // Convert the event into root coords and update target + e = SwingUtilities.convertMouseEvent(dragComponent, e, currentRoot); + updateCurrentTarget(e, false); + } + + @Override + public void mouseClicked(MouseEvent e) {} + @Override + public void mousePressed(MouseEvent e) {} + @Override + public void mouseEntered(MouseEvent e) {} + @Override + public void mouseExited(MouseEvent e) {} + @Override + public void mouseMoved(MouseEvent e) {} +} diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java new file mode 100644 index 00000000000..1a193e6f983 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java @@ -0,0 +1,949 @@ +package mage.client.cards; + +import mage.cards.MageCard; +import mage.cards.decks.Deck; +import mage.cards.decks.importer.DeckImporterUtil; +import mage.client.MageFrame; +import mage.client.plugins.impl.Plugins; +import mage.client.util.CardViewColorComparator; +import mage.client.util.CardViewCostComparator; +import mage.client.util.CardViewRarityComparator; +import mage.client.util.GUISizeHelper; +import mage.constants.CardType; +import mage.game.GameException; +import mage.interfaces.plugin.CardPlugin; +import mage.view.CardView; +import mage.view.CardsView; +import org.apache.log4j.Logger; +import org.mage.card.arcane.CardRenderer; +import org.mage.plugins.card.CardPluginImpl; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.FlavorMap; +import java.awt.dnd.*; +import java.awt.event.*; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.*; + +/** + * Created by StravantUser on 2016-09-20. + */ +public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarget { + private static Logger LOGGER = Logger.getLogger(DragCardGrid.class); + + @Override + public Collection dragCardList() { + ArrayList selectedCards = new ArrayList<>(); + for (CardView card : allCards) { + if (card.isSelected()) { + selectedCards.add(card); + } + } + return selectedCards; + } + + @Override + public void dragCardBegin() { + LOGGER.info("Begin drag"); + } + + @Override + public void dragCardEnd(DragCardTarget target) { + LOGGER.info("End drag (" + target + ")"); + if (target == this) { + // Already handled by dragged onto handler + } else { + // Remove dragged cards + for (ArrayList> gridRow : cardGrid) { + for (ArrayList stack : gridRow) { + for (int i = 0; i < stack.size(); ++i) { + CardView view = stack.get(i); + if (view.isSelected()) { + stack.set(i, null); + } + } + } + } + trimGrid(); + layoutGrid(); + cardScroll.repaint(); + } + } + + @Override + public void dragCardEnter(MouseEvent e) { + insertArrow.setVisible(true); + } + + @Override + public void dragCardMove(MouseEvent e) { + e = SwingUtilities.convertMouseEvent(this, e, cardContent); + showDropPosition(e.getX(), e.getY()); + } + + private void showDropPosition(int x, int y) { + // Clamp to region + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + + // Determine column + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + int cardTopHeight = CardRenderer.getCardTopHeight(cardWidth); + int dx = x % (cardWidth + GRID_PADDING); + int col = x / (cardWidth + GRID_PADDING); + int gridWidth = cardGrid.isEmpty() ? 0 : cardGrid.get(0).size(); + + if (dx < GRID_PADDING && col < gridWidth) { + // Which row to add to? + int curY = COUNT_LABEL_HEIGHT; + int rowIndex = 0; + for (int i = 0; i < cardGrid.size(); ++i) { + int maxStack = maxStackSize.get(i); + int rowHeight = cardTopHeight*(maxStack-1) + cardHeight; + int rowBottom = curY + rowHeight + COUNT_LABEL_HEIGHT; + + // Break out if we're in that row + if (y < rowBottom) { + // Set the row + rowIndex = i; + break; + } else { + rowIndex = i+1; + curY = rowBottom; + } + } + + // Insert between two columns + insertArrow.setIcon(INSERT_COL_ICON); + insertArrow.setSize(64, 64); + insertArrow.setLocation((cardWidth + GRID_PADDING)*col + GRID_PADDING/2 - 32, curY); + } else { + // Clamp to a new col one after the current last one + col = Math.min(col, gridWidth); + + // Determine place in the col + int curY = COUNT_LABEL_HEIGHT; + int rowIndex = 0; + int offsetIntoStack = 0; + for (int i = 0; i < cardGrid.size(); ++i) { + int maxStack = maxStackSize.get(i); + int rowHeight = cardTopHeight*(maxStack-1) + cardHeight; + int rowBottom = curY + rowHeight + COUNT_LABEL_HEIGHT; + + // Break out if we're in that row + if (y < rowBottom) { + // Set the row + rowIndex = i; + offsetIntoStack = y - curY; + break; + } else { + rowIndex = i+1; + offsetIntoStack = y - rowBottom; + curY = rowBottom; + } + } + + // Get the appropirate stack + ArrayList stack; + if (rowIndex < cardGrid.size() && col < cardGrid.get(0).size()) { + stack = cardGrid.get(rowIndex).get(col); + } else { + stack = new ArrayList<>(); + } + + // Figure out position in the stack based on the offsetIntoRow + int stackInsertIndex = (offsetIntoStack + cardTopHeight/2) / cardTopHeight; + stackInsertIndex = Math.max(0, Math.min(stackInsertIndex, stack.size())); + + // Position arrow + insertArrow.setIcon(INSERT_ROW_ICON); + insertArrow.setSize(64, 32); + insertArrow.setLocation((cardWidth + GRID_PADDING)*col + GRID_PADDING + cardWidth/2 - 32, curY + stackInsertIndex*cardTopHeight - 32); + } + } + + @Override + public void dragCardExit(MouseEvent e) { + insertArrow.setVisible(false); + } + + @Override + public void dragCardDrop(MouseEvent e, DragCardSource source, Collection cards) { + e = SwingUtilities.convertMouseEvent(this, e, cardContent); + int x = e.getX(); + int y = e.getY(); + + // Clamp to region + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + + // If we're dragging onto ourself, erase the old cards (just null them out, we will + // compact the grid removing the null gaps / empty rows & cols later) + if (source == this) { + for (ArrayList> gridRow : cardGrid) { + for (ArrayList stack : gridRow) { + for (int i = 0; i < stack.size(); ++i) { + if (cards.contains(stack.get(i))) { + stack.set(i, null); + } + } + } + } + } + + // Determine column + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + int cardTopHeight = CardRenderer.getCardTopHeight(cardWidth); + int dx = x % (cardWidth + GRID_PADDING); + int col = x / (cardWidth + GRID_PADDING); + int gridWidth = cardGrid.isEmpty() ? 0 : cardGrid.get(0).size(); + + if (dx < GRID_PADDING && col < gridWidth) { + // Which row to add to? + int curY = COUNT_LABEL_HEIGHT; + int rowIndex = 0; + for (int i = 0; i < cardGrid.size(); ++i) { + int maxStack = maxStackSize.get(i); + int rowHeight = cardTopHeight*(maxStack-1) + cardHeight; + int rowBottom = curY + rowHeight + COUNT_LABEL_HEIGHT; + + // Break out if we're in that row + if (y < rowBottom) { + // Set the row + rowIndex = i; + break; + } else { + rowIndex = i+1; + curY = rowBottom; + } + } + + // Add a new row if needed + if (rowIndex >= cardGrid.size()) { + ArrayList> newRow = new ArrayList<>(); + if (!cardGrid.isEmpty()) { + for (int colIndex = 0; colIndex < cardGrid.get(0).size(); ++colIndex) { + newRow.add(new ArrayList()); + } + } + cardGrid.add(newRow); + maxStackSize.add(0); + } + + // Insert the new column to add to + for (int i = 0; i < cardGrid.size(); ++i) { + cardGrid.get(i).add(col, new ArrayList()); + } + + // Add the cards + cardGrid.get(rowIndex).get(col).addAll(cards); + } else { + // Clamp to a new col one after the current last one + col = Math.min(col, gridWidth); + + // Determine place in the col + int curY = COUNT_LABEL_HEIGHT; + int rowIndex = 0; + int offsetIntoStack = 0; + for (int i = 0; i < cardGrid.size(); ++i) { + int maxStack = maxStackSize.get(i); + int rowHeight = cardTopHeight*(maxStack-1) + cardHeight; + int rowBottom = curY + rowHeight + COUNT_LABEL_HEIGHT; + + // Break out if we're in that row + if (y < rowBottom) { + // Set the row + rowIndex = i; + offsetIntoStack = y - curY; + break; + } else { + rowIndex = i+1; + offsetIntoStack = y - rowBottom; + curY = rowBottom; + } + } + + // Add a new row if needed + if (rowIndex >= cardGrid.size()) { + ArrayList> newRow = new ArrayList<>(); + if (!cardGrid.isEmpty()) { + for (int colIndex = 0; colIndex < cardGrid.get(0).size(); ++colIndex) { + newRow.add(new ArrayList()); + } + } + cardGrid.add(newRow); + maxStackSize.add(0); + } + + // Add a new col if needed + if (col >= cardGrid.get(0).size()) { + for (int i = 0; i < cardGrid.size(); ++i) { + cardGrid.get(i).add(new ArrayList()); + } + } + + // Get the appropirate stack + ArrayList stack = cardGrid.get(rowIndex).get(col); + + // Figure out position in the stack based on the offsetIntoRow + int stackInsertIndex = (offsetIntoStack + cardTopHeight/2) / cardTopHeight; + stackInsertIndex = Math.max(0, Math.min(stackInsertIndex, stack.size())); + + // Insert the cards + stack.addAll(stackInsertIndex, cards); + } + + // Remove empty rows / cols / spaces in stacks + if (source == this) { + trimGrid(); + layoutGrid(); + cardScroll.repaint(); + } + } + + public enum Sort { + NONE(new Comparator() { + @Override + public int compare(CardView o1, CardView o2) { + // Always equal, sort into the first row + return 0; + } + }), + CMC(new CardViewCostComparator()), + COLOR(new CardViewColorComparator()), + RARITY(new CardViewRarityComparator()); + + Sort(Comparator comparator) { + this.comparator = comparator; + } + + public Comparator getComparator() { + return comparator; + } + + private Comparator comparator; + } + + + + // Constants + public static int CARD_WIDTH = 150; + public static int COUNT_LABEL_HEIGHT = 20; + public static int GRID_PADDING = 10; + + private static ImageIcon INSERT_ROW_ICON = new ImageIcon(DragCardGrid.class.getClassLoader().getResource("editor_insert_row.png")); + private static ImageIcon INSERT_COL_ICON = new ImageIcon(DragCardGrid.class.getClassLoader().getResource("editor_insert_col.png")); + + // All of the current card views + private Map cardViews = new LinkedHashMap<>(); + private ArrayList allCards = new ArrayList<>(); + + // Top bar with dropdowns for sort / filter / etc + JButton sortButton; + JButton filterButton; + + // Popup for toolbar + JPopupMenu filterPopup; + JPopupMenu sortPopup; + + // Main two controls holding the scrollable card grid + JScrollPane cardScroll; + JLayeredPane cardContent; + + // Drag onto insert arrow + JLabel insertArrow; + + // Card area selection panel + SelectionBox selectionPanel; + int selectionDragStartX; + int selectionDragStartY; + + // Dragging + private CardDraggerGlassPane dragger = new CardDraggerGlassPane(this); + + // The grid of cards + // The outermost array contains multiple rows of stacks of cards + // The next inner array represents a row of stacks of cards + // The innermost array represents a single vertical stack of cards + private ArrayList>> cardGrid; + private ArrayList maxStackSize = new ArrayList<>(); + private ArrayList> stackCountLabels = new ArrayList<>(); + private Sort cardSort = Sort.CMC; + private boolean separateCreatures = true; + + // Constructor + public DragCardGrid() { + // Make sure that the card grid is populated with at least one (empty) stack to begin with + cardGrid = new ArrayList<>(); + + // Component init + setLayout(new BorderLayout()); + + // Toolbar + sortButton = new JButton("Sort"); + filterButton = new JButton("Filter"); + + // Tmp load button + JButton loadButton = new JButton("Load"); + loadButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + loadDeck(); + } + }); + + JPanel toolbar = new JPanel(new BorderLayout()); + JPanel toolbarInner = new JPanel(); + toolbar.setBackground(new Color(250, 250, 250, 150)); + toolbar.setOpaque(true); + toolbarInner.setOpaque(false); + toolbarInner.add(sortButton); + toolbarInner.add(filterButton); + toolbarInner.add(loadButton); + toolbar.add(toolbarInner, BorderLayout.WEST); + this.add(toolbar, BorderLayout.NORTH); + + // Content + cardContent = new JLayeredPane(); + cardContent.setLayout(null); + cardContent.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + beginSelectionDrag(e.getX(), e.getY()); + updateSelectionDrag(e.getX(), e.getY()); + } + @Override + public void mouseReleased(MouseEvent e) { + updateSelectionDrag(e.getX(), e.getY()); + endSelectionDrag(e.getX(), e.getY()); + } + }); + cardContent.addMouseMotionListener(new MouseAdapter() { + @Override + public void mouseDragged(MouseEvent e) { + updateSelectionDrag(e.getX(), e.getY()); + } + }); + cardScroll = new JScrollPane(cardContent, + ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + this.add(cardScroll, BorderLayout.CENTER); + + // Insert arrow + insertArrow = new JLabel(); + insertArrow.setSize(20, 20); + insertArrow.setVisible(false); + cardContent.add(insertArrow, new Integer(1000)); + + // Selection panel + selectionPanel = new SelectionBox(); + selectionPanel.setVisible(false); + cardContent.add(selectionPanel, new Integer(1001)); + + // Sort popup + sortPopup = new JPopupMenu(); + sortPopup.setPreferredSize(new Dimension(300, 300)); + makeButtonPopup(sortButton, sortPopup); + + // Filter popup + filterPopup = new JPopupMenu(); + filterPopup.setPreferredSize(new Dimension(300, 300)); + makeButtonPopup(filterButton, filterPopup); + + + + + } + + /** + * Selection drag handling + */ + private void beginSelectionDrag(int x, int y) { + // Show the selection panel + selectionPanel.setVisible(true); + selectionPanel.setLocation(x, y); + cardScroll.revalidate(); + + // Store the drag start location + selectionDragStartX = x; + selectionDragStartY = y; + } + + private void updateSelectionDrag(int x, int y) { + // Coords + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + int cardTopHeight = CardRenderer.getCardTopHeight(cardWidth); + int x1 = Math.min(x, selectionDragStartX); + int x2 = Math.max(x, selectionDragStartX); + int y1 = Math.min(y, selectionDragStartY); + int y2 = Math.max(y, selectionDragStartY); + + // Update selection panel size + selectionPanel.setLocation(x1, y1); + selectionPanel.setSize(x2 - x1, y2 - y1); + + // First and last cols + int col1 = x1 / (cardWidth + GRID_PADDING); + int col2 = x2 / (cardWidth + GRID_PADDING); + int offsetIntoCol2 = x2 % (cardWidth + GRID_PADDING); + if (offsetIntoCol2 < GRID_PADDING) { + --col2; + } + + int curY = COUNT_LABEL_HEIGHT; + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + int stackStartIndex; + if (y1 < curY) { + stackStartIndex = 0; + } else { + stackStartIndex = (y1 - curY) / cardTopHeight; + } + int stackEndIndex; + if (y2 < curY) { + stackEndIndex = -1; + } else { + stackEndIndex = (y2 - curY) / cardTopHeight; + } + ArrayList> gridRow = cardGrid.get(rowIndex); + for (int col = 0; col < gridRow.size(); ++col) { + ArrayList stack = gridRow.get(col); + int stackBottomBegin = curY + cardTopHeight*(stack.size()); + int stackBottomEnd = curY + cardTopHeight*(stack.size()-1) + cardHeight; + for (int i = 0; i < stack.size(); ++i) { + CardView card = stack.get(i); + MageCard view = cardViews.get(card.getId()); + boolean inBoundsX = (col >= col1 && col <= col2); + boolean inBoundsY = (i >= stackStartIndex && i <= stackEndIndex); + boolean lastCard = (i == stack.size()-1); + if (inBoundsX && (inBoundsY || (lastCard && (y2 >= stackBottomBegin && y1 <= stackBottomEnd)))) { + if (!card.isSelected()) { + card.setSelected(true); + view.update(card); + } + } else { + if (card.isSelected()) { + card.setSelected(false); + view.update(card); + } + } + } + } + curY += cardTopHeight*(maxStackSize.get(rowIndex)-1) + cardHeight + COUNT_LABEL_HEIGHT; + } + } + + private void endSelectionDrag(int x, int y) { + // Hide the selection panel + selectionPanel.setVisible(false); + } + + + private void loadDeck() { + JFileChooser fcSelectDeck = new JFileChooser(); + String lastFolder = MageFrame.getPreferences().get("lastDeckFolder", ""); + if (!lastFolder.isEmpty()) { + fcSelectDeck.setCurrentDirectory(new File(lastFolder)); + } + int ret = fcSelectDeck.showOpenDialog(DragCardGrid.this); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fcSelectDeck.getSelectedFile(); + try { + setCursor(new Cursor(Cursor.WAIT_CURSOR)); + Deck deck = Deck.load(DeckImporterUtil.importDeck(file.getPath()), true, true); + Logger.getLogger(DragCardGrid.class).info("Loaded " + deck.getCards().size()); + setCards(new CardsView(deck.getCards())); + } catch (GameException ex) { + JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + try { + if (file != null) { + MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath()); + } + } catch (IOException ex) { + } + } + fcSelectDeck.setSelectedFile(null); + } + + // Update the contents of the card grid + public void setCards(CardsView cardsView) { + // Remove all of the cards not in the cardsView + boolean didModify = false; // Until contested + for (int i = 0; i < cardGrid.size(); ++i) { + ArrayList> gridRow = cardGrid.get(i); + for (int j = 0; j < gridRow.size(); ++j) { + ArrayList stack = gridRow.get(j); + for (int k = 0; k < stack.size(); ++k) { + CardView card = stack.get(k); + if (!cardsView.containsKey(card.getId())) { + // Remove it + removeCardView(card); + stack.remove(k--); + + // Mark + didModify = true; + } + } + } + } + + // Add any new card views + for (CardView newCard: cardsView.values()) { + if (!cardViews.containsKey(newCard.getId())) { + // Is a new card + addCardView(newCard); + + try { + // Put it into the appropirate place in the grid given the current sort + sortIntoGrid(newCard); + } catch (Exception e) { + e.printStackTrace(); + } + // Mark + didModify = true; + } + } + + // Modifications? + if (didModify) { + // Trim extra rows / columns from the grid + trimGrid(); + + // Update layout + layoutGrid(); + + // Update draw + cardScroll.revalidate(); + repaint(); + } + } + + private void addCardView(final CardView card) { + allCards.add(card); + + // Create the card view + final MageCard cardPanel = Plugins.getInstance().getMageCard(card, null, new Dimension(100, 140), null, true); + cardPanel.update(card); + + cardPanel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + cardClicked(card, e); + } + }); + cardPanel.addMouseMotionListener(new MouseAdapter() { + @Override + public void mouseDragged(MouseEvent e) { + if (!dragger.isDragging()) { + // If the card isn't already selected, make sure it is + if (!card.isSelected()) { + cardClicked(card, e); + } + dragger.beginDrag(cardPanel, e); + } + } + }); + + // And add it + cardContent.add(cardPanel); + cardViews.put(card.getId(), cardPanel); + } + + private void cardClicked(CardView targetCard, MouseEvent e) { + // Set the selected card to the target card + for (CardView card : allCards) { + if (card == targetCard) { + if (!card.isSelected()) { + card.setSelected(true); + cardViews.get(card.getId()).update(card); + } + } else { + if (card.isSelected()) { + card.setSelected(false); + cardViews.get(card.getId()).update(card); + } + } + } + } + + private void removeCardView(CardView card) { + allCards.remove(card); + cardContent.remove(cardViews.get(card.getId())); + cardViews.remove(card.getId()); + } + + /** + * Add a card to the cardGrid, in the position that the current sort dictates + * @param newCard + */ + private void sortIntoGrid(CardView newCard) { + // Ensure row 1 exists + if (cardGrid.size() == 0) { + cardGrid.add(0, new ArrayList>()); + maxStackSize.add(0, 0); + } + // What row to add it to? + ArrayList> targetRow; + if (separateCreatures && !newCard.getCardTypes().contains(CardType.CREATURE)) { + // Ensure row 2 exists + if (cardGrid.size() < 2) { + cardGrid.add(1, new ArrayList>()); + maxStackSize.add(1, 0); + // Populate with stacks matching the first row + for (int i = 0; i < cardGrid.get(0).size(); ++i) { + cardGrid.get(1).add(new ArrayList()); + } + } + targetRow = cardGrid.get(1); + } else { + targetRow = cardGrid.get(0); + } + + // Find the right column to insert into + boolean didInsert = false; + for (int currentColumn = 0; currentColumn < cardGrid.get(0).size(); ++currentColumn) { + // Find an item from this column + CardView cardInColumn = null; + for (ArrayList> gridRow : cardGrid) { + for (CardView card : gridRow.get(currentColumn)) { + cardInColumn = card; + break; + } + } + + // No card in this column? + if (cardInColumn == null) { + // Error, should not have an empty column + LOGGER.error("Empty column!"); + } else { + int res = cardSort.getComparator().compare(newCard, cardInColumn); + if (res <= 0) { + // Insert into this col, but if less, then we need to create a new col here first + if (res < 0) { + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + cardGrid.get(rowIndex).add(currentColumn, new ArrayList()); + } + } + targetRow.get(currentColumn).add(newCard); + didInsert = true; + break; + } else { + // Nothing to do, go to next iteration + } + } + } + + // If nothing else, insert in a new column after everything else + if (!didInsert) { + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + cardGrid.get(rowIndex).add(new ArrayList()); + } + targetRow.get(targetRow.size()-1).add(newCard); + } + } + + /** + * Delete any empty columns / rows from the grid, and eleminate any empty space in stacks + */ + private void trimGrid() { + // Compact stacks and rows + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + ArrayList> gridRow = cardGrid.get(rowIndex); + int rowMaxStackSize = 0; + for (ArrayList stack : gridRow) { + // Clear out nulls in the stack + for (int i = 0; i < stack.size(); ++i) { + if (stack.get(i) == null) { + stack.remove(i--); + } + } + // Is the stack still non-empty? + rowMaxStackSize = Math.max(rowMaxStackSize, stack.size()); + } + // Is the row empty? If so remove it + if (rowMaxStackSize == 0) { + cardGrid.remove(rowIndex); + maxStackSize.remove(rowIndex); + --rowIndex; + } else { + maxStackSize.set(rowIndex, rowMaxStackSize); + } + } + + // Remove empty columns + if (!cardGrid.isEmpty()) { + for (int colIndex = 0; colIndex < cardGrid.get(0).size(); ++colIndex) { + boolean hasContent = false; // Until contested + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + if (!cardGrid.get(rowIndex).get(colIndex).isEmpty()) { + hasContent = true; + break; + } + } + if (!hasContent) { + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + cardGrid.get(rowIndex).remove(colIndex); + } + --colIndex; + } + } + } + + // Clean up extra column header count labels + while (stackCountLabels.size() > cardGrid.size()) { + ArrayList labels = stackCountLabels.remove(cardGrid.size()); + for (JLabel label : labels) { + cardContent.remove(label); + } + } + int colCount = cardGrid.isEmpty() ? 0 : cardGrid.get(0).size(); + for (ArrayList labels : stackCountLabels) { + while (labels.size() > colCount) { + cardContent.remove(labels.remove(colCount)); + } + } + } + + private int getCardWidth() { + return CARD_WIDTH; + } + + private int getCardHeight() { + return (int)(1.4*getCardWidth()); + } + + /** + * Position all of the card views correctly + */ + private void layoutGrid() { + // Basic dimensions + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + int cardTopHeight = CardRenderer.getCardTopHeight(cardWidth); + + // Layout one at a time + int layerIndex = 0; + int currentY = COUNT_LABEL_HEIGHT; + int maxWidth = 0; + for (int rowIndex = 0; rowIndex < cardGrid.size(); ++rowIndex) { + int rowMaxStackSize = 0; + ArrayList> gridRow = cardGrid.get(rowIndex); + for (int colIndex = 0; colIndex < gridRow.size(); ++colIndex) { + ArrayList stack = gridRow.get(colIndex); + + // Stack count label + if (stackCountLabels.size() <= rowIndex) { + stackCountLabels.add(new ArrayList()); + } + if (stackCountLabels.get(rowIndex).size() <= colIndex) { + JLabel countLabel = new JLabel("", SwingConstants.CENTER); + cardContent.add(countLabel, new Integer(0)); + stackCountLabels.get(rowIndex).add(countLabel); + } + JLabel countLabel = stackCountLabels.get(rowIndex).get(colIndex); + if (stack.isEmpty()) { + countLabel.setVisible(false); + } else { + countLabel.setText("" + stack.size()); + countLabel.setLocation(GRID_PADDING + (cardWidth + GRID_PADDING) * colIndex, currentY - COUNT_LABEL_HEIGHT); + countLabel.setSize(cardWidth, COUNT_LABEL_HEIGHT); + countLabel.setVisible(true); + } + + // Max stack size + rowMaxStackSize = Math.max(rowMaxStackSize, stack.size()); + + // Layout cards in stack + for (int i = 0; i < stack.size(); ++i) { + CardView card = stack.get(i); + MageCard view = cardViews.get(card.getId()); + int x = GRID_PADDING + (cardWidth + GRID_PADDING) * colIndex; + int y = currentY + i * cardTopHeight; + view.setCardBounds(x, y, cardWidth, cardHeight); + cardContent.setLayer(view, layerIndex++); + } + } + + // Update the max stack size for this row and the max width + maxWidth = Math.max(maxWidth, GRID_PADDING + (GRID_PADDING + cardWidth) * gridRow.size()); + maxStackSize.set(rowIndex, rowMaxStackSize); + currentY += (cardTopHeight * (rowMaxStackSize - 1) + cardHeight) + COUNT_LABEL_HEIGHT; + } + + // Resize card container + cardContent.setPreferredSize(new Dimension(maxWidth, currentY - COUNT_LABEL_HEIGHT + GRID_PADDING)); + //cardContent.setSize(maxWidth, currentY - COUNT_LABEL_HEIGHT + GRID_PADDING); + } + + private static void makeButtonPopup(final AbstractButton button, final JPopupMenu popup) { + button.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + popup.show(button, 0, button.getHeight()); + } + }); + popup.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + button.setSelected(false); + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} + @Override + public void popupMenuCanceled(PopupMenuEvent e) {} + }); + } + + public static void main(String[] args) { + GUISizeHelper.calculateGUISizes(); + Plugins.getInstance().loadPlugins(); + JFrame frame = new JFrame(); + frame.setTitle("Test"); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setBackground(Color.BLUE); + DragCardGrid grid = new DragCardGrid(); + grid.setPreferredSize(new Dimension(800, 600)); + frame.add(grid, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } +} + +class SelectionBox extends JComponent { + public SelectionBox() { + setOpaque(false); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + g = g.create(); + g.setColor(new Color(100, 100, 200, 128)); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(new Color(0, 0, 255)); + g.drawRect(0, 0, getWidth()-1, getHeight()-1); + g.dispose(); + } +} \ No newline at end of file diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardSource.java b/Mage.Client/src/main/java/mage/client/cards/DragCardSource.java new file mode 100644 index 00000000000..eb71b9a89de --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardSource.java @@ -0,0 +1,14 @@ +package mage.client.cards; + +import mage.view.CardView; + +import java.util.Collection; + +/** + * Created by StravantUser on 2016-09-22. + */ +public interface DragCardSource { + Collection dragCardList(); + void dragCardBegin(); + void dragCardEnd(DragCardTarget target); +} diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardTarget.java b/Mage.Client/src/main/java/mage/client/cards/DragCardTarget.java new file mode 100644 index 00000000000..70138889c4c --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardTarget.java @@ -0,0 +1,17 @@ +package mage.client.cards; + +import mage.view.CardView; + +import java.awt.*; +import java.awt.event.MouseEvent; +import java.util.Collection; + +/** + * Created by StravantUser on 2016-09-22. + */ +public interface DragCardTarget { + void dragCardEnter(MouseEvent e); + void dragCardMove(MouseEvent e); + void dragCardExit(MouseEvent e); + void dragCardDrop(MouseEvent e, DragCardSource source, Collection cards); +} diff --git a/Mage.Client/src/main/resources/editor_insert_col.png b/Mage.Client/src/main/resources/editor_insert_col.png new file mode 100644 index 0000000000000000000000000000000000000000..5c087eebd5a2ce434044d05d852ff7616d89ec7d GIT binary patch literal 2093 zcmV+|2-5e7P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^Ag1Z(U700*5(L_t(|UgeuxY*j@Rh8G0_K~%&d5H6Bv z5YPvn6aro%Cdvb9A}SC1*XsWgn$4Boh4E6|PgsxWL40o@kTpQqgM5v?- zpWSUu98Xo7yLVz?v|Sh?bd>^EIC~9fDc1(L77;4x!r}quHa`;T^-Il79#B6dk>M3DooGtfPnY(V7m7?7`p)+TTaD$`g40kl31x;v6 zI65}mu;UJ`o$4_f9*RTfD>?jrdP^el+QWr|dSS9~p$jpI?YSggaD*$I z;f@Bhpefm)m39K!ZIs|0RlgJrPG|8STEz6x`5()_izzFg)SocjT<^$5s;llYY#PBIDu~U`@C%C~8u5gAs8qk6b+R#W_0nJ5W4P7s| znbU$XVAvdq!zfLPn-pMGrPkTEZExy?iDRvawnD8?DV(o@Z({hENjzNO1h+Kl!5Qx5 zLmzFl70~*hT!vxgCzQ059Dmo`wyRqlHpt;N-CN)29$PWY8V*<4e(Xp$$BYPV1v0Vo zkuu}cXL-a*DJ~q~0w=h^F@0cgM+0_cn;`H!?d|%q;6@L%((w;M!@Zh0>DA`g2?rHm zivoQ~CycfI4NI*aJ2J14gX|>jh2=s=W{dd3r;m}cJYvHEE^vYy9N`LQxMPPFG|^r_ z<7rDTJwN}Vqnk4$GzMFySZS{u;v8^a)heLwxzdUWR(JA4JBb|`*uYDRPFRG)4l4Na zzEhS*Ok%?UE@{33aD{W?j~3cTZEb!qY$7!E?4c!PL2z(P!>DFt$fgL;s2<*}AV2Az z`&0y0Pqm#|f19ygKhIp>-o@?ky7$<=f)DQ#-^3smF^LTaxWEZ+aD*$Iu|)$~&?G-+ zwz<>O>`fiqP1m$MOYhQfVtF|l196X$Vt&V@C?Xpkv_|Z}C$E~T=uynJ?b%@U8=3gR zXYx-hViFq;X^w&$9N~%`+|huKsOgML|K4VGI=Z=WZvfQXZf>iFTS}71vUtc~0$O>6 zM#NJswpGuCz!B$?Ez-uf$5--83}O+J*eTP46WrjKY~fD(sO9V?X7$)q9o!|owZ<+A z4v%VBeXD%BPQ9Lz46-d!&h;WxEo^8wrTRk2fpx`9&d?7Ok%?UE^xvgj&Q|~0QU|lYqX3sFOH9#V5^232?!HWT7sC6 z$i~=uVxn4kqt@%Vk3i-&dYB!Nuaq|byKt@vo0R3z79aS+C%)69M@(YF0WOIb9N{Wo zYrNMEDr+h_paaH@Y`X)nX>SL>RlYi`1G2sa@}30a5|ZaKsD@c5LV2gc>anaJhO&Mf z&VECL?V@bA#8`v<(9LmElpfA{TRiJ8Mza5EEc-7<{XgkRFUPOPeT55Pqw;AUGt;EU zLq--aNTdr49kMA>OeU1*}p8E z{p<1|>mN*H{gauje>6n~RVKbY8=0N8_zhMxmTiuJP|5y>lM(s;bXLgv$J3eqeBRtY XuI8ULQKXrL00000NkvXXu0mjf4nWnt literal 0 HcmV?d00001 diff --git a/Mage.Client/src/main/resources/editor_insert_row.png b/Mage.Client/src/main/resources/editor_insert_row.png new file mode 100644 index 0000000000000000000000000000000000000000..9aea52eae112608935373b700a2d0040e8e3cbf9 GIT binary patch literal 1900 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.java:83) + at mage.cards.repository.CardRepository.(CardRepository.java:59) + at mage.cards.decks.importer.DckDeckImporter.readLine(DckDeckImporter.java:63) + at mage.cards.decks.importer.DeckImporter.importDeck(DeckImporter.java:61) + at mage.cards.decks.importer.DeckImporterUtil.importDeck(DeckImporterUtil.java:57) + at mage.client.cards.DragCardGrid$1.actionPerformed(DragCardGrid.java:78) + at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) + at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) + at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) + at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) + at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) + at java.awt.Component.processMouseEvent(Component.java:6533) + at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) + at java.awt.Component.processEvent(Component.java:6298) + at java.awt.Container.processEvent(Container.java:2236) + at java.awt.Component.dispatchEventImpl(Component.java:4889) + at java.awt.Container.dispatchEventImpl(Container.java:2294) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888) + at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525) + at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466) + at java.awt.Container.dispatchEventImpl(Container.java:2280) + at java.awt.Window.dispatchEventImpl(Window.java:2746) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) + at java.awt.EventQueue.access$500(EventQueue.java:97) + at java.awt.EventQueue$3.run(EventQueue.java:709) + at java.awt.EventQueue$3.run(EventQueue.java:703) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) + at java.awt.EventQueue$4.run(EventQueue.java:731) + at java.awt.EventQueue$4.run(EventQueue.java:729) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) + at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) + at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) + at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) + at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) +09-21 19:22:40 jdbc[3]: exception +org.h2.jdbc.JdbcSQLException: Index "NAME_INDEX" not found; SQL statement: +DROP INDEX `name_index` [42112-187] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) + at org.h2.message.DbException.get(DbException.java:179) + at org.h2.message.DbException.get(DbException.java:155) + at org.h2.command.ddl.DropIndex.update(DropIndex.java:49) + at org.h2.command.CommandContainer.update(CommandContainer.java:78) + at org.h2.command.Command.executeUpdate(Command.java:254) + at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:198) + at com.j256.ormlite.jdbc.JdbcCompiledStatement.runExecute(JdbcCompiledStatement.java:62) + at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:462) + at com.j256.ormlite.table.TableUtils.doDropTable(TableUtils.java:273) + at com.j256.ormlite.table.TableUtils.dropTable(TableUtils.java:151) + at mage.cards.repository.CardRepository.(CardRepository.java:83) + at mage.cards.repository.CardRepository.(CardRepository.java:59) + at mage.cards.decks.importer.DckDeckImporter.readLine(DckDeckImporter.java:63) + at mage.cards.decks.importer.DeckImporter.importDeck(DeckImporter.java:61) + at mage.cards.decks.importer.DeckImporterUtil.importDeck(DeckImporterUtil.java:57) + at mage.client.cards.DragCardGrid$1.actionPerformed(DragCardGrid.java:78) + at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) + at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) + at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) + at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) + at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) + at java.awt.Component.processMouseEvent(Component.java:6533) + at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) + at java.awt.Component.processEvent(Component.java:6298) + at java.awt.Container.processEvent(Container.java:2236) + at java.awt.Component.dispatchEventImpl(Component.java:4889) + at java.awt.Container.dispatchEventImpl(Container.java:2294) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888) + at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525) + at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466) + at java.awt.Container.dispatchEventImpl(Container.java:2280) + at java.awt.Window.dispatchEventImpl(Window.java:2746) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) + at java.awt.EventQueue.access$500(EventQueue.java:97) + at java.awt.EventQueue$3.run(EventQueue.java:709) + at java.awt.EventQueue$3.run(EventQueue.java:703) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) + at java.awt.EventQueue$4.run(EventQueue.java:731) + at java.awt.EventQueue$4.run(EventQueue.java:729) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) + at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) + at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) + at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) + at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) +09-21 19:22:40 jdbc[3]: exception +org.h2.jdbc.JdbcSQLException: Index "SETCODE_CARDNUMBER_INDEX" not found; SQL statement: +DROP INDEX `setCode_cardNumber_index` [42112-187] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) + at org.h2.message.DbException.get(DbException.java:179) + at org.h2.message.DbException.get(DbException.java:155) + at org.h2.command.ddl.DropIndex.update(DropIndex.java:49) + at org.h2.command.CommandContainer.update(CommandContainer.java:78) + at org.h2.command.Command.executeUpdate(Command.java:254) + at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:198) + at com.j256.ormlite.jdbc.JdbcCompiledStatement.runExecute(JdbcCompiledStatement.java:62) + at com.j256.ormlite.table.TableUtils.doStatements(TableUtils.java:462) + at com.j256.ormlite.table.TableUtils.doDropTable(TableUtils.java:273) + at com.j256.ormlite.table.TableUtils.dropTable(TableUtils.java:151) + at mage.cards.repository.CardRepository.(CardRepository.java:83) + at mage.cards.repository.CardRepository.(CardRepository.java:59) + at mage.cards.decks.importer.DckDeckImporter.readLine(DckDeckImporter.java:63) + at mage.cards.decks.importer.DeckImporter.importDeck(DeckImporter.java:61) + at mage.cards.decks.importer.DeckImporterUtil.importDeck(DeckImporterUtil.java:57) + at mage.client.cards.DragCardGrid$1.actionPerformed(DragCardGrid.java:78) + at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) + at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) + at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) + at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) + at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) + at java.awt.Component.processMouseEvent(Component.java:6533) + at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) + at java.awt.Component.processEvent(Component.java:6298) + at java.awt.Container.processEvent(Container.java:2236) + at java.awt.Component.dispatchEventImpl(Component.java:4889) + at java.awt.Container.dispatchEventImpl(Container.java:2294) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888) + at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525) + at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466) + at java.awt.Container.dispatchEventImpl(Container.java:2280) + at java.awt.Window.dispatchEventImpl(Window.java:2746) + at java.awt.Component.dispatchEvent(Component.java:4711) + at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) + at java.awt.EventQueue.access$500(EventQueue.java:97) + at java.awt.EventQueue$3.run(EventQueue.java:709) + at java.awt.EventQueue$3.run(EventQueue.java:703) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) + at java.awt.EventQueue$4.run(EventQueue.java:731) + at java.awt.EventQueue$4.run(EventQueue.java:729) + at java.security.AccessController.doPrivileged(Native Method) + at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) + at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) + at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) + at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) + at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) + at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) + at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) +09-21 19:22:40 jdbc[3]: exception +org.h2.jdbc.JdbcSQLException: Table "CARD" not found; SQL statement: +DROP TABLE `card` [42102-187] diff --git a/mageclient.log b/mageclient.log new file mode 100644 index 00000000000..8d3f69adad3 --- /dev/null +++ b/mageclient.log @@ -0,0 +1,80 @@ +FATAL 2016-09-21 19:22:40,587 Could not find card '' at line 2: 3 [KTK:248] Windswept Heath +Could not find card '' at line 3: 4 [KTK:249] Wooded Foothills +Could not find card '' at line 4: 6 [BFZ:269a] Mountain +Could not find card '' at line 5: 2 [ORI:157] Pia and Kiran Nalaar +Could not find card '' at line 6: 4 [M13:170] Farseek +Could not find card '' at line 7: 2 [ZEN:172] Oracle of Mul Daya +Could not find card '' at line 8: 3 [FUT:139] Summoner's Pact +Could not find card '' at line 9: 2 [BFZ:272a] Forest +Could not find card '' at line 10: 4 [GPT:165] Stomping Ground +Could not find card '' at line 11: 4 [M11:192] Primeval Titan +Could not find card '' at line 12: 4 [ZEN:228] Valakut, the Molten Pinnacle +Could not find card '' at line 13: 4 [TSP:216] Search for Tomorrow +Could not find card '' at line 14: 4 [LEB:163] Lightning Bolt +Could not find card '' at line 15: 2 [BFZ:235] Cinder Glade +Could not find card '' at line 16: 4 [OGW:140] Oath of Nissa +Could not find card '' at line 17: 4 [CHK:239] Sakura-Tribe Elder +Could not find card '' at line 18: 4 [CHK:193] Through the Breach +Could not find card '' at line 19: SB: 1 [M15:194] Reclamation Sage +Could not find card '' at line 20: SB: 3 [M11:188] Obstinate Baloth +Could not find card '' at line 21: SB: 1 [M11:174] Gaea's Revenge +Could not find card '' at line 22: SB: 1 [TSP:143] Ancient Grudge +Could not find card '' at line 23: SB: 3 [THS:112] Anger of the Gods +Could not find card '' at line 24: SB: 1 [MM2:230] Spellskite +Could not find card '' at line 25: SB: 2 [MRD:150] Chalice of the Void +Could not find card '' at line 26: SB: 3 [EMA:231] Relic of Progenitus + =>[AWT-EventQueue-0] DeckImporter.importDeck +FATAL 2016-09-21 19:25:13,820 Could not find card '' at line 2: 3 [KTK:248] Windswept Heath +Could not find card '' at line 3: 4 [KTK:249] Wooded Foothills +Could not find card '' at line 4: 6 [BFZ:269a] Mountain +Could not find card '' at line 5: 2 [ORI:157] Pia and Kiran Nalaar +Could not find card '' at line 6: 4 [M13:170] Farseek +Could not find card '' at line 7: 2 [ZEN:172] Oracle of Mul Daya +Could not find card '' at line 8: 3 [FUT:139] Summoner's Pact +Could not find card '' at line 9: 2 [BFZ:272a] Forest +Could not find card '' at line 10: 4 [GPT:165] Stomping Ground +Could not find card '' at line 11: 4 [M11:192] Primeval Titan +Could not find card '' at line 12: 4 [ZEN:228] Valakut, the Molten Pinnacle +Could not find card '' at line 13: 4 [TSP:216] Search for Tomorrow +Could not find card '' at line 14: 4 [LEB:163] Lightning Bolt +Could not find card '' at line 15: 2 [BFZ:235] Cinder Glade +Could not find card '' at line 16: 4 [OGW:140] Oath of Nissa +Could not find card '' at line 17: 4 [CHK:239] Sakura-Tribe Elder +Could not find card '' at line 18: 4 [CHK:193] Through the Breach +Could not find card '' at line 19: SB: 1 [M15:194] Reclamation Sage +Could not find card '' at line 20: SB: 3 [M11:188] Obstinate Baloth +Could not find card '' at line 21: SB: 1 [M11:174] Gaea's Revenge +Could not find card '' at line 22: SB: 1 [TSP:143] Ancient Grudge +Could not find card '' at line 23: SB: 3 [THS:112] Anger of the Gods +Could not find card '' at line 24: SB: 1 [MM2:230] Spellskite +Could not find card '' at line 25: SB: 2 [MRD:150] Chalice of the Void +Could not find card '' at line 26: SB: 3 [EMA:231] Relic of Progenitus + =>[AWT-EventQueue-0] DeckImporter.importDeck +INFO 2016-09-21 19:25:13,827 Loaded 0 =>[AWT-EventQueue-0] DragCardGrid$1.actionPerformed +FATAL 2016-09-21 19:38:03,322 Could not find card '' at line 2: 3 [KTK:248] Windswept Heath +Could not find card '' at line 3: 4 [KTK:249] Wooded Foothills +Could not find card '' at line 4: 6 [BFZ:269a] Mountain +Could not find card '' at line 5: 2 [ORI:157] Pia and Kiran Nalaar +Could not find card '' at line 6: 4 [M13:170] Farseek +Could not find card '' at line 7: 2 [ZEN:172] Oracle of Mul Daya +Could not find card '' at line 8: 3 [FUT:139] Summoner's Pact +Could not find card '' at line 9: 2 [BFZ:272a] Forest +Could not find card '' at line 10: 4 [GPT:165] Stomping Ground +Could not find card '' at line 11: 4 [M11:192] Primeval Titan +Could not find card '' at line 12: 4 [ZEN:228] Valakut, the Molten Pinnacle +Could not find card '' at line 13: 4 [TSP:216] Search for Tomorrow +Could not find card '' at line 14: 4 [LEB:163] Lightning Bolt +Could not find card '' at line 15: 2 [BFZ:235] Cinder Glade +Could not find card '' at line 16: 4 [OGW:140] Oath of Nissa +Could not find card '' at line 17: 4 [CHK:239] Sakura-Tribe Elder +Could not find card '' at line 18: 4 [CHK:193] Through the Breach +Could not find card '' at line 19: SB: 1 [M15:194] Reclamation Sage +Could not find card '' at line 20: SB: 3 [M11:188] Obstinate Baloth +Could not find card '' at line 21: SB: 1 [M11:174] Gaea's Revenge +Could not find card '' at line 22: SB: 1 [TSP:143] Ancient Grudge +Could not find card '' at line 23: SB: 3 [THS:112] Anger of the Gods +Could not find card '' at line 24: SB: 1 [MM2:230] Spellskite +Could not find card '' at line 25: SB: 2 [MRD:150] Chalice of the Void +Could not find card '' at line 26: SB: 3 [EMA:231] Relic of Progenitus + =>[AWT-EventQueue-0] DeckImporter.importDeck +INFO 2016-09-21 19:38:03,330 Loaded 0 =>[AWT-EventQueue-0] DragCardGrid$1.actionPerformed