From 09fc3ae60c28b57d35c970ad112dc03f290a639a Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Wed, 9 Jan 2019 21:13:09 -0500 Subject: [PATCH] add new GUI interface allowing cards to be moved around in a list and use for arrangeForScry if preference UI_SELECT_FROM_CARD_DISPLAYS is set --- .../src/main/java/forge/util/Localizer.java | 2 +- .../src/main/java/forge/gui/GuiChoose.java | 28 +- .../java/forge/screens/match/CMatchUI.java | 6 + .../main/java/forge/view/arcane/CardArea.java | 4 +- .../forge/view/arcane/CardPanelContainer.java | 35 +- .../java/forge/view/arcane/ListCardArea.java | 317 ++++++++++++++++++ .../forge/screens/match/MatchController.java | 6 + .../main/java/forge/interfaces/IGuiGame.java | 5 + .../main/java/forge/net/ProtocolMethod.java | 1 + .../java/forge/net/server/NetGuiGame.java | 6 + .../forge/player/PlayerControllerHuman.java | 72 ++-- .../forge/properties/ForgePreferences.java | 2 +- 12 files changed, 443 insertions(+), 41 deletions(-) create mode 100644 forge-gui-desktop/src/main/java/forge/view/arcane/ListCardArea.java diff --git a/forge-core/src/main/java/forge/util/Localizer.java b/forge-core/src/main/java/forge/util/Localizer.java index 6463a9716c1..cc31a7f1af3 100644 --- a/forge-core/src/main/java/forge/util/Localizer.java +++ b/forge-core/src/main/java/forge/util/Localizer.java @@ -86,7 +86,7 @@ public class Localizer { resourceBundle = ResourceBundle.getBundle(languageRegionID, new Locale(splitLocale[0], splitLocale[1]), loader); } catch (NullPointerException | MissingResourceException e) { //If the language can't be loaded, default to US English - resourceBundle = ResourceBundle.getBundle("en-GB", new Locale("en", "GB"), loader); + resourceBundle = ResourceBundle.getBundle("en-US", new Locale("en", "US"), loader); e.printStackTrace(); } diff --git a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java index ea177273bda..61a919fd59e 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java +++ b/forge-gui-desktop/src/main/java/forge/gui/GuiChoose.java @@ -29,7 +29,7 @@ import forge.item.PaperCard; import forge.model.FModel; import forge.screens.match.CMatchUI; import forge.toolbox.FOptionPane; - +import forge.view.arcane.ListCardArea; public class GuiChoose { @@ -285,5 +285,31 @@ public class GuiChoose { return null; } + public static List manipulateCardList(final CMatchUI gui, final String title, final List cards, final List manipulable, + final boolean toTop, final boolean toBottom, final boolean toAnywhere) { + final Callable> callable = new Callable>() { + @Override + public List call() throws Exception { + ListCardArea tempArea = new ListCardArea(gui,title,cards,manipulable,toTop,toBottom,toAnywhere); + // tempArea.pack(); + // window? tempArea.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + tempArea.show(); + // tempArea.dispose(); + //try { Thread.sleep(1000); } catch(InterruptedException ex) { } + final List cardList = tempArea.getCardList(); + return cardList; + } + }; + final FutureTask> ft = new FutureTask>(callable); + FThreads.invokeInEdtAndWait(ft); + try { + List result = ft.get(); + return result; + } catch (final Exception e) { // we have waited enough + e.printStackTrace(); + } + return null; + } + } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 5da67c046f3..a338000744f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -51,6 +51,7 @@ import forge.deck.Deck; import forge.deckchooser.FDeckViewer; import forge.game.GameEntityView; import forge.game.GameView; +import forge.game.card.Card; import forge.game.card.CardView; import forge.game.combat.CombatView; import forge.game.phase.PhaseType; @@ -1003,6 +1004,11 @@ public final class CMatchUI return (List) order(title,"Selected", min, max, optionList, null, null, false); } + @Override + public List manipulateCardList(final String title, final List cards, final List manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) { + return GuiChoose.manipulateCardList(this, title, cards, manipulable, toTop, toBottom, toAnywhere); + } + @Override public void setPlayerAvatar(final LobbyPlayer player, final IHasIcon ihi) { avatarImages.put(player.getName(), ihi.getIconImageKey()); diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardArea.java index 46132c094e5..7c148bc3062 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardArea.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardArea.java @@ -246,8 +246,8 @@ public class CardArea extends CardPanelContainer implements CardPanelMouseListen dragPanel.setDisplayEnabled(false); CardPanel.setDragAnimationPanel(new CardPanel(dragPanel.getMatchUI(), dragPanel.getCard())); - final JFrame frame = (JFrame) SwingUtilities.windowForComponent(this); - final JLayeredPane layeredPane = frame.getLayeredPane(); + final RootPaneContainer frame = (RootPaneContainer) SwingUtilities.windowForComponent(this); + final JLayeredPane layeredPane = frame.getLayeredPane(); layeredPane.add(CardPanel.getDragAnimationPanel()); layeredPane.moveToFront(CardPanel.getDragAnimationPanel()); final Point p = SwingUtilities.convertPoint(this, this.mouseDragStartX, this.mouseDragStartY, layeredPane); diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java index de07aafc508..45c9c1780fd 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanelContainer.java @@ -182,6 +182,10 @@ public abstract class CardPanelContainer extends SkinnedPanel { }); } + protected boolean cardPanelDraggable(final CardPanel panel) { + return true; + } + private MouseMotionListener setupMotionMouseListener() { final MouseMotionListener mml = new MouseMotionListener() { @Override @@ -207,20 +211,23 @@ public abstract class CardPanelContainer extends SkinnedPanel { if (panel != mouseDownPanel) { return; } - if (intialMouseDragX == -1) { - intialMouseDragX = x; - intialMouseDragY = y; - return; - } - if ((Math.abs(x - intialMouseDragX) < CardPanelContainer.DRAG_SMUDGE) + + if (cardPanelDraggable(panel)) { // allow for non-draggable cards + if (intialMouseDragX == -1) { + intialMouseDragX = x; + intialMouseDragY = y; + return; + } + if ((Math.abs(x - intialMouseDragX) < CardPanelContainer.DRAG_SMUDGE) && (Math.abs(y - intialMouseDragY) < CardPanelContainer.DRAG_SMUDGE)) { - return; - } - mouseDownPanel = null; - setMouseDragPanel(panel); - mouseDragOffsetX = panel.getX() - intialMouseDragX; - mouseDragOffsetY = panel.getY() - intialMouseDragY; - mouseDragStart(getMouseDragPanel(), evt); + return; + } + mouseDownPanel = null; + setMouseDragPanel(panel); + mouseDragOffsetX = panel.getX() - intialMouseDragX; + mouseDragOffsetY = panel.getY() - intialMouseDragY; + mouseDragStart(getMouseDragPanel(), evt); + } } @Override @@ -453,4 +460,4 @@ public abstract class CardPanelContainer extends SkinnedPanel { this.layoutListeners.add(listener); } -} \ No newline at end of file +} diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/ListCardArea.java b/forge-gui-desktop/src/main/java/forge/view/arcane/ListCardArea.java new file mode 100644 index 00000000000..2ab3358a9f0 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/ListCardArea.java @@ -0,0 +1,317 @@ +/* + * Forge: Play Magic: the Gathering. + * + * 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.view.arcane; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ScrollPaneConstants; +import javax.swing.Timer; + +import forge.Singletons; +import forge.game.card.Card; +import forge.game.card.CardView; +import forge.gui.framework.SDisplayUtil; +import forge.model.FModel; +import forge.properties.ForgePreferences; +import forge.properties.ForgePreferences.FPref; +import forge.screens.match.CMatchUI; +import forge.view.arcane.util.CardPanelMouseAdapter; +import forge.toolbox.FScrollPane; +import forge.toolbox.MouseTriggerEvent; +import forge.view.FFrame; +import forge.view.FDialog; + +import forge.toolbox.FButton; + +public class ListCardArea extends CardArea { + + private static final String COORD_DELIM = ","; + private static final ForgePreferences prefs = FModel.getPreferences(); + + public void show() { + this.showWindow(); + } + public void hide() { + this.hideWindow(); + } + + private ArrayList cardList; + private ArrayList moveableCards; + private boolean toTop, toBottom, toAnywhere; + private String title; + private FPref locPref; + private boolean hasBeenShown = false, locLoaded; + private static ListCardArea storedArea; + + private final FButton doneButton; + + public ListCardArea(final CMatchUI matchUI, final String title0, final List cardList0, final List moveableCards0, final boolean toTop0, final boolean toBottom0, final boolean toAnywhere0) { + super(matchUI, new FScrollPane(false, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)); + window.add(getScrollPane(),"grow, push"); + try { Thread.sleep(1000); } catch(InterruptedException ex) { } + getScrollPane().setViewportView(this); + setOpaque(false); + doneButton = new FButton("Done"); + doneButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { window.setVisible(false); } + }); + window.add(doneButton,BorderLayout.SOUTH); + cardList = new ArrayList(cardList0); // this is modified - pfps - is there a better way? + moveableCards = new ArrayList(moveableCards0); + title = title0; + toTop = toTop0; + toBottom = toBottom0; + toAnywhere = toAnywhere0; + this.setDragEnabled(true); + this.setVertical(true); + storedArea = this; + } + + public List getCardList() { + return cardList; + } + + @SuppressWarnings("serial") + // private SkinnedFrame window = new SkinnedFrame() { + private final FDialog window = new FDialog(true, true, "0") { + @Override + public void setLocationRelativeTo(Component c) { + super.setLocationRelativeTo(c); + } + + @Override + public void setVisible(boolean b0) { + if (isVisible() == b0) { return; } + if (b0) { + refresh(); + } + super.setVisible(b0); + } + }; + + private void showWindow() { + onShow(); + window.setFocusableWindowState(true); + window.setVisible(true); + } + private void hideWindow() { + onShow(); + window.setFocusableWindowState(false); // should probably do this earlier + window.setVisible(false); + } + private void onShow() { + if (!hasBeenShown) { + loadLocation(); + this.addCardPanelMouseListener(new CardPanelMouseAdapter() { + @Override + public void mouseDragEnd(final CardPanel dragPanel, final MouseEvent evt) { + dragEnd(dragPanel); + } + }); + this.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(final KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.VK_ENTER: + doneButton.doClick(); + break; + default: + break; + } + } + }); + } + + } + + // is this a valid place to move the card? + private boolean validIndex(final Card card, final int index) { + if (toAnywhere) { return true; } + int oldIndex = cardList.indexOf(card); + boolean topMove = true; + for(int i=0; iindex?1:0); i 0) { + String[] coords = value.split(COORD_DELIM); + if (coords.length == 4) { + try { + int x = Integer.parseInt(coords[0]); + int y = Integer.parseInt(coords[1]); + int w = Integer.parseInt(coords[2]); + int h = Integer.parseInt(coords[3]); + + //ensure the window is accessible + int centerX = x + w / 2; + int centerY = y + h / 2; + Rectangle screenBounds = SDisplayUtil.getScreenBoundsForPoint(new Point(centerX, centerY)); + if (centerX < screenBounds.x) { + x = screenBounds.x; + } + else if (centerX > screenBounds.x + screenBounds.width) { + x = screenBounds.x + screenBounds.width - w; + if (x < screenBounds.x) { + x = screenBounds.x; + } + } + if (centerY < screenBounds.y) { + y = screenBounds.y; + } + else if (centerY > screenBounds.y + screenBounds.height) { + y = screenBounds.y + screenBounds.height - h; + if (y < screenBounds.y) { + y = screenBounds.y; + } + } + window.setBounds(x, y, w, h); + locLoaded = true; + return; + } + catch (Exception ex) { + ex.printStackTrace(); + } + } + prefs.setPref(locPref, ""); //clear value if invalid + prefs.save(); + } + } + //fallback default size + FFrame mainFrame = Singletons.getView().getFrame(); + window.setSize(mainFrame.getWidth() / 5, mainFrame.getHeight() / 2); + } + + public void refresh() { + List cardPanels = new ArrayList(); + // FCollectionView cards = new FCollection(cardList); + if (cardList != null) { + for (final Card card : cardList) { + CardPanel cardPanel = getCardPanel(card.getId()); + if (cardPanel == null) { + cardPanel = new CardPanel(getMatchUI(), card.getView()); + cardPanel.setDisplayEnabled(true); + } + else { + cardPanel.setCard(card.getView()); //ensure card view updated + } + cardPanels.add(cardPanel); + } + } + + boolean hadCardPanels = getCardPanels().size() > 0; + setCardPanels(cardPanels); + window.setTitle(String.format(title, cardPanels.size())); + + //if window had cards and now doesn't, hide window + //(e.g. cast final card from Flashback zone) + if (hadCardPanels && cardPanels.size() == 0) { + window.setVisible(false); + } + } + + @Override + public void doLayout() { + // if (window.isResizing()) { + // //delay layout slightly to reduce flicker during window resize + // layoutTimer.restart(); + // } + //else { + finishDoLayout(); + //} + } + + private final Timer layoutTimer = new Timer(250, new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + layoutTimer.stop(); + finishDoLayout(); + } + }); + + private void finishDoLayout() { + super.doLayout(); + } + + @Override + public final void mouseOver(final CardPanel panel, final MouseEvent evt) { + getMatchUI().setCard(panel.getCard(), evt.isShiftDown()); + super.mouseOver(panel, evt); + } + @Override + public final void mouseLeftClicked(final CardPanel panel, final MouseEvent evt) { + getMatchUI().getGameController().selectCard(panel.getCard(), null, new MouseTriggerEvent(evt)); + super.mouseLeftClicked(panel, evt); + } + @Override + public final void mouseRightClicked(final CardPanel panel, final MouseEvent evt) { + getMatchUI().getGameController().selectCard(panel.getCard(), null, new MouseTriggerEvent(evt)); + super.mouseRightClicked(panel, evt); + } + +} diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index f0ab65ff144..5a361c87e49 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -29,6 +29,7 @@ import forge.deck.CardPool; import forge.deck.FSideboardDialog; import forge.game.GameEntityView; import forge.game.GameView; +import forge.game.card.Card; import forge.game.card.CardView; import forge.game.phase.PhaseType; import forge.game.player.DelayedReveal; @@ -520,6 +521,11 @@ public class MatchController extends AbstractGuiGame { return SGuiChoose.order(title, "Selected", min, max, (List) optionList, null); } + @Override + public List manipulateCardList(final String title, final List cards, final List manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) { + return null; // pfps not implemented yet + } + @Override public void setCard(final CardView card) { // doesn't need to do anything diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java index de67ed2ef38..5e60457fb8d 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java @@ -11,6 +11,7 @@ import forge.assets.FSkinProp; import forge.deck.CardPool; import forge.game.GameEntityView; import forge.game.GameView; +import forge.game.card.Card; import forge.game.card.CardView; import forge.game.phase.PhaseType; import forge.game.player.DelayedReveal; @@ -147,6 +148,10 @@ public interface IGuiGame { List sideboard(CardPool sideboard, CardPool main); GameEntityView chooseSingleEntityForEffect(String title, List optionList, DelayedReveal delayedReveal, boolean isOptional); List chooseEntitiesForEffect(String title, List optionList, int min, int max, DelayedReveal delayedReveal); + + // show a list of cards and allow some of them to be moved around and return new list + List manipulateCardList(String title, final List cards, final List manipulable, boolean toTop, boolean toBottom, boolean toAnywhere); + void setCard(CardView card); void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi); boolean openZones(Collection zones, Map players); diff --git a/forge-gui/src/main/java/forge/net/ProtocolMethod.java b/forge-gui/src/main/java/forge/net/ProtocolMethod.java index a5c3851c1cc..4642efd5101 100644 --- a/forge-gui/src/main/java/forge/net/ProtocolMethod.java +++ b/forge-gui/src/main/java/forge/net/ProtocolMethod.java @@ -68,6 +68,7 @@ public enum ProtocolMethod { sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class), chooseSingleEntityForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, DelayedReveal.class, Boolean.TYPE), chooseEntitiesForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, Integer.TYPE, Integer.TYPE, DelayedReveal.class), + manipulateCardList (Mode.SERVER, List.class, String.class, List.class, List.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE), setCard (Mode.SERVER, Void.TYPE, CardView.class), // TODO case "setPlayerAvatar": openZones (Mode.SERVER, Boolean.TYPE, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class), diff --git a/forge-gui/src/main/java/forge/net/server/NetGuiGame.java b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java index 7578bb067f5..069f3302d4c 100644 --- a/forge-gui/src/main/java/forge/net/server/NetGuiGame.java +++ b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java @@ -11,6 +11,7 @@ import forge.assets.FSkinProp; import forge.deck.CardPool; import forge.game.GameEntityView; import forge.game.GameView; +import forge.game.card.Card; import forge.game.card.CardView; import forge.game.phase.PhaseType; import forge.game.player.DelayedReveal; @@ -248,6 +249,11 @@ public class NetGuiGame extends AbstractGuiGame { return sendAndWait(ProtocolMethod.chooseEntitiesForEffect, title, optionList, min, max, delayedReveal); } + @Override + public List manipulateCardList(final String title, final List cards, final List manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) { + return sendAndWait(ProtocolMethod.manipulateCardList, title, cards, manipulable, toTop, toBottom, toAnywhere); + } + @Override public void setCard(final CardView card) { updateGameView(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index bad4aa8d8e0..8874ca43c9a 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -349,8 +349,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } private boolean useSelectCardsInput(final FCollectionView sourceList) { - // if UI_SELECT_FROM_ZONES not set use InputSelect only for battlefield and player hand - // if UI_SELECT_FROM_ZONES set use InputSelect for any zone that can be shown + // if UI_SELECT_FROM_CARD_DISPLAYS not set use InputSelect only for battlefield and player hand + // if UI_SELECT_FROM_CARD_DISPLAYS set use InputSelect for any zone that can be shown + if ( FThreads.isGuiThread() ) { return false; } // also can't use InputSelect from GUI thread (e.g., DevMode Tutor) for (final GameEntity c : sourceList) { if (c instanceof Player) { continue; @@ -361,7 +362,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont final Zone cz = ((Card) c).getZone(); final boolean useUiPointAtCard = cz != null && - FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_ZONES) ? + FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) ? (cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) || cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) : (cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield)); @@ -736,31 +737,58 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } } + public ImmutablePair arrangeForMove(final String title, final List cards, final List manipulable, final boolean topOK, final boolean bottomOK) { + List result = getGui().manipulateCardList("Move cards to top or bottom of library", cards, manipulable, topOK, bottomOK, false); + CardCollection toBottom = new CardCollection(); + CardCollection toTop = new CardCollection(); + for (int i = 0; manipulable.contains(result.get(i)) && i arrangeForScry(final CardCollection topN) { CardCollection toBottom = null; CardCollection toTop = null; tempShowCards(topN); - if (topN.size() == 1) { - if (willPutCardOnTop(topN.get(0))) { - toTop = topN; - } else { - toBottom = topN; - } - } else { - toBottom = game.getCardList(getGui().many("Select cards to be put on the bottom of your library", - "Cards to put on the bottom", -1, CardView.getCollection(topN), null)); - topN.removeAll((Collection) toBottom); - if (topN.isEmpty()) { - toTop = null; - } else if (topN.size() == 1) { - toTop = topN; - } else { - toTop = game.getCardList(getGui().order("Arrange cards to be put on top of your library", - "Top of Library", CardView.getCollection(topN), null)); - } - } + if ( FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) ) { + ArrayList cardList = new ArrayList(); // pfps there must be a better way + for (final Card card : player.getCardsIn(ZoneType.Library)) { + cardList.add(card); + } + ImmutablePair result = + arrangeForMove("Move cards to top or bottom of library", cardList, topN, true, true); + System.out.print("Arrange "); System.out.println(result); + toTop = result.getLeft(); + toBottom = result.getRight(); + } else { + if (topN.size() == 1) { + if (willPutCardOnTop(topN.get(0))) { + toTop = topN; + } else { + toBottom = topN; + } + } else { + toBottom = game.getCardList(getGui().many("Select cards to be put on the bottom of your library", + "Cards to put on the bottom", -1, CardView.getCollection(topN), null)); + topN.removeAll((Collection) toBottom); + if (topN.isEmpty()) { + toTop = null; + } else if (topN.size() == 1) { + toTop = topN; + } else { + toTop = game.getCardList(getGui().order("Arrange cards to be put on top of your library", + "Top of Library", CardView.getCollection(topN), null)); + } + } + } endTempShowCards(); return ImmutablePair.of(toTop, toBottom); } diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index b96037d9fca..6059254787d 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -125,7 +125,7 @@ public class ForgePreferences extends PreferencesStore { UI_DISABLE_IMAGES_EFFECT_CARDS("false"), UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"), UI_DEFAULT_FONT_SIZE("12"), - UI_SELECT_FROM_ZONES("true"), + UI_SELECT_FROM_CARD_DISPLAYS("true"), UI_FOR_TOUCHSCREN("false"), UI_VIBRATE_ON_LIFE_LOSS("true"),