Branch GUI refactoring.

Most of the code has been converted, but some problems remain (mostly with Inputs). Nothing has been tested yet.
This commit is contained in:
elcnesh
2014-09-02 08:29:19 +00:00
parent 6418962357
commit e4f6c7cb5d
71 changed files with 2192 additions and 1207 deletions

View File

@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ForgeLocal</name>
<name>forge</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>

View File

@@ -31,17 +31,11 @@ import forge.control.FControl;
import forge.deck.CardPool;
import forge.error.BugReportDialog;
import forge.events.UiEvent;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.event.GameEventTurnBegan;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.IHasIcon;
import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
@@ -81,6 +75,10 @@ import forge.toolbox.MouseTriggerEvent;
import forge.toolbox.special.PhaseLabel;
import forge.util.BuildInfo;
import forge.util.ITriggerEvent;
import forge.view.CardView;
import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView;
public class GuiDesktop implements IGuiBase {
@@ -132,7 +130,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public boolean mayShowCard(Card card) {
public boolean mayShowCard(CardView card) {
return Singletons.getControl().mayShowCard(card);
}
@@ -153,7 +151,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public int showCardOptionDialog(final Card card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) {
public int showCardOptionDialog(final CardView card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) {
if (card != null) {
FThreads.invokeInEdtAndWait(new Runnable() {
@Override
@@ -177,7 +175,7 @@ public class GuiDesktop implements IGuiBase {
@Override
public <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode) {
return GuiChoose.order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode);
}
@@ -231,10 +229,11 @@ public class GuiDesktop implements IGuiBase {
@Override
public void updatePhase() {
PhaseHandler pH = Singletons.getControl().getObservedGame().getPhaseHandler();
Player p = pH.getPlayerTurn();
PhaseType ph = pH.getPhase();
//PhaseHandler pH = Singletons.getControl().getObservedGame().getPhaseHandler();
//PhaseType ph = pH.getPhase();
final PlayerView p = Singletons.getControl().getGameView().getPlayerTurn();
final PhaseType ph = Singletons.getControl().getGameView().getPhase();
final CMatchUI matchUi = CMatchUI.SINGLETON_INSTANCE;
PhaseLabel lbl = matchUi.getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph);
@@ -245,10 +244,10 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void updateTurn(final GameEventTurnBegan event, final Game game) {
VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(event.turnOwner);
public void updateTurn(final PlayerView player) {
VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(player);
SDisplayUtil.showTab(nextField);
CPrompt.SINGLETON_INSTANCE.updateText(game);
CPrompt.SINGLETON_INSTANCE.updateText();
}
@Override
@@ -273,7 +272,7 @@ public class GuiDesktop implements IGuiBase {
@Override
public void finishGame() {
new ViewWinLose(Singletons.getControl().getObservedGame());
new ViewWinLose(Singletons.getControl().getGameView());
if (showOverlay) {
SOverlayUtils.showOverlay();
}
@@ -290,7 +289,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void setPanelSelection(Card c) {
public void setPanelSelection(final CardView c) {
GuiUtils.setPanelSelection(c);
}
@@ -374,7 +373,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void setCard(Card card) {
public void setCard(final CardView card) {
CMatchUI.SINGLETON_INSTANCE.setCard(card);
}
@@ -384,22 +383,22 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void setUsedToPay(Card card, boolean b) {
public void setUsedToPay(final CardView card, final boolean b) {
CMatchUI.SINGLETON_INSTANCE.setUsedToPay(card, b);
}
@Override
public void setHighlighted(Player player, boolean b) {
public void setHighlighted(final PlayerView player, final boolean b) {
CMatchUI.SINGLETON_INSTANCE.setHighlighted(player, b);
}
@Override
public void showPromptMessage(String message) {
public void showPromptMessage(final String message) {
CMatchUI.SINGLETON_INSTANCE.showMessage(message);
}
@Override
public boolean stopAtPhase(Player playerTurn, PhaseType phase) {
public boolean stopAtPhase(final PlayerView playerTurn, PhaseType phase) {
return CMatchUI.SINGLETON_INSTANCE.stopAtPhase(playerTurn, phase);
}
@@ -409,21 +408,22 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public Game getGame() {
return FControl.instance.getObservedGame();
@Deprecated
public IGameView getGame() {
return FControl.instance.getGameView();
}
public Object showManaPool(Player player) {
public Object showManaPool(final PlayerView player) {
return null; //not needed since mana pool icons are always visible
}
@Override
public void hideManaPool(Player player, Object zoneToRestore) {
public void hideManaPool(final PlayerView player, final Object zoneToRestore) {
//not needed since mana pool icons are always visible
}
@Override
public boolean openZones(List<ZoneType> zones, Map<Player, Object> players) {
public boolean openZones(final List<ZoneType> zones, final Map<PlayerView, Object> players) {
if (zones.size() == 1) {
switch (zones.get(0)) {
case Battlefield:
@@ -437,31 +437,31 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void restoreOldZones(Map<Player, Object> playersToRestoreZonesFor) {
public void restoreOldZones(final Map<PlayerView, Object> playersToRestoreZonesFor) {
}
@Override
public void updateZones(List<Pair<Player, ZoneType>> zonesToUpdate) {
public void updateZones(final List<Pair<PlayerView, ZoneType>> zonesToUpdate) {
CMatchUI.SINGLETON_INSTANCE.updateZones(zonesToUpdate);
}
@Override
public void updateCards(Set<Card> cardsToUpdate) {
public void updateCards(final Set<CardView> cardsToUpdate) {
CMatchUI.SINGLETON_INSTANCE.updateCards(cardsToUpdate);
}
@Override
public void refreshCardDetails(Collection<Card> cards) {
public void refreshCardDetails(final Collection<CardView> cards) {
CMatchUI.SINGLETON_INSTANCE.refreshCardDetails(cards);
}
@Override
public void updateManaPool(List<Player> manaPoolUpdate) {
public void updateManaPool(final List<PlayerView> manaPoolUpdate) {
CMatchUI.SINGLETON_INSTANCE.updateManaPool(manaPoolUpdate);
}
@Override
public void updateLives(List<Player> livesUpdate) {
public void updateLives(final List<PlayerView> livesUpdate) {
CMatchUI.SINGLETON_INSTANCE.updateLives(livesUpdate);
}
@@ -471,10 +471,11 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public Map<Card, Integer> getDamageToAssign(Card attacker, List<Card> blockers,
int damageDealt, GameEntity defender, boolean overrideOrder) {
return CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker, blockers,
damageDealt, defender, overrideOrder);
public Map<CardView, Integer> getDamageToAssign(final CardView attacker,
final List<CardView> blockers, final int damageDealt,
final GameEntityView defender, final boolean overrideOrder) {
return CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker,
blockers, damageDealt, defender, overrideOrder);
}
@Override

View File

@@ -29,6 +29,7 @@ import forge.item.InventoryItem;
import forge.properties.ForgeConstants;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinIcon;
import forge.view.CardView;
import org.apache.commons.lang3.StringUtils;
@@ -80,6 +81,7 @@ public class ImageCache {
* retrieve an image from the cache. returns null if the image is not found in the cache
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.
*/
@Deprecated
public static BufferedImage getImage(Card card, int width, int height) {
final String key;
if (!Singletons.getControl().mayShowCard(card) || card.isFaceDown()) {
@@ -89,7 +91,21 @@ public class ImageCache {
}
return scaleImage(key, width, height, true);
}
/**
* retrieve an image from the cache. returns null if the image is not found in the cache
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.
*/
public static BufferedImage getImage(final CardView card, final int width, final int height) {
final String key;
if (!Singletons.getControl().mayShowCard(card)) {
key = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE;
} else {
key = card.getOriginal().getImageKey();
}
return scaleImage(key, width, height, true);
}
/**
* retrieve an image from the cache. returns null if the image is not found in the cache
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.

View File

@@ -17,6 +17,26 @@
*/
package forge.control;
import java.awt.Component;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.swing.ImageIcon;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import org.apache.commons.lang3.StringUtils;
import forge.FThreads;
import forge.GuiBase;
import forge.ImageCache;
@@ -35,15 +55,21 @@ import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
import forge.gui.framework.*;
import forge.player.GamePlayerUtil;
import forge.player.LobbyPlayerHuman;
import forge.gui.framework.EDocID;
import forge.gui.framework.FScreen;
import forge.gui.framework.InvalidLayoutFileException;
import forge.gui.framework.SDisplayUtil;
import forge.gui.framework.SLayoutIO;
import forge.gui.framework.SOverflowUtil;
import forge.gui.framework.SResizingUtil;
import forge.match.input.InputQueue;
import forge.menus.ForgeMenu;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.player.LobbyPlayerHuman;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import forge.properties.ForgeConstants;
import forge.quest.QuestController;
import forge.quest.data.QuestPreferences.QPref;
import forge.quest.io.QuestDataIO;
@@ -66,19 +92,11 @@ import forge.toolbox.special.PhaseIndicator;
import forge.util.GuiDisplayUtil;
import forge.util.MyRandom;
import forge.util.NameGenerator;
import forge.view.CardView;
import forge.view.FFrame;
import forge.view.FView;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import forge.view.IGameView;
import forge.view.PlayerView;
/**
* <p>
@@ -97,7 +115,7 @@ public enum FControl implements KeyEventDispatcher {
private FScreen currentScreen;
private boolean altKeyLastDown;
private CloseAction closeAction;
private Player localPlayer;
private PlayerView localPlayer;
public static enum CloseAction {
NONE,
@@ -352,6 +370,7 @@ public enum FControl implements KeyEventDispatcher {
if (children.length != 0) { children[0].setSize(display.getSize()); }
}
@Deprecated
public Player getCurrentPlayer() {
// try current priority
Player currentPriority = game.getPhaseHandler().getPriorityPlayer();
@@ -369,9 +388,13 @@ public enum FControl implements KeyEventDispatcher {
return null;
}
@Deprecated
public boolean mayShowCard(Card c) {
return game == null || !gameHasHumanPlayer || c.canBeShownTo(getCurrentPlayer());
}
public boolean mayShowCard(final CardView c) {
return gameView == null || !gameHasHumanPlayer || gameView.mayShowCard(c, getCurrentPlayer());
}
/**
* TODO: Write javadoc for this method.
@@ -382,13 +405,19 @@ public enum FControl implements KeyEventDispatcher {
}
private Game game;
private IGameView gameView;
private boolean gameHasHumanPlayer;
@Deprecated
public Game getObservedGame() {
return game;
}
public Player getLocalPlayer() {
public IGameView getGameView() {
return this.gameView;
}
public PlayerView getLocalPlayer() {
return localPlayer;
}
@@ -428,6 +457,14 @@ public enum FControl implements KeyEventDispatcher {
return inputQueue;
}
public final void startGameInSameMatch() {
this.startGameWithUi(game.getMatch());
}
public final void startGameAndClearMatch() {
game.getMatch().clearGamesPlayed();
startGameInSameMatch();
}
public final void startGameWithUi(final Match match) {
if (this.game != null) {
this.setCurrentScreen(FScreen.MATCH_SCREEN);
@@ -436,15 +473,23 @@ public enum FControl implements KeyEventDispatcher {
return; //TODO: See if it's possible to run multiple games at once without crashing
}
setPlayerName(match.getPlayers());
final Game newGame = match.createGame();
attachToGame(newGame);
this.game = match.createGame();
final LobbyPlayer me = getGuiPlayer();
for (final Player p : this.game.getPlayers()) {
if (p.getLobbyPlayer().equals(me)) {
this.gameView = (IGameView) p.getController();
break;
}
}
attachToGame(this.gameView);
// It's important to run match in a different thread to allow GUI inputs to be invoked from inside game.
// Game is set on pause while gui player takes decisions
game.getAction().invoke(new Runnable() {
@Override
public void run() {
match.startGame(newGame);
match.startGame(game);
}
});
SOverlayUtils.hideOverlay();
@@ -459,11 +504,11 @@ public enum FControl implements KeyEventDispatcher {
private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler();
private final FControlGamePlayback playbackControl = new FControlGamePlayback();
private void attachToGame(Game game0) {
if (game0.getRules().getGameType() == GameType.Quest) {
private void attachToGame(final IGameView game0) {
if (game0.getGameType().equals(GameType.Quest)) {
QuestController qc = FModel.getQuest();
// Reset new list when the Match round starts, not when each game starts
if (game0.getMatch().getPlayedGames().isEmpty()) {
if (game0.isFirstGameInMatch()) {
qc.getCards().resetNewList();
}
game0.subscribeToEvents(qc); // this one listens to player's mulligans ATM
@@ -471,49 +516,45 @@ public enum FControl implements KeyEventDispatcher {
inputQueue = new InputQueue();
this.game = game0;
game.subscribeToEvents(Singletons.getControl().getSoundSystem());
game0.subscribeToEvents(Singletons.getControl().getSoundSystem());
//switch back to match screen music
Singletons.getControl().getSoundSystem().setBackgroundMusic(MusicPlaylist.MATCH);
LobbyPlayer humanLobbyPlayer = getGuiPlayer();
final LobbyPlayer humanLobbyPlayer = getGuiPlayer();
// The UI controls should use these game data as models
CMatchUI.SINGLETON_INSTANCE.initMatch(game.getRegisteredPlayers(), humanLobbyPlayer);
final List<PlayerView> players = game0.getPlayers();
CMatchUI.SINGLETON_INSTANCE.initMatch(players, humanLobbyPlayer);
localPlayer = null;
for (Player p : game.getPlayers()) {
gameHasHumanPlayer = false;
for (final PlayerView p : players) {
if (p.getLobbyPlayer() == humanLobbyPlayer) {
localPlayer = p;
gameHasHumanPlayer = true;
break;
}
}
CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer);
CStack.SINGLETON_INSTANCE.setModel(game.getStack(), localPlayer);
CPlayers.SINGLETON_INSTANCE.setModel(game);
CLog.SINGLETON_INSTANCE.setModel(game.getGameLog());
CDock.SINGLETON_INSTANCE.setModel(game0, humanLobbyPlayer);
CStack.SINGLETON_INSTANCE.setModel(game0, localPlayer);
CPlayers.SINGLETON_INSTANCE.setModel(game0);
CLog.SINGLETON_INSTANCE.setModel(game0.getGameLog());
actuateMatchPreferences();
VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers());
VAntes.SINGLETON_INSTANCE.setModel(players);
setCurrentScreen(FScreen.MATCH_SCREEN);
SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
CPrompt.SINGLETON_INSTANCE.getInputControl().setGame(game);
CPrompt.SINGLETON_INSTANCE.getInputControl().setGame(game0);
// Listen to DuelOutcome event to show ViewWinLose
game.subscribeToEvents(fcVisitor);
game0.subscribeToEvents(fcVisitor);
// Add playback controls to match if needed
gameHasHumanPlayer = false;
for (Player p : game.getPlayers()) {
if (p.getController().getLobbyPlayer() == getGuiPlayer())
gameHasHumanPlayer = true;
}
if (!gameHasHumanPlayer) {
game.subscribeToEvents(playbackControl);
if (localPlayer != null) {
game0.subscribeToEvents(playbackControl);
}
for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
@@ -522,7 +563,7 @@ public enum FControl implements KeyEventDispatcher {
// per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch
//Set Field shown to current player.
VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(game.getPlayers().get(0));
final VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(localPlayer);
SDisplayUtil.showTab(nextField);
}

View File

@@ -36,7 +36,7 @@ public class FDeckViewer extends FDialog {
private final CardManager cardManager;
private DeckSection currentSection;
private final CardDetailPanel cardDetail = new CardDetailPanel(null);
private final CardDetailPanel cardDetail = new CardDetailPanel();
private final CardPicturePanel cardPicture = new CardPicturePanel();
private final FButton btnCopyToClipboard = new FButton("Copy to Clipboard");
private final FButton btnChangeSection = new FButton("Change Section");

View File

@@ -99,7 +99,7 @@ public class BoxedProductCardListViewer extends FDialog {
public BoxedProductCardListViewer(final String title, final String message, final List<PaperCard> list, final Icon dialogIcon) {
this.list = Collections.unmodifiableList(list);
this.jList = new JList<PaperCard>(new ChooserListModel());
this.detail = new CardDetailPanel(null);
this.detail = new CardDetailPanel();
this.picture = new CardPicturePanel();
this.picture.setOpaque(false);

View File

@@ -18,7 +18,7 @@
package forge.gui;
import forge.game.card.Card;
import forge.view.CardView;
/**
* The class CardContainer. A card container is an object that references a
@@ -36,7 +36,7 @@ public interface CardContainer {
* @param card
* a {@link forge.game.card.Card} object.
*/
void setCard(Card card);
void setCard(CardView card);
/**
* <p>
@@ -45,6 +45,6 @@ public interface CardContainer {
*
* @return a {@link forge.game.card.Card} object.
*/
Card getCard();
CardView getCard();
}

View File

@@ -30,6 +30,8 @@ import forge.item.InventoryItemFromSet;
import forge.model.FModel;
import forge.toolbox.*;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
import forge.view.FDialog;
import org.apache.commons.lang3.StringUtils;
@@ -62,7 +64,7 @@ public class CardDetailPanel extends SkinnedPanel {
private final FHtmlViewer cdArea;
private final FScrollPane scrArea;
public CardDetailPanel(final Card card) {
public CardDetailPanel() {
super();
this.setLayout(null);
this.setOpaque(false);
@@ -74,7 +76,7 @@ public class CardDetailPanel extends SkinnedPanel {
this.setInfoLabel = new JLabel();
this.setInfoLabel.setHorizontalAlignment(SwingConstants.CENTER);
Font font = new Font("Dialog", 0, 14);
final Font font = new Font("Dialog", 0, 14);
this.nameCostLabel.setFont(font);
this.typeLabel.setFont(font);
this.idLabel.setFont(font);
@@ -91,8 +93,6 @@ public class CardDetailPanel extends SkinnedPanel {
this.add(this.powerToughnessLabel);
this.add(this.setInfoLabel);
this.add(this.scrArea);
this.setCard(card);
}
@Override
@@ -121,7 +121,7 @@ public class CardDetailPanel extends SkinnedPanel {
this.scrArea.setBounds(0, y, getWidth(), getHeight() - y);
}
public final void setItem(InventoryItemFromSet item) {
public final void setItem(final InventoryItemFromSet item) {
nameCostLabel.setText(item.getName());
typeLabel.setVisible(false);
powerToughnessLabel.setVisible(false);
@@ -155,7 +155,7 @@ public class CardDetailPanel extends SkinnedPanel {
});
}
/** {@inheritDoc} */
@Deprecated
public final void setCard(Card card) {
this.nameCostLabel.setText("");
this.typeLabel.setVisible(true);
@@ -169,7 +169,7 @@ public class CardDetailPanel extends SkinnedPanel {
this.setInfoLabel.setBorder(null);
this.cdArea.setText("");
if (card == null) {
this.updateBorder(null, false);
this.updateBorder((Card)null, false);
return;
}
@@ -258,6 +258,102 @@ public class CardDetailPanel extends SkinnedPanel {
});
}
public final void setCard(final CardView card, final boolean isInAltState) {
this.nameCostLabel.setText("");
this.typeLabel.setVisible(true);
this.typeLabel.setText("");
this.powerToughnessLabel.setVisible(true);
this.powerToughnessLabel.setText("");
this.idLabel.setText("");
this.setInfoLabel.setText("");
this.setInfoLabel.setToolTipText("");
this.setInfoLabel.setOpaque(false);
this.setInfoLabel.setBorder(null);
this.cdArea.setText("");
if (card == null) {
this.updateBorder((CardStateView)null, false);
return;
}
final CardStateView state = card.getState(isInAltState);
//this.setCard(card.card);
boolean canShowThis = false;
if (Singletons.getControl().mayShowCard(card) || FDialog.isModalOpen()) { //allow showing cards while modal open to account for revealing, picking, and ordering cards
canShowThis = true;
if (state.getManaCost().isNoCost()) {
this.nameCostLabel.setText(state.getName());
} else {
String manaCost = state.getManaCost().toString();
//if (state.isSplitCard() && card.getCurState() == CardCharacteristicName.Original) {
// manaCost = card.getRules().getMainPart().getManaCost().toString() + " // " + card.getRules().getOtherPart().getManaCost().toString();
//}
this.nameCostLabel.setText(FSkin.encodeSymbols(state.getName() + " - " + manaCost, true));
}
this.typeLabel.setText(CardDetailUtil.formatCardType(state));
String set = card.getSetCode();
this.setInfoLabel.setText(set);
if (null != set && !set.isEmpty()) {
CardEdition edition = FModel.getMagicDb().getEditions().get(set);
if (null == edition) {
setInfoLabel.setToolTipText(card.getRarity().name());
}
else {
setInfoLabel.setToolTipText(String.format("%s (%s)", edition.getName(), card.getRarity().name()));
}
this.setInfoLabel.setOpaque(true);
Color backColor;
switch(card.getRarity()) {
case Uncommon:
backColor = fromDetailColor(DetailColors.UNCOMMON);
break;
case Rare:
backColor = fromDetailColor(DetailColors.RARE);
break;
case MythicRare:
backColor = fromDetailColor(DetailColors.MYTHIC);
break;
case Special: //"Timeshifted" or other Special Rarity Cards
backColor = fromDetailColor(DetailColors.SPECIAL);
break;
default: //case BasicLand: + case Common:
backColor = fromDetailColor(DetailColors.COMMON);
break;
}
Color foreColor = FSkin.getHighContrastColor(backColor);
this.setInfoLabel.setBackground(backColor);
this.setInfoLabel.setForeground(foreColor);
this.setInfoLabel.setBorder(BorderFactory.createLineBorder(foreColor));
}
}
this.updateBorder(state, canShowThis);
this.powerToughnessLabel.setText(CardDetailUtil.formatPowerToughness(state));
this.idLabel.setText(CardDetailUtil.formatCardId(state));
// fill the card text
this.cdArea.setText(FSkin.encodeSymbols(CardDetailUtil.composeCardText(state, canShowThis), true));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scrArea.getVerticalScrollBar().setValue(scrArea.getVerticalScrollBar().getMinimum());
}
});
}
/** @return FLabel */
public FLabel getNameCostLabel() {
return this.nameCostLabel;
@@ -283,6 +379,7 @@ public class CardDetailPanel extends SkinnedPanel {
return this.cdArea;
}
@Deprecated
private void updateBorder(final Card card, final boolean canShow) {
// color info
if (card == null) {
@@ -296,6 +393,19 @@ public class CardDetailPanel extends SkinnedPanel {
scrArea.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, color));
}
private void updateBorder(final CardStateView card, final boolean canShow) {
// color info
if (card == null) {
this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
scrArea.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
return;
}
Color color = fromDetailColor(CardDetailUtil.getBorderColor(card, canShow));
this.setBorder(BorderFactory.createLineBorder(color, 2));
scrArea.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, color));
}
//ensure mouse listener hooked up to all certain opaque child components so it can get raised properly
@Override
public void addMouseListener(MouseListener l) {

View File

@@ -97,7 +97,7 @@ public class CardListViewer extends FDialog {
public CardListViewer(final String title, final String message, final List<PaperCard> list, final Icon dialogIcon) {
this.list = Collections.unmodifiableList(list);
this.jList = new JList<PaperCard>(new ChooserListModel());
this.detail = new CardDetailPanel(null);
this.detail = new CardDetailPanel();
this.picture = new CardPicturePanel();
this.picture.setOpaque(false);

View File

@@ -18,21 +18,21 @@
package forge.gui;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import forge.ImageCache;
import forge.ImageKeys;
import forge.card.CardCharacteristicName;
import forge.game.card.Card;
import forge.item.InventoryItem;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.toolbox.imaging.FImagePanel;
import forge.toolbox.imaging.FImageUtil;
import forge.toolbox.imaging.FImagePanel.AutoSizeImageMode;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import forge.toolbox.imaging.FImageUtil;
import forge.view.CardView.CardStateView;
/**
* Displays image associated with a card or inventory item.
@@ -48,7 +48,7 @@ public final class CardPicturePanel extends JPanel {
private final FImagePanel panel;
private BufferedImage currentImage;
private boolean mayShowCard;
private boolean mayShowObject;
public CardPicturePanel() {
super(new BorderLayout());
@@ -59,23 +59,21 @@ public final class CardPicturePanel extends JPanel {
public void setCard(final InventoryItem cp) {
this.displayed = cp;
this.mayShowCard = true;
this.mayShowObject = true;
this.setImage();
}
//@Override
@Deprecated
public void setCard(final Card c, boolean mayShowCard) {
this.displayed = c;
this.mayShowCard = mayShowCard;
this.mayShowObject = mayShowCard;
this.setImage();
}
public void setCardImage(CardCharacteristicName flipState) {
BufferedImage image = FImageUtil.getImage((Card)displayed, flipState);
if (image != null && image != this.currentImage) {
this.currentImage = image;
this.panel.setImage(image, getAutoSizeImageMode());
}
public void setCard(final CardStateView c, final boolean mayShowCard) {
this.displayed = c;
this.mayShowObject = mayShowCard;
this.setImage();
}
public void setImage() {
@@ -88,14 +86,19 @@ public final class CardPicturePanel extends JPanel {
public BufferedImage getImage() {
if (displayed instanceof InventoryItem) {
InventoryItem item = (InventoryItem) displayed;
final InventoryItem item = (InventoryItem) displayed;
return ImageCache.getOriginalImage(ImageKeys.getImageKey(item, false), true);
}
else if (displayed instanceof Card) {
if (mayShowCard) {
if (mayShowObject) {
return FImageUtil.getImage((Card)displayed);
}
return ImageCache.getOriginalImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true);
} else if (displayed instanceof CardStateView) {
if (mayShowObject) {
return FImageUtil.getImage((CardStateView)displayed);
}
return ImageCache.getOriginalImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true);
}
return null;
}

View File

@@ -1,23 +1,37 @@
package forge.gui;
import forge.game.card.Card;
import forge.game.spellability.SpellAbility;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import forge.screens.match.CMatchUI;
import forge.toolbox.*;
import forge.view.FDialog;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import forge.screens.match.CMatchUI;
import forge.toolbox.FButton;
import forge.toolbox.FLabel;
import forge.toolbox.FList;
import forge.toolbox.FPanel;
import forge.toolbox.FScrollPane;
import forge.view.CardView;
import forge.view.FDialog;
import forge.view.SpellAbilityView;
// An input box for handling the order of choices.
// Left box has the original choices
@@ -310,13 +324,13 @@ public class DualListBox<T> extends FDialog {
if (!showCard || null == obj) {
return;
}
Card card = null;
if (obj instanceof Card) {
card = (Card) obj;
} else if (obj instanceof SpellAbility) {
card = ((SpellAbility) obj).getHostCard();
CardView card = null;
if (obj instanceof CardView) {
card = (CardView) obj;
} else if (obj instanceof SpellAbilityView) {
card = ((SpellAbilityView) obj).getHostCard();
} else if (obj instanceof PaperCard) {
card = Card.getCardForUi((IPaperCard) obj);
card = CardView.getCardForUi((IPaperCard) obj);
}
GuiUtils.clearPanelSelections();

View File

@@ -1,24 +1,30 @@
package forge.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import javax.swing.JList;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import forge.FThreads;
import forge.Singletons;
import forge.game.card.Card;
import forge.item.InventoryItem;
import forge.screens.match.CMatchUI;
import forge.toolbox.FOptionPane;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import forge.view.CardView;
/**
* TODO: Write javadoc for this type.
@@ -200,8 +206,8 @@ public class GuiChoose {
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent ev) {
if (list.getSelectedValue() instanceof Card) {
Card card = (Card) list.getSelectedValue();
if (list.getSelectedValue() instanceof CardView) {
final CardView card = (CardView) list.getSelectedValue();
if (card.isFaceDown() && Singletons.getControl().mayShowCard(card)) {
CMatchUI.SINGLETON_INSTANCE.setCard(card, true);
}
@@ -240,17 +246,17 @@ public class GuiChoose {
return null;
}
public static <T> List<T> many(final String title, final String topCaption, int cnt, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> many(final String title, final String topCaption, int cnt, final List<T> sourceChoices, final CardView referenceCard) {
return order(title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false);
}
public static <T> List<T> many(final String title, final String topCaption, int min, int max, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> many(final String title, final String topCaption, int min, int max, final List<T> sourceChoices, final CardView referenceCard) {
int m2 = min >= 0 ? sourceChoices.size() - min : -1;
int m1 = max >= 0 ? sourceChoices.size() - max : -1;
return order(title, topCaption, m1, m2, sourceChoices, null, referenceCard, false);
}
public static <T> List<T> order(final String title, final String top, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> order(final String title, final String top, final List<T> sourceChoices, final CardView referenceCard) {
return order(title, top, 0, 0, sourceChoices, null, referenceCard, false);
}
@@ -261,7 +267,7 @@ public class GuiChoose {
}
public static <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode) {
// An input box for handling the order of choices.
Callable<List<T>> callable = new Callable<List<T>>() {

View File

@@ -1,17 +1,17 @@
package forge.gui;
import forge.FThreads;
import forge.game.card.Card;
import forge.screens.match.CMatchUI;
import forge.toolbox.FOptionPane;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import javax.swing.UIManager;
import org.apache.commons.lang3.StringUtils;
import forge.FThreads;
import forge.screens.match.CMatchUI;
import forge.toolbox.FOptionPane;
import forge.view.CardView;
/**
* Holds player interactions using standard windows
*
@@ -19,17 +19,17 @@ import java.util.concurrent.FutureTask;
public class GuiDialog {
private static final String[] defaultConfirmOptions = { "Yes", "No" };
public static boolean confirm(final Card c, final String question) {
public static boolean confirm(final CardView c, final String question) {
return GuiDialog.confirm(c, question, true, null);
}
public static boolean confirm(final Card c, final String question, final boolean defaultChoice) {
public static boolean confirm(final CardView c, final String question, final boolean defaultChoice) {
return GuiDialog.confirm(c, question, defaultChoice, null);
}
public static boolean confirm(final Card c, final String question, String[] options) {
public static boolean confirm(final CardView c, final String question, String[] options) {
return GuiDialog.confirm(c, question, true, options);
}
public static boolean confirm(final Card c, final String question, final boolean defaultIsYes, final String[] options) {
public static boolean confirm(final CardView c, final String question, final boolean defaultIsYes, final String[] options) {
Callable<Boolean> confirmTask = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
@@ -37,7 +37,7 @@ public class GuiDialog {
CMatchUI.SINGLETON_INSTANCE.setCard(c);
}
final String title = c == null ? "Question" : c.getCardForUi().getName() + " - Ability";
final String title = c == null ? "Question" : c + " - Ability";
String questionToUse = StringUtils.isBlank(question) ? "Activate card's ability?" : question;
String[] opts = options == null ? defaultConfirmOptions : options;
int answer = FOptionPane.showOptionDialog(questionToUse, title, FOptionPane.QUESTION_ICON, opts, defaultIsYes ? 0 : 1);

View File

@@ -17,20 +17,26 @@
*/
package forge.gui;
import forge.game.card.Card;
import forge.screens.match.VMatchUI;
import forge.screens.match.views.VField;
import forge.view.arcane.CardPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import forge.screens.match.VMatchUI;
import forge.screens.match.views.VField;
import forge.view.CardView;
import forge.view.arcane.CardPanel;
/**
* <p>
* GuiUtils class.
@@ -81,15 +87,15 @@ public final class GuiUtils {
/**
* Highlight a card on the playfield.
*
* @param c
* @param card
* a card to be highlighted
*/
public static void setPanelSelection(final Card c) {
public static void setPanelSelection(final CardView card) {
mainLoop:
for (VField v : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
List<CardPanel> panels = v.getTabletop().getCardPanels();
for (CardPanel p : panels) {
if (p.getCard().equals(c)) {
for (final VField v : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
final List<CardPanel> panels = v.getTabletop().getCardPanels();
for (final CardPanel p : panels) {
if (p.getCard().equals(card)) {
p.setSelected(true);
break mainLoop;
}

View File

@@ -1,7 +1,6 @@
package forge.itemmanager.views;
import forge.ImageCache;
import forge.game.card.Card;
import forge.assets.FSkinProp;
import forge.deck.DeckProxy;
import forge.gui.framework.ILocalRepaint;
@@ -20,6 +19,7 @@ import forge.toolbox.FSkin.SkinColor;
import forge.toolbox.FSkin.SkinFont;
import forge.toolbox.FSkin.SkinImage;
import forge.toolbox.special.CardZoomer;
import forge.view.CardView;
import forge.view.arcane.CardPanel;
import javax.swing.*;
@@ -232,7 +232,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
ItemInfo item = getItemAtPoint(e.getPoint());
if (item != null && item.item instanceof IPaperCard) {
setLockHoveredItem(true); //lock hoveredItem while zoomer open
Card card = Card.getCardForUi((IPaperCard) item.item);
final CardView card = CardView.getCardForUi((IPaperCard) item.item);
CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(card);
}
}
@@ -1099,8 +1099,8 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
if (item instanceof IPaperCard) {
IPaperCard paperCard = (IPaperCard)item;
if (paperCard.isFoil()) {
Card card = Card.getCardForUi(paperCard);
if (card.getFoil() == 0) { //if foil finish not yet established, assign a random one
final CardView card = CardView.getCardForUi(paperCard);
if (card.getFoilIndex() == 0) { //if foil finish not yet established, assign a random one
card.setRandomFoil();
}
CardPanel.drawFoilEffect(g, card, bounds.x, bounds.y, bounds.width, bounds.height, borderSize);

View File

@@ -321,7 +321,7 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
FScrollPane scrAvatars = new FScrollPane(vgdAvatarList, true,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
CardDetailPanel vgdDetail = new CardDetailPanel(null);
CardDetailPanel vgdDetail = new CardDetailPanel();
vgdAvatarDetails.add(vgdDetail);
vgdDeckPanel.setLayout(new MigLayout(sectionConstraints));

View File

@@ -17,49 +17,65 @@
*/
package forge.screens.match;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JMenu;
import org.apache.commons.lang3.tuple.Pair;
import org.testng.collections.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import forge.LobbyPlayer;
import forge.UiCommand;
import forge.FThreads;
import forge.ImageCache;
import forge.LobbyPlayer;
import forge.Singletons;
import forge.UiCommand;
import forge.events.IUiEventVisitor;
import forge.events.UiEvent;
import forge.events.UiEventAttackerDeclared;
import forge.events.UiEventBlockerAssigned;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.gui.framework.*;
import forge.gui.framework.EDocID;
import forge.gui.framework.FScreen;
import forge.gui.framework.ICDoc;
import forge.gui.framework.IVDoc;
import forge.gui.framework.SDisplayUtil;
import forge.item.InventoryItem;
import forge.menus.IMenuProvider;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.QuestDraftUtils;
import forge.screens.match.controllers.*;
import forge.screens.match.controllers.CAntes;
import forge.screens.match.controllers.CCombat;
import forge.screens.match.controllers.CDetail;
import forge.screens.match.controllers.CPicture;
import forge.screens.match.controllers.CPrompt;
import forge.screens.match.menus.CMatchUIMenus;
import forge.screens.match.views.*;
import forge.screens.match.views.VCommand;
import forge.screens.match.views.VField;
import forge.screens.match.views.VHand;
import forge.screens.match.views.VPlayers;
import forge.toolbox.FOptionPane;
import forge.toolbox.FOverlay;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinImage;
import forge.toolbox.special.PhaseLabel;
import forge.view.CardView;
import forge.view.GameEntityView;
import forge.view.PlayerView;
import forge.view.arcane.CardPanel;
import forge.view.arcane.PlayArea;
import org.apache.commons.lang3.tuple.Pair;
import javax.swing.*;
import java.util.*;
/**
* Constructs instance of match UI controller, used as a single point of
* top-level control for child UIs. Tasks targeting the view of individual
@@ -71,7 +87,7 @@ import java.util.*;
public enum CMatchUI implements ICDoc, IMenuProvider {
SINGLETON_INSTANCE;
private List<Player> sortedPlayers;
private List<PlayerView> sortedPlayers;
private VMatchUI view;
private EventBus uiEvents;
@@ -85,14 +101,12 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
uiEvents.register(visitor);
}
private SkinImage getPlayerAvatar(final Player p, final int defaultIndex) {
LobbyPlayer lp = p.getLobbyPlayer();
if (avatarImages.containsKey(lp)) {
return ImageCache.getIcon(avatarImages.get(lp));
private SkinImage getPlayerAvatar(final LobbyPlayer p, final int defaultIndex) {
if (avatarImages.containsKey(p)) {
return ImageCache.getIcon(avatarImages.get(p));
}
int avatarIdx = lp.getAvatarIndex();
int avatarIdx = p.getAvatarIndex();
return FSkin.getAvatars().get(avatarIdx >= 0 ? avatarIdx : defaultIndex);
}
@@ -108,7 +122,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
* @param numFieldPanels int
* @param numHandPanels int
*/
public void initMatch(final List<Player> players, LobbyPlayer localPlayer) {
public void initMatch(final List<PlayerView> players, LobbyPlayer localPlayer) {
view = VMatchUI.SINGLETON_INSTANCE;
// TODO fix for use with multiplayer
@@ -121,7 +135,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
final List<VCommand> commands = new ArrayList<VCommand>();
int i = 0;
for (Player p : sortedPlayers) {
for (final PlayerView p : sortedPlayers) {
// A field must be initialized after it's instantiated, to update player info.
// No player, no init.
VField f = new VField(EDocID.Fields[i], p, localPlayer);
@@ -130,7 +144,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
commands.add(c);
//setAvatar(f, new ImageIcon(FSkin.getAvatars().get()));
setAvatar(f, getPlayerAvatar(p, Integer.parseInt(indices[i > 2 ? 1 : 0])));
setAvatar(f, getPlayerAvatar(p.getLobbyPlayer(), Integer.parseInt(indices[i > 2 ? 1 : 0])));
f.getLayoutControl().initialize();
c.getLayoutControl().initialize();
i++;
@@ -149,7 +163,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
final List<VHand> hands = new ArrayList<VHand>();
int i = 0;
for (Player p : sortedPlayers) {
for (final PlayerView p : sortedPlayers) {
if (p.getLobbyPlayer() == localPlayer) {
VHand newHand = new VHand(EDocID.Hands[i], p);
newHand.getLayoutControl().initialize();
@@ -166,9 +180,9 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
view.setHandViews(hands);
}
private List<Player> shiftPlayersPlaceLocalFirst(final List<Player> players, LobbyPlayer localPlayer) {
private List<PlayerView> shiftPlayersPlaceLocalFirst(final List<PlayerView> players, final LobbyPlayer localPlayer) {
// get an arranged list so that the first local player is at index 0
List<Player> sortedPlayers = Lists.newArrayList(players);
final List<PlayerView> sortedPlayers = Lists.newArrayList(players);
int ixFirstHuman = -1;
for (int i = 0; i < players.size(); i++) {
if (sortedPlayers.get(i).getLobbyPlayer() == localPlayer) {
@@ -199,17 +213,17 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
CPrompt.SINGLETON_INSTANCE.setMessage(s0);
}
public VField getFieldViewFor(Player p) {
public VField getFieldViewFor(PlayerView p) {
int idx = getPlayerIndex(p);
return idx < 0 ? null :view.getFieldViews().get(idx);
}
public VCommand getCommandFor(Player p) {
public VCommand getCommandFor(PlayerView p) {
int idx = getPlayerIndex(p);
return idx < 0 ? null :view.getCommandViews().get(idx);
}
public VHand getHandFor(Player p) {
public VHand getHandFor(PlayerView p) {
int idx = getPlayerIndex(p);
List<VHand> allHands = view.getHands();
return idx < 0 || idx >= allHands.size() ? null : allHands.get(idx);
@@ -226,15 +240,15 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
* @param overrideOrder overriding combatant order
*/
@SuppressWarnings("unchecked")
public Map<Card, Integer> getDamageToAssign(final Card attacker, final List<Card> blockers, final int damage, final GameEntity defender, final boolean overrideOrder) {
public Map<CardView, Integer> getDamageToAssign(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
if (damage <= 0) {
return new HashMap<Card, Integer>();
return Maps.newHashMap();
}
// If the first blocker can absorb all of the damage, don't show the Assign Damage Frame
Card firstBlocker = blockers.get(0);
if (!overrideOrder && !attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) {
Map<Card, Integer> res = new HashMap<Card, Integer>();
final CardView firstBlocker = blockers.get(0);
if (!overrideOrder && !attacker.getState().hasDeathtouch() && firstBlocker.getLethalDamage() >= damage) {
final Map<CardView, Integer> res = Maps.newHashMap();
res.put(firstBlocker, damage);
return res;
}
@@ -246,7 +260,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender, overrideOrder);
result[0] = v.getDamageMap();
}});
return (Map<Card, Integer>)result[0];
return (Map<CardView, Integer>)result[0];
}
/**
@@ -257,20 +271,20 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
* @param phase &emsp; {@link java.lang.String}
* @return boolean
*/
public final boolean stopAtPhase(final Player turn, final PhaseType phase) {
public final boolean stopAtPhase(final PlayerView turn, final PhaseType phase) {
VField vf = getFieldViewFor(turn);
PhaseLabel label = vf.getPhaseIndicator().getLabelFor(phase);
return label == null || label.getEnabled();
}
public void setCard(final Card c) {
FThreads.assertExecutedByEdt(true);
setCard(c, false);
public void setCard(final CardView c) {
this.setCard(c, c.isInAltState());
}
public void setCard(final Card c, final boolean showFlipped) {
CDetail.SINGLETON_INSTANCE.showCard(c);
CPicture.SINGLETON_INSTANCE.showCard(c, showFlipped);
public void setCard(final CardView c, final boolean isInAltState) {
FThreads.assertExecutedByEdt(true);
CDetail.SINGLETON_INSTANCE.showCard(c, isInAltState);
CPicture.SINGLETON_INSTANCE.showCard(c, isInAltState);
}
public void setCard(final InventoryItem c) {
@@ -278,7 +292,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
CPicture.SINGLETON_INSTANCE.showImage(c);
}
private int getPlayerIndex(Player player) {
private int getPlayerIndex(PlayerView player) {
return sortedPlayers.indexOf(player);
}
@@ -305,19 +319,19 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
CCombat.SINGLETON_INSTANCE.update();
} // showBlockers()
Set<Player> highlightedPlayers = new HashSet<Player>();
public void setHighlighted(Player ge, boolean b) {
final Set<PlayerView> highlightedPlayers = Sets.newHashSet();
public void setHighlighted(PlayerView ge, boolean b) {
if (b) highlightedPlayers.add(ge);
else highlightedPlayers.remove(ge);
}
public boolean isHighlighted(Player player) {
public boolean isHighlighted(final PlayerView player) {
return highlightedPlayers.contains(player);
}
Set<Card> highlightedCards = new HashSet<Card>();
Set<CardView> highlightedCards = Sets.newHashSet();
// used to highlight cards in UI
public void setUsedToPay(Card card, boolean value) {
public void setUsedToPay(CardView card, boolean value) {
FThreads.assertExecutedByEdt(true);
boolean hasChanged = value ? highlightedCards.add(card) : highlightedCards.remove(card);
@@ -326,14 +340,14 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
}
}
public boolean isUsedToPay(Card card) {
public boolean isUsedToPay(CardView card) {
return highlightedCards.contains(card);
}
public void updateZones(List<Pair<Player, ZoneType>> zonesToUpdate) {
public void updateZones(List<Pair<PlayerView, ZoneType>> zonesToUpdate) {
//System.out.println("updateZones " + zonesToUpdate);
for (Pair<Player, ZoneType> kv : zonesToUpdate) {
Player owner = kv.getKey();
for (Pair<PlayerView, ZoneType> kv : zonesToUpdate) {
PlayerView owner = kv.getKey();
ZoneType zt = kv.getValue();
if (zt == ZoneType.Command) {
@@ -355,41 +369,39 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
}
// Player's mana pool changes
public void updateManaPool(List<Player> manaPoolUpdate) {
for (Player p : manaPoolUpdate) {
public void updateManaPool(final List<PlayerView> manaPoolUpdate) {
for (final PlayerView p : manaPoolUpdate) {
getFieldViewFor(p).getDetailsPanel().updateManaPool();
}
}
// Player's lives and poison counters
public void updateLives(List<Player> livesUpdate) {
for (Player p : livesUpdate) {
public void updateLives(final List<PlayerView> livesUpdate) {
for (final PlayerView p : livesUpdate) {
getFieldViewFor(p).updateDetails();
}
}
public void updateCards(Set<Card> cardsToUpdate) {
for (Card c : cardsToUpdate) {
public void updateCards(final Set<CardView> cardsToUpdate) {
for (final CardView c : cardsToUpdate) {
updateSingleCard(c);
}
}
public void updateSingleCard(Card c) {
Zone zone = c.getZone();
if (zone != null && zone.getZoneType() == ZoneType.Battlefield) {
PlayArea pa = getFieldViewFor(zone.getPlayer()).getTabletop();
public void updateSingleCard(final CardView c) {
if (ZoneType.Battlefield.equals(c.getZone())) {
final PlayArea pa = getFieldViewFor(c.getController()).getTabletop();
pa.updateCard(c, false);
}
}
public void refreshCardDetails(Collection<Card> cards) {
for (Card c : cards) {
Zone zone = c.getZone();
if (zone != null && zone.getZoneType() == ZoneType.Battlefield) {
PlayArea pa = getFieldViewFor(zone.getPlayer()).getTabletop();
CardPanel pnl = pa.getCardPanel(c.getUniqueNumber());
public void refreshCardDetails(final Iterable<CardView> cards) {
for (final CardView c : cards) {
if (ZoneType.Battlefield.equals(c.getZone())) {
PlayArea pa = getFieldViewFor(c.getController()).getTabletop();
CardPanel pnl = pa.getCardPanel(c.getId());
if (pnl != null) {
pnl.updatePTOverlay();
}

View File

@@ -1,15 +1,15 @@
package forge.screens.match;
import forge.Singletons;
import forge.game.Game;
import forge.game.Match;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import forge.Singletons;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.view.IGameView;
/**
* Default controller for a ViewWinLose object. This class can
* be extended for various game modes to populate the custom
@@ -18,13 +18,13 @@ import java.awt.event.ActionListener;
*/
public class ControlWinLose {
private final ViewWinLose view;
protected final Game lastGame;
protected final IGameView lastGame;
/** @param v &emsp; ViewWinLose
* @param match */
public ControlWinLose(final ViewWinLose v, Game game) {
public ControlWinLose(final ViewWinLose v, final IGameView game0) {
this.view = v;
this.lastGame = game;
this.lastGame = game0;
addListeners();
}
@@ -59,17 +59,15 @@ public class ControlWinLose {
saveOptions();
Singletons.getControl().endCurrentGame();
Singletons.getControl().startGameWithUi(lastGame.getMatch());
Singletons.getControl().startGameInSameMatch();
}
/** Action performed when "restart" button is pressed in default win/lose UI. */
public void actionOnRestart() {
SOverlayUtils.hideOverlay();
saveOptions();
final Match match = lastGame.getMatch();
match.clearGamesPlayed();
Singletons.getControl().endCurrentGame();
Singletons.getControl().startGameWithUi(match);
Singletons.getControl().startGameAndClearMatch();
}
/** Action performed when "quit" button is pressed in default win/lose UI. */

View File

@@ -17,18 +17,20 @@ package forge.screens.match;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.awt.Color;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import forge.assets.FSkinProp;
import forge.game.Game;
import forge.gauntlet.GauntletWinLoseController;
import forge.toolbox.FLabel;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import forge.view.IGameView;
/**
* The Win/Lose handler for 'gauntlet' type tournament
@@ -43,9 +45,9 @@ public class GauntletWinLose extends ControlWinLose {
* @param view0 ViewWinLose object
* @param match
*/
public GauntletWinLose(final ViewWinLose view0, Game lastGame) {
super(view0, lastGame);
controller = new GauntletWinLoseController(view0, lastGame) {
public GauntletWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
controller = new GauntletWinLoseController(view0, game0) {
@Override
protected void showOutcome(String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num) {
final JLabel lblTitle = new FLabel.Builder().text("Gauntlet Progress")

View File

@@ -21,12 +21,12 @@ import java.awt.Dimension;
import javax.swing.SwingConstants;
import forge.game.Game;
import forge.limited.LimitedWinLoseController;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.Colors;
import forge.toolbox.FSkin.SkinColor;
import forge.toolbox.FSkin.SkinnedLabel;
import forge.view.IGameView;
/**
* The Win/Lose handler for 'gauntlet' type tournament
@@ -46,9 +46,9 @@ public class LimitedWinLose extends ControlWinLose {
* @param view0 {@link forge.screens.match.ViewWinLose}
* @param match {@link forge.game.Match}
*/
public LimitedWinLose(final ViewWinLose view0, Game lastGame) {
super(view0, lastGame);
controller = new LimitedWinLoseController(view0, lastGame) {
public LimitedWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
controller = new LimitedWinLoseController(view0, game0) {
@Override
protected void showOutcome(Runnable runnable) {
runnable.run(); //just run on GUI thread

View File

@@ -24,8 +24,6 @@ import forge.GuiBase;
import forge.LobbyPlayer;
import forge.Singletons;
import forge.assets.FSkinProp;
import forge.game.Game;
import forge.game.player.Player;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.model.FModel;
@@ -37,6 +35,8 @@ import forge.screens.home.quest.CSubmenuQuestDraft;
import forge.screens.home.quest.VSubmenuQuestDraft;
import forge.toolbox.FOptionPane;
import forge.toolbox.FSkin;
import forge.view.IGameView;
import forge.view.PlayerView;
/**
* <p>
@@ -58,8 +58,8 @@ public class QuestDraftWinLose extends ControlWinLose {
* @param view0 ViewWinLose object
* @param match2
*/
public QuestDraftWinLose(final ViewWinLose view0, Game lastGame) {
super(view0, lastGame);
public QuestDraftWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
this.view = view0;
qData = FModel.getQuest();
}
@@ -79,18 +79,18 @@ public class QuestDraftWinLose extends ControlWinLose {
QuestController quest = FModel.getQuest();
final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer();
List<Player> players = lastGame.getRegisteredPlayers();
final List<PlayerView> players = lastGame.getPlayers();
boolean gameHadHumanPlayer = false;
for (Player p : players) {
for (final PlayerView p : players) {
if (p.getLobbyPlayer().equals(questLobbyPlayer)) {
gameHadHumanPlayer = true;
break;
}
}
if (lastGame.getMatch().isMatchOver()) {
if (lastGame.isMatchOver()) {
String winner = lastGame.getOutcome().getWinningPlayer().getName();
String winner = lastGame.getWinningPlayer().getName();
quest.getAchievements().getCurrentDraft().setWinner(winner);
quest.save();
@@ -99,7 +99,7 @@ public class QuestDraftWinLose extends ControlWinLose {
if (!gameHadHumanPlayer) {
if (lastGame.getMatch().isMatchOver()) {
if (lastGame.isMatchOver()) {
this.actionOnQuitMatch();
QuestDraftUtils.matchInProgress = false;
QuestDraftUtils.update();
@@ -114,7 +114,7 @@ public class QuestDraftWinLose extends ControlWinLose {
view.getBtnRestart().setEnabled(false);
view.getBtnRestart().setVisible(false);
if (lastGame.getMatch().isMatchOver()) {
if (lastGame.isMatchOver()) {
view.getBtnQuit().setEnabled(true);
view.getBtnContinue().setEnabled(false);
view.getBtnQuit().setText("Continue Tournament");

View File

@@ -16,12 +16,16 @@
*/
package forge.screens.match;
import java.awt.Dimension;
import java.util.List;
import javax.swing.SwingConstants;
import forge.assets.FSkinProp;
import forge.game.Game;
import forge.item.*;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.*;
import forge.quest.QuestWinLoseController;
import forge.screens.home.quest.CSubmenuChallenges;
import forge.screens.home.quest.CSubmenuDuels;
import forge.toolbox.FSkin;
@@ -29,11 +33,7 @@ import forge.toolbox.FSkin.Colors;
import forge.toolbox.FSkin.SkinColor;
import forge.toolbox.FSkin.SkinIcon;
import forge.toolbox.FSkin.SkinnedLabel;
import java.awt.Dimension;
import java.util.List;
import javax.swing.SwingConstants;
import forge.view.IGameView;
/**
* <p>
@@ -61,10 +61,10 @@ public class QuestWinLose extends ControlWinLose {
* @param view0 ViewWinLose object
* @param match2
*/
public QuestWinLose(final ViewWinLose view0, Game lastGame) {
super(view0, lastGame);
public QuestWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
view = view0;
controller = new QuestWinLoseController(lastGame) {
controller = new QuestWinLoseController(game0) {
@Override
protected void showRewards(Runnable runnable) {
runnable.run(); //just run on GUI thread

View File

@@ -63,7 +63,7 @@ public class QuestWinLoseCardViewer extends FPanel {
public QuestWinLoseCardViewer(final List<PaperCard> list) {
this.list = Collections.unmodifiableList(list);
this.jList = new FList<PaperCard>(new ChooserListModel());
this.detail = new CardDetailPanel(null);
this.detail = new CardDetailPanel();
this.picture = new CardPicturePanel();
this.scroller = new FScrollPane(this.jList, false);

View File

@@ -17,6 +17,7 @@
*/
package forge.screens.match;
import forge.control.FControl;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CounterType;
@@ -27,13 +28,20 @@ import forge.toolbox.FLabel;
import forge.toolbox.FScrollPane;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.view.CardView;
import forge.view.FDialog;
import forge.view.GameEntityView;
import forge.view.PlayerView;
import forge.view.arcane.CardPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.border.Border;
import org.testng.collections.Lists;
import com.google.common.collect.Maps;
import java.awt.Dialog.ModalityType;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -68,7 +76,7 @@ public class VAssignDamage {
private boolean attackerHasInfect = false;
private boolean overrideCombatantOrder = false;
private final GameEntity defender;
private final GameEntityView defender;
private final JLabel lblTotalDamage = new FLabel.Builder().text("Available damage points: Unknown").build();
private final JLabel lblAssignRemaining = new FLabel.Builder().text("Distribute the remaining damage points among lethally wounded entities").build();
@@ -79,24 +87,24 @@ public class VAssignDamage {
private static class DamageTarget {
public final Card card;
public final CardView card;
public final JLabel label;
public int damage;
public DamageTarget(Card entity0, JLabel lbl) {
card = entity0;
public DamageTarget(final CardView c, final JLabel lbl) {
card = c;
label = lbl;
}
}
// Indexes of defenders correspond to their indexes in the damage list and labels.
private final List<DamageTarget> defenders = new ArrayList<DamageTarget>(); // NULL in this map means defender
private final Map<Card, DamageTarget> damage = new HashMap<Card, DamageTarget>(); // NULL in this map means defender
private final List<DamageTarget> defenders = Lists.newArrayList(); // NULL in this map means defender
private final Map<CardView, DamageTarget> damage = Maps.newHashMap(); // NULL in this map means defender
private boolean canAssignTo(Card card) {
for(DamageTarget dt : defenders) {
if ( dt.card == card ) return true;
if ( getDamageToKill(dt.card) > dt.damage )
private boolean canAssignTo(final CardView card) {
for (DamageTarget dt : defenders) {
if (dt.card == card ) return true;
if (getDamageToKill(dt.card) > dt.damage )
return false;
}
throw new RuntimeException("Asking to assign damage to object which is not present in defenders list");
@@ -106,10 +114,10 @@ public class VAssignDamage {
private final MouseAdapter mad = new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent evt) {
Card source = ((CardPanel) evt.getSource()).getCard();
CardView source = ((CardPanel) evt.getSource()).getCard();
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
final FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
((CardPanel) evt.getSource()).setBorder(new FSkin.LineSkinBorder(FSkin.getColor(brdrColor), 2));
}
@@ -120,7 +128,7 @@ public class VAssignDamage {
@Override
public void mousePressed(final MouseEvent evt) {
Card source = ((CardPanel) evt.getSource()).getCard(); // will be NULL for player
CardView source = ((CardPanel) evt.getSource()).getCard(); // will be NULL for player
boolean meta = evt.isControlDown();
boolean isLMB = SwingUtilities.isLeftMouseButton(evt);
@@ -133,22 +141,22 @@ public class VAssignDamage {
/** Constructor.
*
* @param attacker0 {@link forge.game.card.Card}
* @param defenderCards List<{@link forge.game.card.Card}>
* @param attacker {@link forge.game.card.Card}
* @param blockers List<{@link forge.game.card.Card}>
* @param damage0 int
* @param defender GameEntity that's bein attacked
* @param overrideOrder override combatant order
*/
public VAssignDamage(final Card attacker0, final List<Card> defenderCards, final int damage0, final GameEntity defender, boolean overrideOrder) {
dlg.setTitle("Assign damage dealt by " + attacker0.getName());
public VAssignDamage(final CardView attacker, final List<CardView> blockers, final int damage0, final GameEntityView defender, boolean overrideOrder) {
dlg.setTitle("Assign damage dealt by " + attacker);
// Set damage storage vars
this.totalDamageToAssign = damage0;
this.defender = defender;
this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch");
this.attackerHasInfect = attacker0.hasKeyword("Infect");
this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample");
this.attackerHasDeathtouch = attacker.getState().hasDeathtouch();
this.attackerHasInfect = attacker.getState().hasInfect();
this.attackerHasTrample = defender != null && attacker.getState().hasTrample();
this.overrideCombatantOrder = overrideOrder;
// Top-level UI stuff
@@ -157,7 +165,7 @@ public class VAssignDamage {
pnlMain.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
// Attacker area
final CardPanel pnlAttacker = new CardPanel(attacker0);
final CardPanel pnlAttacker = new CardPanel(attacker);
pnlAttacker.setOpaque(false);
pnlAttacker.setCardBounds(0, 0, 105, 150);
@@ -170,14 +178,14 @@ public class VAssignDamage {
// Defenders area
final JPanel pnlDefenders = new JPanel();
pnlDefenders.setOpaque(false);
int cols = attackerHasTrample ? defenderCards.size() + 1 : defenderCards.size();
int cols = attackerHasTrample ? blockers.size() + 1 : blockers.size();
final String wrap = "wrap " + Integer.toString(cols);
pnlDefenders.setLayout(new MigLayout("insets 0, gap 0, ax center, " + wrap));
final FScrollPane scrDefenders = new FScrollPane(pnlDefenders, false);
// Top row of cards...
for (final Card c : defenderCards) {
for (final CardView c : blockers) {
DamageTarget dt = new DamageTarget(c, new FLabel.Builder().text("0").fontSize(18).fontAlign(SwingConstants.CENTER).build());
this.damage.put(c, dt);
this.defenders.add(dt);
@@ -188,18 +196,18 @@ public class VAssignDamage {
DamageTarget dt = new DamageTarget(null, new FLabel.Builder().text("0").fontSize(18).fontAlign(SwingConstants.CENTER).build());
this.damage.put(null, dt);
this.defenders.add(dt);
Card fakeCard;
if (defender instanceof Card)
fakeCard = (Card)defender;
else if (defender instanceof Player) {
fakeCard = new Card(-1);
fakeCard.setName(this.defender.getName());
fakeCard.setOwner((Player)defender);
Player p = (Player)defender;
fakeCard.setImageKey(CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getOriginalLobbyPlayer()));
final CardView fakeCard;
if (defender instanceof CardView)
fakeCard = (CardView)defender;
else if (defender instanceof PlayerView) {
fakeCard = new CardView(null, -1);
fakeCard.getState().setName(this.defender.toString());
final PlayerView p = (PlayerView)defender;
fakeCard.getState().setOwner(p);
fakeCard.getState().setImageKey(CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getLobbyPlayer()));
} else {
fakeCard = new Card(-2);
fakeCard.setName(this.defender.getName());
fakeCard = new CardView(null, -2);
fakeCard.getState().setName(this.defender.toString());
}
addPanelForDefender(pnlDefenders, fakeCard);
}
@@ -259,7 +267,7 @@ public class VAssignDamage {
* @param pnlDefenders
* @param defender
*/
private void addPanelForDefender(final JPanel pnlDefenders, final Card defender) {
private void addPanelForDefender(final JPanel pnlDefenders, final CardView defender) {
final CardPanel cp = new CardPanel(defender);
cp.setCardBounds(0, 0, 105, 150);
cp.setOpaque(true);
@@ -273,7 +281,7 @@ public class VAssignDamage {
* @param meta
* @param isLMB
*/
private void assignDamageTo(Card source, boolean meta, boolean isAdding) {
private void assignDamageTo(CardView source, final boolean meta, final boolean isAdding) {
if ( !damage.containsKey(source) )
source = null;
@@ -366,14 +374,14 @@ public class VAssignDamage {
dt.damage = 0;
}
private void addDamage(final Card card, int addedDamage) {
private void addDamage(final CardView card, int addedDamage) {
// If we don't have enough left or we're trying to unassign too much return
int canAssign = getRemainingDamage();
final int canAssign = getRemainingDamage();
if (canAssign < addedDamage) {
addedDamage = canAssign;
}
DamageTarget dt = damage.get(card);
final DamageTarget dt = damage.get(card);
dt.damage = Math.max(0, addedDamage + dt.damage);
}
@@ -433,28 +441,28 @@ public class VAssignDamage {
/**
* TODO: Write javadoc for this method.
* @param source
* @param card
* @return
*/
private int getDamageToKill(Card source) {
private int getDamageToKill(final CardView card) {
int lethalDamage = 0;
if ( source == null ) {
if ( defender instanceof Player ) {
Player p = (Player)defender;
lethalDamage = attackerHasInfect ? p.getGame().getRules().getPoisonCountersToLose() - p.getPoisonCounters() : p.getLife();
} else if ( defender instanceof Card ) { // planeswalker
Card pw = (Card)defender;
lethalDamage = pw.getCounters(CounterType.LOYALTY);
if (card == null) {
if (defender instanceof PlayerView) {
final PlayerView p = (PlayerView)defender;
lethalDamage = attackerHasInfect ? FControl.instance.getGameView().getPoisonCountersToLose() - p.getPoisonCounters() : p.getLife();
} else if (defender instanceof CardView) { // planeswalker
final CardView pw = (CardView)defender;
lethalDamage = pw.getState().getLoyalty();
}
} else {
lethalDamage = VAssignDamage.this.attackerHasDeathtouch ? 1 : Math.max(0, source.getLethalDamage());
lethalDamage = VAssignDamage.this.attackerHasDeathtouch ? 1 : Math.max(0, card.getLethalDamage());
}
return lethalDamage;
}
public Map<Card, Integer> getDamageMap() {
Map<Card, Integer> result = new HashMap<Card, Integer>();
for(DamageTarget dt : defenders)
public Map<CardView, Integer> getDamageMap() {
Map<CardView, Integer> result = Maps.newHashMapWithExpectedSize(defenders.size());
for (DamageTarget dt : defenders)
result.put(dt.card, dt.damage);
return result;
}

View File

@@ -10,14 +10,14 @@ import javax.swing.event.ChangeListener;
import forge.Singletons;
import forge.UiCommand;
import forge.game.Game;
import forge.game.player.Player;
import forge.toolbox.FButton;
import forge.toolbox.FCheckBox;
import forge.toolbox.FList;
import forge.toolbox.FOptionPane;
import forge.toolbox.FScrollPane;
import forge.view.FDialog;
import forge.view.IGameView;
import forge.view.PlayerView;
@SuppressWarnings("serial")
public class VAutoYields extends FDialog {
@@ -32,12 +32,12 @@ public class VAutoYields extends FDialog {
private final FCheckBox chkDisableAll;
private final List<String> autoYields;
public VAutoYields(final Game game, final Player player) {
public VAutoYields(final IGameView game, final PlayerView playerView) {
super(true);
setTitle("Auto-Yields");
autoYields = new ArrayList<String>();
for (String autoYield : player.getController().getAutoYields()) {
for (final String autoYield : playerView.getController().getAutoYields()) {
autoYields.add(autoYield);
}
lstAutoYields = new FList<String>(new AutoYieldsListModel());
@@ -72,7 +72,7 @@ public class VAutoYields extends FDialog {
if (selected != null) {
autoYields.remove(selected);
btnRemove.setEnabled(autoYields.size() > 0);
player.getController().setShouldAutoYield(selected, false);
playerView.getController().setShouldAutoYield(selected, false);
VAutoYields.this.revalidate();
lstAutoYields.repaint();
}

View File

@@ -11,13 +11,11 @@ import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import forge.LobbyPlayer;
import forge.UiCommand;
import forge.game.Game;
import forge.game.GameLog;
import forge.game.GameLogEntry;
import forge.game.GameLogEntryType;
import forge.game.GameOutcome;
import forge.game.player.Player;
import forge.gui.SOverlayUtils;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
@@ -29,7 +27,7 @@ import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedLabel;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.toolbox.FTextArea;
import forge.view.IGameView;
public class ViewWinLose implements IWinLoseView<FButton> {
private final FButton btnContinue, btnRestart, btnQuit;
@@ -39,12 +37,12 @@ public class ViewWinLose implements IWinLoseView<FButton> {
private final SkinnedLabel lblStats = new SkinnedLabel("WinLoseFrame > lblStats needs updating.");
private final JPanel pnlOutcomes = new JPanel(new MigLayout("wrap, align center"));
private final Game game;
private final IGameView game;
@SuppressWarnings("serial")
public ViewWinLose(final Game game0) {
public ViewWinLose(final IGameView game0) {
game = game0;
this.game = game0;
final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
@@ -60,7 +58,7 @@ public class ViewWinLose implements IWinLoseView<FButton> {
// Control of the win/lose is handled differently for various game
// modes.
ControlWinLose control = null;
switch (game0.getRules().getGameType()) {
switch (game0.getGameType()) {
case Quest:
control = new QuestWinLose(this, game0);
break;
@@ -103,7 +101,7 @@ public class ViewWinLose implements IWinLoseView<FButton> {
btnRestart.setFont(FSkin.getFont(22));
btnQuit.setText("Quit Match");
btnQuit.setFont(FSkin.getFont(22));
btnContinue.setEnabled(!game0.getMatch().isMatchOver());
btnContinue.setEnabled(!game0.isMatchOver());
// Assemble game log scroller.
final FTextArea txtLog = new FTextArea();
@@ -180,20 +178,20 @@ public class ViewWinLose implements IWinLoseView<FButton> {
}
});
lblTitle.setText(composeTitle(game0.getOutcome()));
lblTitle.setText(composeTitle(game0));
showGameOutcomeSummary();
showPlayerScores();
}
private String composeTitle(GameOutcome outcome) {
Player winner = outcome.getWinningPlayer();
int winningTeam = outcome.getWinningTeam();
private String composeTitle(final IGameView game) {
final LobbyPlayer winner = game.getWinningPlayer();
final int winningTeam = game.getWinningTeam();
if (winner == null) {
return "It's a draw!";
} else if (winningTeam != -1) {
return "Team " + winner.getTeam() + " Won!";
return "Team " + winningTeam + " Won!";
} else {
return winner.getName() + " Won!";
}

View File

@@ -1,17 +1,16 @@
package forge.screens.match;
import forge.Singletons;
import forge.card.CardCharacteristicName;
import forge.game.card.Card;
import forge.game.card.CardFactory;
import forge.game.zone.PlayerZone;
import java.awt.event.ActionEvent;
import java.util.List;
import com.beust.jcommander.internal.Lists;
import com.google.common.collect.Iterables;
import forge.gui.ForgeAction;
import forge.gui.GuiChoose;
import forge.match.MatchConstants;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
/**
* Receives click and programmatic requests for viewing data stacks in the
@@ -20,7 +19,7 @@ import java.util.List;
*/
public class ZoneAction extends ForgeAction {
private static final long serialVersionUID = -5822976087772388839L;
private final PlayerZone zone;
private final Iterable<CardView> cards;
private final String title;
/**
@@ -33,10 +32,10 @@ public class ZoneAction extends ForgeAction {
* @param property
* &emsp; String obj
*/
public ZoneAction(final PlayerZone zone, MatchConstants property) {
public ZoneAction(final Iterable<CardView> cards, final MatchConstants property) {
super(property);
this.title = property.title;
this.zone = zone;
this.cards = Iterables.unmodifiableIterable(cards);
}
/**
@@ -45,37 +44,33 @@ public class ZoneAction extends ForgeAction {
*/
@Override
public void actionPerformed(final ActionEvent e) {
final List<Card> choices = this.getCardsAsIterable();
if (choices.isEmpty()) {
final Iterable<CardView> choices = this.getCardsAsIterable();
if (!choices.iterator().hasNext()) {
GuiChoose.reveal(this.title, "no cards");
return;
}
final ArrayList<Card> choices2 = new ArrayList<Card>();
for (Card crd : choices) {
Card toAdd = crd;
if (crd.isFaceDown()) {
if (Singletons.getControl().mayShowCard(crd)) {
toAdd = CardFactory.copyCard(crd, false);
toAdd.setState(CardCharacteristicName.Original);
} else {
toAdd = new Card(0);
toAdd.setName("Face Down");
}
}
final List<CardStateView> choices2 = Lists.newLinkedList();
for (final CardView crd : choices) {
final CardStateView toAdd;
if (crd.isFaceDown() && crd.hasAltState()) {
toAdd = crd.getAlternate();
} else {
toAdd = crd.getState();
}
choices2.add(toAdd);
}
final Card choice = GuiChoose.oneOrNone(this.title, choices2);
final CardStateView choice = GuiChoose.oneOrNone(this.title, choices2);
if (choice != null) {
this.doAction(choice);
this.doAction(choice.getCard());
}
}
protected List<Card> getCardsAsIterable() {
return this.zone.getCards();
protected Iterable<CardView> getCardsAsIterable() {
return cards;
}
protected void doAction(final Card c) {
protected void doAction(final CardView c) {
}
} // End ZoneAction

View File

@@ -18,24 +18,25 @@
package forge.screens.match.controllers;
import forge.UiCommand;
import forge.game.player.Player;
import forge.gui.framework.ICDoc;
import forge.screens.match.views.VCommand;
import forge.view.PlayerView;
/**
* Controls Swing components of a player's command instance.
*/
public class CCommand implements ICDoc {
private final Player player;
private final PlayerView player;
private final VCommand view;
/**
* Controls Swing components of a player's command instance.
*
* @param p0 &emsp; {@link forge.game.player.Player}
* @param player2 &emsp; {@link forge.game.player.Player}
* @param v0 &emsp; {@link forge.screens.match.views.VCommand}
*/
public CCommand(final Player p0, final VCommand v0) {
this.player = p0;
public CCommand(final PlayerView player2, final VCommand v0) {
this.player = player2;
this.view = v0;
}
@@ -48,7 +49,7 @@ public class CCommand implements ICDoc {
}
/** @return {@link forge.game.player.Player} */
public Player getPlayer() {
public PlayerView getPlayer() {
return this.player;
}

View File

@@ -27,6 +27,7 @@ import forge.item.InventoryItem;
import forge.item.InventoryItemFromSet;
import forge.screens.match.views.VDetail;
import forge.toolbox.FMouseAdapter;
import forge.view.CardView;
import java.awt.event.MouseEvent;
@@ -45,6 +46,7 @@ public enum CDetail implements ICDoc {
*
* @param c &emsp; Card object
*/
@Deprecated
public void showCard(Card c) {
if (c != null) {
c = c.getCardForUi();
@@ -56,7 +58,15 @@ public enum CDetail implements ICDoc {
}
}
public void showCard(InventoryItem item) {
public void showCard(final CardView c, final boolean isInAltState) {
view.getLblFlipcard().setVisible(c != null && c.hasAltState() && Singletons.getControl().mayShowCard(c));
view.getPnlDetail().setCard(c, isInAltState);
if (view.getParentCell() != null) {
view.getParentCell().repaintSelf();
}
}
public void showCard(final InventoryItem item) {
if (item instanceof IPaperCard) {
showCard(Card.getCardForUi((IPaperCard)item));
}

View File

@@ -17,19 +17,18 @@
*/
package forge.screens.match.controllers;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.UiCommand;
import forge.FThreads;
import forge.Singletons;
import forge.assets.FSkinProp;
import forge.deckchooser.FDeckViewer;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
@@ -38,7 +37,6 @@ import forge.gui.SOverlayUtils;
import forge.gui.framework.ICDoc;
import forge.gui.framework.SLayoutIO;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.properties.FileLocation;
import forge.properties.ForgePreferences.FPref;
import forge.screens.match.CMatchUI;
@@ -47,6 +45,7 @@ import forge.toolbox.FSkin;
import forge.toolbox.SaveOpenDialog;
import forge.toolbox.SaveOpenDialog.Filetypes;
import forge.view.FView;
import forge.view.IGameView;
import java.io.File;
import java.util.List;
@@ -61,9 +60,9 @@ public enum CDock implements ICDoc {
SINGLETON_INSTANCE;
private int arcState;
private Game game;
private IGameView game;
public void setModel(Game game0, LobbyPlayer player0) {
public void setModel(IGameView game0, LobbyPlayer player0) {
game = game0;
}
@@ -136,7 +135,8 @@ public enum CDock implements ICDoc {
* View deck list.
*/
public void viewDeckList() {
RegisteredPlayer player = GamePlayerUtil.getGuiRegisteredPlayer(game);
final LobbyPlayer guiPlayer = GuiBase.getInterface().getGuiPlayer();
final RegisteredPlayer player = game.getGuiRegisteredPlayer(guiPlayer);
if (player != null) {
FDeckViewer.show(player.getDeck());
}
@@ -178,12 +178,9 @@ public enum CDock implements ICDoc {
/** Attack with everyone. */
public void alphaStrike() {
final PhaseHandler ph = game.getPhaseHandler();
final Player p = findAffectedPlayer();
final Game game = p.getGame();
Combat combat = game.getCombat();
if (ph.is(PhaseType.COMBAT_DECLARE_ATTACKERS, p) && combat!= null) { // ph.is(...) includes null check
final Player p = this.findAffectedPlayer();
final Combat combat = game.getCombat();
if (this.game.isCombatDeclareAttackers()) {
List<Player> defenders = p.getOpponents();
for (Card c : CardLists.filter(p.getCardsIn(ZoneType.Battlefield), Presets.CREATURES)) {

View File

@@ -17,14 +17,17 @@
*/
package forge.screens.match.controllers;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import com.google.common.base.Function;
import forge.LobbyPlayer;
import forge.UiCommand;
import forge.Singletons;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.UiCommand;
import forge.gui.framework.ICDoc;
import forge.match.MatchConstants;
import forge.match.input.Input;
@@ -33,19 +36,15 @@ import forge.properties.ForgePreferences;
import forge.screens.match.ZoneAction;
import forge.screens.match.views.VField;
import forge.toolbox.MouseTriggerEvent;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import forge.view.CardView;
import forge.view.PlayerView;
/**
* Controls Swing components of a player's field instance.
*/
public class CField implements ICDoc {
// The one who owns cards on this side of table
private final Player player;
private final PlayerView player;
// Tho one who looks at screen and 'performs actions'
private final LobbyPlayer viewer;
private final VField view;
@@ -61,42 +60,44 @@ public class CField implements ICDoc {
/**
* Controls Swing components of a player's field instance.
*
* @param p0 &emsp; {@link forge.game.player.Player}
* @param player2 &emsp; {@link forge.game.player.Player}
* @param v0 &emsp; {@link forge.screens.match.views.VField}
* @param playerViewer
*/
@SuppressWarnings("serial")
public CField(final Player p0, final VField v0, LobbyPlayer playerViewer) {
this.player = p0;
public CField(final PlayerView player2, final VField v0, LobbyPlayer playerViewer) {
this.player = player2;
this.viewer = playerViewer;
this.view = v0;
ZoneAction handAction = new ZoneAction(player.getZone(ZoneType.Hand), MatchConstants.HUMANHAND) {
final ZoneAction handAction = new ZoneAction(player.getHandCards(), MatchConstants.HUMANHAND) {
@Override
public void actionPerformed(ActionEvent e) {
if ( player.getLobbyPlayer() == viewer || ForgePreferences.DEV_MODE || player.hasKeyword("Play with your hand revealed."))
if (player.getLobbyPlayer() == viewer || ForgePreferences.DEV_MODE) {// || player.hasKeyword("Play with your hand revealed."))
super.actionPerformed(e);
}
}
};
ZoneAction libraryAction = new ZoneAction(player.getZone(ZoneType.Library), MatchConstants.HUMANLIBRARY) {
final ZoneAction libraryAction = new ZoneAction(player.getLibraryCards(), MatchConstants.HUMANLIBRARY) {
@Override
public void actionPerformed(ActionEvent e) {
if (ForgePreferences.DEV_MODE)
if (ForgePreferences.DEV_MODE) {
super.actionPerformed(e);
}
}
};
ZoneAction exileAction = new ZoneAction(player.getZone(ZoneType.Exile), MatchConstants.HUMANEXILED);
ZoneAction graveAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANGRAVEYARD);
ZoneAction flashBackAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANFLASHBACK) {
final ZoneAction exileAction = new ZoneAction(player.getExileCards(), MatchConstants.HUMANEXILED);
final ZoneAction graveAction = new ZoneAction(player.getGraveCards(), MatchConstants.HUMANGRAVEYARD);
final ZoneAction flashBackAction = new ZoneAction(player.getFlashbackCards(), MatchConstants.HUMANFLASHBACK) {
@Override
protected List<Card> getCardsAsIterable() {
return player.getCardsActivableInExternalZones(true);
protected List<CardView> getCardsAsIterable() {
return player.getFlashbackCards();
}
@Override
protected void doAction(final Card c) {
protected void doAction(final CardView c) {
// activate cards only via your own flashback button
if (player.getLobbyPlayer() != CField.this.viewer) {
return;
@@ -157,16 +158,6 @@ public class CField implements ICDoc {
public void update() {
}
/** @return {@link forge.game.player.Player} */
public Player getPlayer() {
return this.player;
}
/** @return {@link forge.screens.match.views.VField} */
public VField getView() {
return this.view;
}
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
*/

View File

@@ -17,35 +17,36 @@
*/
package forge.screens.match.controllers;
import forge.UiCommand;
import forge.FThreads;
import forge.Singletons;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.framework.ICDoc;
import forge.screens.match.CMatchUI;
import forge.screens.match.views.VField;
import forge.screens.match.views.VHand;
import forge.view.arcane.CardPanel;
import forge.view.arcane.HandArea;
import forge.view.arcane.util.Animation;
import forge.view.arcane.util.CardPanelMouseAdapter;
import javax.swing.*;
import java.awt.*;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
import forge.FThreads;
import forge.Singletons;
import forge.UiCommand;
import forge.gui.framework.ICDoc;
import forge.screens.match.CMatchUI;
import forge.screens.match.views.VField;
import forge.screens.match.views.VHand;
import forge.view.CardView;
import forge.view.PlayerView;
import forge.view.arcane.CardPanel;
import forge.view.arcane.HandArea;
import forge.view.arcane.util.Animation;
import forge.view.arcane.util.CardPanelMouseAdapter;
/**
* Controls Swing components of a player's hand instance.
*
*/
public class CHand implements ICDoc {
private final Player player;
private final PlayerView player;
private final VHand view;
private boolean initializedAlready = false;
@@ -55,15 +56,15 @@ public class CHand implements ICDoc {
* @param p0 &emsp; {@link forge.game.player.Player}
* @param v0 &emsp; {@link forge.screens.match.views.VHand}
*/
public CHand(final Player p0, final VHand v0) {
public CHand(final PlayerView p0, final VHand v0) {
this.player = p0;
this.view = v0;
v0.getHandArea().addCardPanelMouseListener(new CardPanelMouseAdapter() {
@Override
public void mouseDragEnd(CardPanel dragPanel, MouseEvent evt) {
//update index of dragged card in hand zone to match new index within hand area
int index = CHand.this.view.getHandArea().getCardPanels().indexOf(dragPanel);
CHand.this.player.getZone(ZoneType.Hand).reposition(dragPanel.getCard(), index);
//int index = CHand.this.view.getHandArea().getCardPanels().indexOf(dragPanel);
//CHand.this.player.getZone(ZoneType.Hand).reposition(dragPanel.getCard(), index);
}
});
}
@@ -103,12 +104,12 @@ public class CHand implements ICDoc {
}
//update card panels in hand area
final List<Card> cards = player.getZone(ZoneType.Hand).getCards();
final List<CardView> cards = player.getHandCards();
final List<CardPanel> placeholders = new ArrayList<CardPanel>();
final List<CardPanel> cardPanels = new ArrayList<CardPanel>();
for (Card card : cards) {
CardPanel cardPanel = p.getCardPanel(card.getUniqueNumber());
for (final CardView card : cards) {
CardPanel cardPanel = p.getCardPanel(card.getId());
if (cardPanel == null) { //create placeholders for new cards
cardPanel = new CardPanel(card);
cardPanel.setDisplayEnabled(false);

View File

@@ -29,6 +29,7 @@ import forge.item.InventoryItem;
import forge.screens.match.views.VPicture;
import forge.toolbox.FMouseAdapter;
import forge.toolbox.special.CardZoomer;
import forge.view.CardView;
import forge.view.FDialog;
import javax.swing.*;
@@ -57,9 +58,14 @@ public enum CPicture implements ICDoc {
private final JLabel flipIndicator = this.view.getLblFlipcard();
private final CardZoomer zoomer = CardZoomer.SINGLETON_INSTANCE;
@Deprecated
private Card currentCard = null;
@Deprecated
private CardCharacteristicName displayedState = CardCharacteristicName.Original;
private CardView currentView = null;
private boolean isDisplayAlt = false;
private boolean mayShowCurrentCard() {
if (currentCard == null) { return false; }
if (FDialog.isModalOpen()) { return true; } //allow showing cards while modal open to account for revealing, picking, and ordering cards
@@ -70,8 +76,9 @@ public enum CPicture implements ICDoc {
* Shows card details and/or picture in sidebar cardview tabber.
*
*/
@Deprecated
public void showCard(Card c, boolean showFlipped) {
if (c == null) {
if (null == c) {
return;
}
@@ -86,6 +93,24 @@ public enum CPicture implements ICDoc {
}
}
/**
* Shows card details and/or picture in sidebar cardview tabber.
*
*/
public void showCard(final CardView c, boolean showAlt) {
if (null == c) {
return;
}
currentView = c;
isDisplayAlt = false;
flipIndicator.setVisible(c.hasAltState());
picturePanel.setCard(c.getState(showAlt), mayShowCurrentCard());
if (showAlt && c.hasAltState()) {
flipCard();
}
}
/**
* Displays image associated with either a {@code Card}
* or {@code InventoryItem} instance.
@@ -137,7 +162,7 @@ public enum CPicture implements ICDoc {
@Override
public void onMiddleMouseDown(MouseEvent e) {
if (isCardDisplayed()) {
CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(currentCard, displayedState);
CardZoomer.SINGLETON_INSTANCE.doMouseButtonZoom(currentView);
}
}
@@ -162,7 +187,7 @@ public enum CPicture implements ICDoc {
public void mouseWheelMoved(MouseWheelEvent arg0) {
if (isCardDisplayed()) {
if (arg0.getWheelRotation() < 0) {
zoomer.doMouseWheelZoom(currentCard, displayedState);
zoomer.doMouseWheelZoom(currentView);
}
}
}
@@ -178,10 +203,9 @@ public enum CPicture implements ICDoc {
}
public void flipCard() {
if (isCurrentCardFlippable()) {
displayedState = CardDetailUtil.getAlternateState(currentCard, displayedState);
picturePanel.setCardImage(displayedState);
setCardDetailPanel();
if (currentView.hasAltState()) {
isDisplayAlt = !isDisplayAlt;
picturePanel.setCard(currentView.getState(isDisplayAlt), mayShowCurrentCard());
}
}
@@ -205,6 +229,7 @@ public enum CPicture implements ICDoc {
currentCard.setState(temp);
}
@Deprecated
private boolean isCurrentCardFlippable() {
if (!mayShowCurrentCard()) { return false; }

View File

@@ -1,9 +1,9 @@
package forge.screens.match.controllers;
import forge.UiCommand;
import forge.game.Game;
import forge.gui.framework.ICDoc;
import forge.screens.match.views.VPlayers;
import forge.view.IGameView;
/**
* Controls the combat panel in the match UI.
@@ -14,7 +14,7 @@ import forge.screens.match.views.VPlayers;
public enum CPlayers implements ICDoc {
/** */
SINGLETON_INSTANCE;
private Game game;
private IGameView game;
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
@@ -39,7 +39,7 @@ public enum CPlayers implements ICDoc {
VPlayers.SINGLETON_INSTANCE.update(game);
}
public void setModel(Game game) {
public void setModel(IGameView game) {
this.game = game;
}

View File

@@ -17,8 +17,18 @@
*/
package forge.screens.match.controllers;
import forge.UiCommand;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JButton;
import forge.FThreads;
import forge.Singletons;
import forge.UiCommand;
import forge.game.Game;
import forge.game.GameRules;
import forge.game.Match;
@@ -28,11 +38,6 @@ import forge.match.input.InputProxy;
import forge.screens.match.views.VPrompt;
import forge.toolbox.FSkin;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* Controls the prompt panel in the match UI.
*
@@ -114,8 +119,9 @@ public enum CPrompt implements ICDoc {
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void updateText(Game game) {
public void updateText() {
FThreads.assertExecutedByEdt(true);
final Game game = Singletons.getControl().getObservedGame();
final Match match = game.getMatch();
final GameRules rules = game.getRules();
final String text = String.format("T:%d G:%d/%d [%s]", game.getPhaseHandler().getTurn(), match.getPlayedGames().size() + 1, rules.getGamesPerMatch(), rules.getGameType());

View File

@@ -1,12 +1,12 @@
package forge.screens.match.controllers;
import forge.UiCommand;
import forge.game.player.Player;
import forge.game.zone.MagicStack;
import forge.gui.framework.EDocID;
import forge.gui.framework.ICDoc;
import forge.gui.framework.SDisplayUtil;
import forge.screens.match.views.VStack;
import forge.view.IGameView;
import forge.view.PlayerView;
/**
* Controls the combat panel in the match UI.
@@ -18,8 +18,8 @@ public enum CStack implements ICDoc {
/** */
SINGLETON_INSTANCE;
private MagicStack model;
private Player localPlayer;
private IGameView model;
private PlayerView localPlayer;
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
@@ -42,8 +42,9 @@ public enum CStack implements ICDoc {
VStack.SINGLETON_INSTANCE.updateStack(model, localPlayer);
}
public void setModel(MagicStack model0, Player localPlayer0) {
model = model0;
localPlayer = localPlayer0;
public void setModel(final IGameView game0, final PlayerView localPlayer) {
model = game0;
this.localPlayer = localPlayer;
}
}

View File

@@ -198,8 +198,8 @@ public final class GameMenu {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FControl control = Singletons.getControl();
VAutoYields autoYields = new VAutoYields(control.getObservedGame(), control.getLocalPlayer());
final FControl control = Singletons.getControl();
final VAutoYields autoYields = new VAutoYields(control.getGameView(), control.getLocalPlayer());
autoYields.showAutoYields();
}
};

View File

@@ -17,9 +17,15 @@
*/
package forge.screens.match.views;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import java.awt.Dimension;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import forge.gui.CardPicturePanel;
import forge.gui.WrapLayout;
import forge.gui.framework.DragCell;
@@ -29,13 +35,8 @@ import forge.gui.framework.IVDoc;
import forge.screens.match.controllers.CAntes;
import forge.toolbox.FLabel;
import forge.toolbox.FScrollPane;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.*;
import java.util.SortedSet;
import java.util.TreeSet;
import forge.view.CardView;
import forge.view.PlayerView;
/**
* Assembles Swing components of card ante area.
@@ -54,7 +55,7 @@ public enum VAntes implements IVDoc<CAntes> {
private final FScrollPane scroller = new FScrollPane(pnl, false);
private final SortedSet<AntePanel> allAntes = new TreeSet<AntePanel>();
private Iterable<Player> players;
private Iterable<PlayerView> players;
//========== Constructor
private VAntes() {
pnl.setLayout(new WrapLayout());
@@ -72,8 +73,8 @@ public enum VAntes implements IVDoc<CAntes> {
parentCell.getBody().add(scroller, "w 100%!, h 100%!");
}
public final void setModel(Iterable<Player> playerz) {
players = playerz;
public final void setModel(final List<PlayerView> players) {
this.players = players;
update();
}
@@ -121,8 +122,8 @@ public enum VAntes implements IVDoc<CAntes> {
allAntes.clear();
pnl.removeAll();
for(Player p : players) {
for(Card c : p.getZone(ZoneType.Ante)) {
for (final PlayerView p : players) {
for (final CardView c : p.getAnteCards()) {
final AntePanel pnlTemp = new AntePanel(c);
allAntes.add(pnlTemp);
}
@@ -136,15 +137,15 @@ public enum VAntes implements IVDoc<CAntes> {
//========= Private class handling
@SuppressWarnings("serial")
private class AntePanel extends JPanel implements Comparable<AntePanel> {
private final Card card;
private final CardView card;
/**
*
* @param p0 &emsp; {@link forge.game.player.Player}
* @param c0 &emsp; {@link forge.game.card.Card}
* @param c &emsp; {@link forge.game.card.Card}
*/
public AntePanel(final Card c0) {
public AntePanel(final CardView c) {
super();
card = c0;
card = c;
final Dimension d = new Dimension(160, 250);
setPreferredSize(d);
@@ -157,12 +158,12 @@ public enum VAntes implements IVDoc<CAntes> {
.fontAlign(SwingConstants.CENTER).build(), "w 160px, h 20px");
CardPicturePanel picPanel = new CardPicturePanel();
add(picPanel, "w 160px, h 230px");
picPanel.setCard(c0, true);
picPanel.setCard(c.getState(), true);
}
@Override
public int compareTo(AntePanel o) {
return o.card.getUniqueNumber() - card.getUniqueNumber();
public int compareTo(final AntePanel o) {
return o.card.getId() - card.getId();
}
}
}

View File

@@ -17,8 +17,9 @@
*/
package forge.screens.match.views;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
@@ -26,10 +27,8 @@ import forge.gui.framework.IVDoc;
import forge.screens.match.controllers.CCommand;
import forge.toolbox.FScrollPane;
import forge.toolbox.FSkin;
import forge.view.PlayerView;
import forge.view.arcane.PlayArea;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
/**
* Assembles Swing components of a player command instance.
@@ -44,7 +43,7 @@ public class VCommand implements IVDoc<CCommand> {
private final DragTab tab = new DragTab("Command");
// Other fields
private Player player = null;
private PlayerView player = null;
// Top-level containers
private final FScrollPane scroller = new FScrollPane(false);
@@ -54,20 +53,20 @@ public class VCommand implements IVDoc<CCommand> {
/**
* Assembles Swing components of a player command instance.
*
* @param player0 &emsp; {@link forge.game.player.Player}
* @param p &emsp; {@link forge.game.player.Player}
* @param id0 &emsp; {@link forge.gui.framework.EDocID}
*/
public VCommand(final EDocID id0, final Player player0) {
public VCommand(final EDocID id0, final PlayerView p) {
this.docID = id0;
id0.setDoc(this);
this.player = player0;
if (player0 != null) { tab.setText(player0.getName() + " Command"); }
this.player = p;
if (p != null) { tab.setText(p.getName() + " Command"); }
else { tab.setText("NO PLAYER FOR " + docID.toString()); }
// TODO player is hard-coded into tabletop...should be dynamic
// (haven't looked into it too deeply). Doublestrike 12-04-12
tabletop = new PlayArea(scroller, id0 == EDocID.COMMAND_0, player.getZone(ZoneType.Command).getCards(false));
tabletop = new PlayArea(scroller, id0 == EDocID.COMMAND_0, player.getCommandCards());
control = new CCommand(player, this);
@@ -135,7 +134,7 @@ public class VCommand implements IVDoc<CCommand> {
* Gets the player currently associated with this command.
* @return {@link forge.game.player.Player}
*/
public Player getPlayer() {
public PlayerView getPlayer() {
return this.player;
}

View File

@@ -44,7 +44,7 @@ public enum VDetail implements IVDoc<CDetail> {
private final DragTab tab = new DragTab("Card Detail");
// Top-level containers
private final CardDetailPanel pnlDetail = new CardDetailPanel(null);
private final CardDetailPanel pnlDetail = new CardDetailPanel();
private final SkinnedLabel lblFlipcard = new SkinnedLabel();
//========= Constructor

View File

@@ -17,9 +17,18 @@
*/
package forge.screens.match.views;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import net.miginfocom.swing.MigLayout;
import forge.LobbyPlayer;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
@@ -32,16 +41,8 @@ import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.toolbox.special.PhaseIndicator;
import forge.toolbox.special.PlayerDetailsPanel;
import forge.view.PlayerView;
import forge.view.arcane.PlayArea;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Assembles Swing components of a player field instance.
@@ -56,7 +57,7 @@ public class VField implements IVDoc<CField> {
private final DragTab tab = new DragTab("Field");
// Other fields
private Player player = null;
private PlayerView player = null;
// Top-level containers
private final FScrollPane scroller = new FScrollPane(false);
@@ -79,22 +80,22 @@ public class VField implements IVDoc<CField> {
/**
* Assembles Swing components of a player field instance.
*
* @param playerOnwer &emsp; {@link forge.game.player.Player}
* @param p &emsp; {@link forge.game.player.Player}
* @param id0 &emsp; {@link forge.gui.framework.EDocID}
*/
public VField(final EDocID id0, final Player playerOnwer, LobbyPlayer playerViewer) {
public VField(final EDocID id0, final PlayerView p, final LobbyPlayer playerViewer) {
this.docID = id0;
id0.setDoc(this);
this.player = playerOnwer;
if (playerOnwer != null) { tab.setText(playerOnwer.getName() + " Field"); }
this.player = p;
if (p != null) { tab.setText(p.getName() + " Field"); }
else { tab.setText("NO PLAYER FOR " + docID.toString()); }
detailsPanel = new PlayerDetailsPanel(player);
// TODO player is hard-coded into tabletop...should be dynamic
// (haven't looked into it too deeply). Doublestrike 12-04-12
tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player.getZone(ZoneType.Battlefield).getCards(false));
tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player.getBfCards());
control = new CField(player, this, playerViewer);
@@ -195,7 +196,7 @@ public class VField implements IVDoc<CField> {
* Gets the player currently associated with this field.
* @return {@link forge.game.player.Player}
*/
public Player getPlayer() {
public PlayerView getPlayer() {
return this.player;
}

View File

@@ -17,17 +17,17 @@
*/
package forge.screens.match.views;
import forge.game.player.Player;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.gui.framework.IVDoc;
import forge.screens.match.controllers.CHand;
import forge.toolbox.FScrollPane;
import forge.view.PlayerView;
import forge.view.arcane.HandArea;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
/**
* Assembles Swing components of hand area.
@@ -41,7 +41,6 @@ public class VHand implements IVDoc<CHand> {
private final EDocID docID;
private final DragTab tab = new DragTab("Your Hand");
// Top-level containers
private final FScrollPane scroller = new FScrollPane(false);
private final HandArea hand = new HandArea(scroller);
@@ -51,23 +50,23 @@ public class VHand implements IVDoc<CHand> {
* Assembles Swing components of a player hand instance.
*
* @param id0 &emsp; {@link forge.gui.framework.EDocID}
* @param owner &emsp; {@link forge.game.player.Player}
* @param p &emsp; {@link forge.game.player.Player}
*/
public VHand(final EDocID id0, final Player owner) {
public VHand(final EDocID id0, final PlayerView p) {
docID = id0;
id0.setDoc(this);
if (owner == null) {
if (p == null) {
tab.setText("NO PLAYER Hand");
} else {
tab.setText(owner.getName() + " Hand");
tab.setText(p.getName() + " Hand");
}
scroller.setViewportView(VHand.this.hand);
hand.setOpaque(false);
control = new CHand(owner, this);
control = new CHand(p, this);
}
//========= Overridden methods

View File

@@ -17,12 +17,17 @@
*/
package forge.screens.match.views;
import forge.game.Game;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JLabel;
import javax.swing.ScrollPaneConstants;
import net.miginfocom.swing.MigLayout;
import org.testng.collections.Maps;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
@@ -33,14 +38,9 @@ import forge.screens.match.controllers.CPlayers;
import forge.toolbox.FScrollPanel;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedLabel;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import forge.view.CardView;
import forge.view.IGameView;
import forge.view.PlayerView;
/**
* Assembles Swing components of players report.
@@ -59,7 +59,7 @@ public enum VPlayers implements IVDoc<CPlayers> {
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
// Other fields
private Map<Player, JLabel[]> infoLBLs;
private Map<PlayerView, JLabel[]> infoLBLs;
//========= Overridden methods
@@ -70,7 +70,7 @@ public enum VPlayers implements IVDoc<CPlayers> {
public void populate() {
scroller.removeAll();
final String constraints = "w 97%!, gapleft 2%, gapbottom 1%";
for (final Entry<Player, JLabel[]> p : infoLBLs.entrySet()) {
for (final Entry<PlayerView, JLabel[]> p : infoLBLs.entrySet()) {
for (JLabel label : p.getValue()) {
scroller.add(label, constraints);
}
@@ -79,9 +79,9 @@ public enum VPlayers implements IVDoc<CPlayers> {
parentCell.getBody().add(scroller, "w 100%, h 100%!");
}
public void init(final Iterable<Player> players) {
this.infoLBLs = new HashMap<Player, JLabel[]>();
for (final Player p : players) {
public void init(final List<PlayerView> players) {
this.infoLBLs = Maps.newHashMap();
for (final PlayerView p : players) {
// Create and store labels detailing various non-critical player info.
final InfoLabel name = new InfoLabel();
final InfoLabel life = new InfoLabel();
@@ -142,27 +142,27 @@ public enum VPlayers implements IVDoc<CPlayers> {
//========== Observer update methods
/** @param p0 {@link forge.game.player.Player} */
public void update(Game game) {
public void update(final IGameView game) {
// No need to update if this panel isn't showing
if (parentCell == null || !this.equals(parentCell.getSelected())) { return; }
boolean isCommander = game.getRules().hasAppliedVariant(GameType.Commander);
boolean isCommander = game.isCommander();
for(Entry<Player, JLabel[]> rr : infoLBLs.entrySet()) {
Player p0 = rr.getKey();
for(final Entry<PlayerView, JLabel[]> rr : infoLBLs.entrySet()) {
PlayerView p0 = rr.getKey();
final JLabel[] temp = rr.getValue();
temp[1].setText("Life: " + String.valueOf(p0.getLife()) + " | Poison counters: "
+ String.valueOf(p0.getPoisonCounters()));
temp[2].setText("Maximum hand size: " + String.valueOf(p0.getMaxHandSize()));
temp[3].setText("Cards drawn this turn: " + String.valueOf(p0.getNumDrawnThisTurn()));
temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamageTotalShields()));
temp[4].setText("Damage Prevention: " + String.valueOf(p0.getPreventNextDamage()));
if (!p0.getKeywords().isEmpty()) {
temp[5].setText(p0.getKeywords().toString());
} else {
temp[5].setText("");
}
if (FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE)) {
List<Card> list = p0.getCardsIn(ZoneType.Ante);
StringBuilder sb = new StringBuilder();
final List<CardView> list = p0.getAnteCards();
final StringBuilder sb = new StringBuilder();
sb.append("Ante'd: ");
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
@@ -173,7 +173,7 @@ public enum VPlayers implements IVDoc<CPlayers> {
temp[6].setText(sb.toString());
}
if (isCommander) {
temp[7].setText(CardFactoryUtil.getCommanderInfo(p0).trim().replace("\r\n", "; "));
temp[7].setText(p0.getCommanderInfo());
}
}
}

View File

@@ -17,16 +17,28 @@
*/
package forge.screens.match.views;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import net.miginfocom.swing.MigLayout;
import forge.ImageCache;
import forge.Singletons;
import forge.card.CardDetailUtil;
import forge.card.CardDetailUtil.DetailColors;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.player.PlayerController;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.zone.MagicStack;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
@@ -39,18 +51,11 @@ import forge.toolbox.FMouseAdapter;
import forge.toolbox.FScrollPanel;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedTextArea;
import forge.view.CardView;
import forge.view.IGameView;
import forge.view.PlayerView;
import forge.view.StackItemView;
import forge.view.arcane.CardPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
/**
* Assembles Swing components of stack report.
@@ -129,10 +134,11 @@ public enum VStack implements IVDoc<CStack> {
//========== Observer update methods
/**
* @param stack
* @param model
* @param viewer */
public void updateStack(final MagicStack stack, final Player localPlayer) {
tab.setText("Stack : " + stack.size());
public void updateStack(final IGameView model, final PlayerView localPlayer) {
final java.util.List<StackItemView> items = model.getStack();
tab.setText("Stack : " + items.size());
// No need to update the rest unless it's showing
if (!parentCell.getSelected().equals(this)) { return; }
@@ -140,15 +146,15 @@ public enum VStack implements IVDoc<CStack> {
scroller.removeAll();
boolean isFirst = true;
for (final SpellAbilityStackInstance spell : stack) {
StackInstanceTextArea tar = new StackInstanceTextArea(stack, spell, localPlayer);
for (final StackItemView item : items) {
final StackInstanceTextArea tar = new StackInstanceTextArea(model, item, localPlayer);
scroller.add(tar, "pushx, growx" + (isFirst ? "" : ", gaptop 2px"));
//update the Card Picture/Detail when the spell is added to the stack
if (isFirst) {
isFirst = false;
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSourceCard());
CMatchUI.SINGLETON_INSTANCE.setCard(item.getSource());
}
}
@@ -169,16 +175,14 @@ public enum VStack implements IVDoc<CStack> {
private static final int CARD_WIDTH = 50;
private static final int CARD_HEIGHT = Math.round((float)CARD_WIDTH * CardPanel.ASPECT_RATIO);
private final Card sourceCard;
private final CardView sourceCard;
public StackInstanceTextArea(final MagicStack stack, final SpellAbilityStackInstance spell, final Player localPlayer) {
sourceCard = spell.getSourceCard().getCardForUi();
public StackInstanceTextArea(final IGameView game, final StackItemView item, final PlayerView localPlayer) {
sourceCard = item.getSource();
final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer)
? "(OPTIONAL) " : "") + item.getText();
String txt = spell.getStackDescription();
if (spell.getSpellAbility().isOptionalTrigger()
&& spell.getSourceCard().getController().equals(localPlayer)) {
txt = "(OPTIONAL) " + txt;
}
setText(txt);
setToolTipText(txt);
setOpaque(true);
@@ -193,13 +197,13 @@ public enum VStack implements IVDoc<CStack> {
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent e) {
if (!spell.getStackDescription().startsWith("Morph ")) {
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSpellAbility().getHostCard());
if (!txt.startsWith("Morph ")) {
CMatchUI.SINGLETON_INSTANCE.setCard(item.getSource());
}
}
});
if (spell.getSpellAbility().isAbility() && localPlayer != null) {
if (item.isAbility() && localPlayer != null) {
addMouseListener(new FMouseAdapter() {
@Override
public void onLeftClick(MouseEvent e) {
@@ -210,13 +214,13 @@ public enum VStack implements IVDoc<CStack> {
onClick(e);
}
private void onClick(MouseEvent e) {
abilityMenu.setStackInstance(stack, spell.getSpellAbility(), localPlayer);
abilityMenu.setStackInstance(game, item, localPlayer);
abilityMenu.show(e.getComponent(), e.getX(), e.getY());
}
});
}
DetailColors color = CardDetailUtil.getBorderColor(sourceCard, !spell.getStackDescription().startsWith("Morph "));
DetailColors color = CardDetailUtil.getBorderColor(item.getSource().getOriginal(), !txt.startsWith("Morph "));
setBackground(new Color(color.r, color.g, color.b));
setForeground(FSkin.getHighContrastColor(getBackground()));
}
@@ -228,7 +232,7 @@ public enum VStack implements IVDoc<CStack> {
final Graphics2D g2d = (Graphics2D) g;
//draw image for source card
BufferedImage img = ImageCache.getImage(sourceCard, CARD_WIDTH, CARD_HEIGHT);
final BufferedImage img = ImageCache.getImage(sourceCard, CARD_WIDTH, CARD_HEIGHT);
if (img != null) {
g2d.drawImage(img, null, PADDING, PADDING);
}
@@ -242,8 +246,8 @@ public enum VStack implements IVDoc<CStack> {
private final JCheckBoxMenuItem jmiAutoYield;
private final JCheckBoxMenuItem jmiAlwaysYes;
private final JCheckBoxMenuItem jmiAlwaysNo;
private MagicStack stack;
private SpellAbility ability;
private IGameView game;
private StackItemView item;
private PlayerController controller;
private Integer triggerID = 0;
@@ -253,10 +257,10 @@ public enum VStack implements IVDoc<CStack> {
jmiAutoYield.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
final String key = ability.toUnsuppressedString();
final String key = item.getKey();
final boolean autoYield = controller.shouldAutoYield(key);
controller.setShouldAutoYield(key, !autoYield);
if (!autoYield && stack.peekAbility() == ability) {
if (!autoYield && game.peekStack() == item) {
//auto-pass priority if ability is on top of stack
CPrompt.SINGLETON_INSTANCE.getInputControl().passPriority();
}
@@ -273,7 +277,7 @@ public enum VStack implements IVDoc<CStack> {
}
else {
controller.setShouldAlwaysAcceptTrigger(triggerID);
if (stack.peekAbility() == ability &&
if (game.peekStack() == item &&
Singletons.getControl().getInputQueue().getInput() instanceof InputConfirm) {
//auto-yes if ability is on top of stack
CPrompt.SINGLETON_INSTANCE.getInputControl().selectButtonOK();
@@ -292,7 +296,7 @@ public enum VStack implements IVDoc<CStack> {
}
else {
controller.setShouldAlwaysDeclineTrigger(triggerID);
if (stack.peekAbility() == ability &&
if (game.peekStack() == item &&
Singletons.getControl().getInputQueue().getInput() instanceof InputConfirm) {
//auto-no if ability is on top of stack
CPrompt.SINGLETON_INSTANCE.getInputControl().selectButtonOK();
@@ -303,15 +307,15 @@ public enum VStack implements IVDoc<CStack> {
add(jmiAlwaysNo);
}
public void setStackInstance(final MagicStack stack0, final SpellAbility ability0, final Player localPlayer) {
stack = stack0;
ability = ability0;
public void setStackInstance(final IGameView game, final StackItemView item, final PlayerView localPlayer) {
this.game = game;
this.item = item;
controller = localPlayer.getController();
triggerID = ability.getSourceTrigger();
triggerID = Integer.valueOf(item.getSourceTrigger());
jmiAutoYield.setSelected(controller.shouldAutoYield(ability.toUnsuppressedString()));
jmiAutoYield.setSelected(controller.shouldAutoYield(item.getKey()));
if (ability.isOptionalTrigger() && ability.getActivatingPlayer() == localPlayer) {
if (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer)) {
jmiAlwaysYes.setSelected(controller.shouldAlwaysAcceptTrigger(triggerID));
jmiAlwaysNo.setSelected(controller.shouldAlwaysDeclineTrigger(triggerID));
jmiAlwaysYes.setVisible(true);

View File

@@ -18,6 +18,10 @@
package forge.toolbox.imaging;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import forge.ImageCache;
import forge.card.CardCharacteristicName;
import forge.game.card.Card;
@@ -25,10 +29,7 @@ import forge.model.FModel;
import forge.properties.ForgePreferences;
import forge.toolbox.CardFaceSymbols;
import forge.toolbox.FSkin.SkinIcon;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import forge.view.CardView.CardStateView;
/**
* Common image-related routines specific to Forge images.
@@ -38,7 +39,8 @@ import java.awt.image.ColorModel;
*/
public final class FImageUtil {
private FImageUtil() {}
@Deprecated
public static BufferedImage getImage(Card card, CardCharacteristicName state) {
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(state), true);
int foilIndex = card.getFoil();
@@ -56,6 +58,7 @@ public final class FImageUtil {
* For double-sided cards, returns the front-side image.<br>
* For flip cards, returns the un-flipped image.
*/
@Deprecated
public static BufferedImage getImage(Card card) {
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true);
int foilIndex = card.getFoil();
@@ -64,7 +67,24 @@ public final class FImageUtil {
}
return image;
}
/**
* Gets the image associated with a card.
* <p>
* Adds a random foil effect if enabled.
* <p>
* For double-sided cards, returns the front-side image.<br>
* For flip cards, returns the un-flipped image.
*/
public static BufferedImage getImage(final CardStateView card) {
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true);
final int foilIndex = card.getCard().getFoilIndex();
if (image != null && foilIndex > 0) {
image = getImageWithFoilEffect(image, foilIndex);
}
return image;
}
/**
* Applies a foil effect to a card image.
*/

View File

@@ -56,7 +56,7 @@ public class CardViewer extends JPanel {
public CardViewer(final List<PaperCard> list) {
this.list = Collections.unmodifiableList(list);
this.jList = new JList<PaperCard>(new ChooserListModel());
this.detail = new CardDetailPanel(null);
this.detail = new CardDetailPanel();
this.picture = new CardPicturePanel();
this.add(new FScrollPane(this.jList, true));

View File

@@ -18,23 +18,29 @@
package forge.toolbox.special;
import forge.Singletons;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JPanel;
import javax.swing.Timer;
import net.miginfocom.swing.MigLayout;
import forge.assets.FSkinProp;
import forge.card.CardCharacteristicName;
import forge.card.CardDetailUtil;
import forge.game.card.Card;
import forge.gui.SOverlayUtils;
import forge.toolbox.FOverlay;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedLabel;
import forge.toolbox.imaging.FImagePanel;
import forge.toolbox.imaging.FImageUtil;
import forge.toolbox.imaging.FImagePanel.AutoSizeImageMode;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.awt.event.*;
import forge.toolbox.imaging.FImageUtil;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
/**
* Displays card image at its original size and correct orientation.
@@ -46,30 +52,28 @@ import java.awt.event.*;
*
*/
public enum CardZoomer {
SINGLETON_INSTANCE;
SINGLETON_INSTANCE;
// Gui controls
private final JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
private JPanel pnlMain;
private FImagePanel imagePanel;
private SkinnedLabel lblFlipcard = new SkinnedLabel();
// Details about the current card being displayed.
private Card thisCard;
private CardCharacteristicName cardState = CardCharacteristicName.Original;
private boolean isImageFlipped = false;
private boolean isFaceDownCard = false;
private CardView thisCard;
private boolean isInAltState;
// The zoomer is in button mode when it is activated by holding down the
// middle mouse button or left and right mouse buttons simultaneously.
private boolean isButtonMode = false;
private boolean isOpen = false;
private long lastClosedTime;
// Used to ignore mouse wheel rotation for a short period of time.
private Timer mouseWheelCoolDownTimer;
private boolean isMouseWheelEnabled = false;
// ctr
private CardZoomer() {
lblFlipcard.setIcon(FSkin.getIcon(FSkinProp.ICO_FLIPCARD));
@@ -77,7 +81,7 @@ public enum CardZoomer {
setMouseWheelListener();
setKeyListeners();
}
/**
* Creates listener for keys that are recognised by zoomer.
* <p><ul>
@@ -103,30 +107,33 @@ public enum CardZoomer {
/**
* Creates listener for mouse button events.
* <p>
* NOTE: Needed even if ButtonMode to prevent Zoom getting stuck open on certain systems.
* NOTE: Needed even if ButtonMode to prevent Zoom getting stuck open on
* certain systems.
*/
private void setMouseButtonListener() {
overlay.addMouseListener(new MouseAdapter() {
overlay.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
closeZoomer();
}
});
}
/**
* Creates listener for mouse wheel events.
* <p>
* If the zoomer is opened using the mouse wheel then additional
* actions can be performed dependent on the card type -
* <p><ul>
* If the zoomer is opened using the mouse wheel then additional actions can
* be performed dependent on the card type -
* <p>
* <ul>
* <li>If mouse wheel is rotated back then close zoomer.
* <li>If mouse wheel is rotated forward and...<ul>
* <li>if image is a flip card then rotate 180 degrees.
* <li>if image is a double-sided card then show other side.
* <li>If mouse wheel is rotated forward and...
* <ul>
* <li>if image is a flip card then rotate 180 degrees.
* <li>if image is a double-sided card then show other side.
*/
private void setMouseWheelListener() {
overlay.addMouseWheelListener(new MouseWheelListener() {
overlay.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (!isButtonMode) {
@@ -136,111 +143,86 @@ public enum CardZoomer {
closeZoomer();
} else {
toggleCardImage();
startMouseWheelCoolDownTimer(250);
}
}
startMouseWheelCoolDownTimer(250);
}
}
}
}
}
});
}
/**
* Opens zoomer in mouse wheel mode and displays the image associated with
* the given card based on its current {@code CardCharacteristicName} state.
* the given card based.
* <p>
* This method should be called if the zoomer is activated by rotating the mouse wheel.
* This method should be called if the zoomer is activated by rotating the
* mouse wheel.
*/
public void doMouseWheelZoom(Card newCard) {
doMouseWheelZoom(newCard, newCard.getCurState());
}
/**
* Opens zoomer in mouse wheel mode and displays the image associated with
* the given card based on the specified {@code CardCharacteristicName} state.
* <p>
* This method should be called if the zoomer is activated by rotating the mouse wheel.
*/
public void doMouseWheelZoom(Card newCard, CardCharacteristicName state) {
public void doMouseWheelZoom(final CardView card) {
isButtonMode = false;
isFaceDownCard = (state == CardCharacteristicName.FaceDown);
cardState = state;
displayCard(newCard);
startMouseWheelCoolDownTimer(200);
displayCard(card);
startMouseWheelCoolDownTimer(200);
}
/**
* Opens zoomer in mouse button mode and displays the image associated with
* the given card based on its current {@code CardCharacteristicName} state.
* <p>
* This method should be called if the zoomer is activated by holding down
* the middle mouse button or left and right mouse buttons simultaneously.
*/
public void doMouseButtonZoom(Card newCard) {
doMouseButtonZoom(newCard, newCard.getCurState());
}
/**
* Opens zoomer in mouse button mode and displays the image associated with
* the given card based on the specified {@code CardCharacteristicName} state.
* the given card.
* <p>
* This method should be called if the zoomer is activated by holding down
* the middle mouse button or left and right mouse buttons simultaneously.
*/
public void doMouseButtonZoom(Card newCard, CardCharacteristicName state) {
public void doMouseButtonZoom(final CardView newCard) {
// don't display zoom if already zoomed or just closed zoom
// (handles mouse wheeling while middle clicking)
if (isOpen || System.currentTimeMillis() - lastClosedTime < 250) {
return;
}
}
isButtonMode = true;
isFaceDownCard = (state == CardCharacteristicName.FaceDown);
cardState = state;
displayCard(newCard);
}
public boolean isZoomerOpen() {
return isOpen;
}
private void displayCard(Card card) {
private void displayCard(final CardView newCard) {
isMouseWheelEnabled = false;
isImageFlipped = false;
thisCard = card.getCardForUi();
thisCard = newCard;
isInAltState = false;
setLayout();
setImage();
SOverlayUtils.showOverlay();
isOpen = true;
}
/**
* Displays a graphical indicator that shows whether the current card can be flipped or transformed.
*/
private void setFlipIndicator() {
boolean isFaceDownFlippable = (isFaceDownCard && Singletons.getControl().mayShowCard(thisCard));
if (thisCard.isFlipCard() || thisCard.isDoubleFaced() || isFaceDownFlippable ) {
if (thisCard.hasAltState()) {
imagePanel.setLayout(new MigLayout("insets 0, w 100%!, h 100%!"));
imagePanel.add(lblFlipcard, "pos (100% - 100px) 0");
}
}
}
/**
* Needs to be called whenever the source image changes.
*/
private void setImage() {
imagePanel = new FImagePanel();
imagePanel.setImage(FImageUtil.getImage(thisCard, cardState), getInitialRotation(), AutoSizeImageMode.SOURCE);
imagePanel.setImage(FImageUtil.getImage(getState()), getInitialRotation(), AutoSizeImageMode.SOURCE);
pnlMain.removeAll();
pnlMain.add(imagePanel, "w 80%!, h 80%!");
pnlMain.validate();
setFlipIndicator();
}
private int getInitialRotation() {
return (thisCard.isSplitCard() || thisCard.isPlane() || thisCard.isPhenomenon() ? 90 : 0);
return (thisCard.isSplitCard() || getState().isPlane() || getState().isPhenomenon() ? 90 : 0);
}
private void setLayout() {
overlay.removeAll();
pnlMain = new JPanel();
@@ -283,53 +265,35 @@ public enum CardZoomer {
});
}
}
private void stopMouseWheelCoolDownTimer() {
if (mouseWheelCoolDownTimer != null && mouseWheelCoolDownTimer.isRunning()) {
mouseWheelCoolDownTimer.stop();
}
}
/**
* Toggles between primary and alternate image associated with card if applicable.
*/
private void toggleCardImage() {
if (thisCard.isFlipCard()) {
if (thisCard.hasAltState()) {
toggleFlipCard();
} else if (thisCard.isDoubleFaced()) {
toggleDoubleFacedCard();
} else if (isFaceDownCard) {
toggleFaceDownCard();
}
}
/**
* Flips image by rotating 180 degrees each time.
* <p>
* No need to get the alternate card image from cache.
* Can simply rotate current card image in situ to get same effect.
*/
private void toggleFlipCard() {
isImageFlipped = !isImageFlipped;
imagePanel.setRotation(isImageFlipped ? 180 : 0);
}
/**
* Toggles between the front and back image of a card that can be
* played face-down (eg. morph).
* <p>
* Uses constraint that prevents a player from identifying opponent's face-down cards.
*/
private void toggleFaceDownCard() {
cardState = CardDetailUtil.getAlternateState(thisCard, cardState);
private void toggleFlipCard() {
isInAltState = !isInAltState;
imagePanel.setRotation(thisCard.isFlipCard() && isInAltState ? 180 : 0);
setImage();
}
/**
* Toggles between the front and back image of a double-sided card.
*/
private void toggleDoubleFacedCard() {
cardState = CardDetailUtil.getAlternateState(thisCard, cardState);
setImage();
private CardStateView getState() {
return thisCard.getState(isButtonMode);
}
}

View File

@@ -1,35 +1,36 @@
package forge.toolbox.special;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Function;
import forge.assets.FSkinProp;
import forge.card.MagicColor;
import forge.game.mana.ManaPool;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.ForgeAction;
import forge.properties.ForgePreferences;
import forge.screens.match.controllers.CPlayers;
import forge.toolbox.FLabel;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedPanel;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.tuple.Pair;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import forge.view.PlayerView;
public class PlayerDetailsPanel extends JPanel {
private static final long serialVersionUID = 8444559244193214459L;
private Player player;
private PlayerView player;
// Info labels
private FLabel lblHand = getBuiltFLabel(FSkinProp.IMG_ZONE_HAND, "99", "Cards in hand");
@@ -47,8 +48,7 @@ public class PlayerDetailsPanel extends JPanel {
.text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build();
}
public PlayerDetailsPanel(Player player) {
public PlayerDetailsPanel(final PlayerView player) {
this.player = player;
manaLabels.add(Pair.of(getBuiltFLabel(FSkinProp.IMG_MANA_B, "99", "Black mana"), MagicColor.BLACK));
@@ -121,14 +121,14 @@ public class PlayerDetailsPanel extends JPanel {
* @param p0 &emsp; {@link forge.game.player.Player}
*/
public void updateZones() {
this.getLblHand().setText("" + player.getZone(ZoneType.Hand).size());
final String handMaxToolTip = player.isUnlimitedHandSize()
this.getLblHand().setText("" + player.getHandCards().size());
final String handMaxToolTip = player.hasUnlimitedHandSize()
? "no maximum hand size" : String.valueOf(player.getMaxHandSize());
this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")");
this.getLblGraveyard().setText("" + player.getZone(ZoneType.Graveyard).size());
this.getLblLibrary().setText("" + player.getZone(ZoneType.Library).size());
this.getLblFlashback().setText("" + player.getCardsActivableInExternalZones(true).size());
this.getLblExile().setText("" + player.getZone(ZoneType.Exile).size());
this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")");
this.getLblGraveyard().setText("" + player.getGraveCards().size());
this.getLblLibrary().setText("" + player.getLibraryCards().size());
this.getLblFlashback().setText("" + player.getFlashbackCards().size());
this.getLblExile().setText("" + player.getExileCards().size());
}
@@ -158,9 +158,8 @@ public class PlayerDetailsPanel extends JPanel {
* @param p0 &emsp; {@link forge.game.player.Player}
*/
public void updateManaPool() {
ManaPool m = player.getManaPool();
for(Pair<FLabel, Byte> label : manaLabels)
label.getKey().setText(Integer.toString(m.getAmountOfColor(label.getRight())));
for (final Pair<FLabel, Byte> label : manaLabels)
label.getKey().setText(Integer.toString(player.getMana(label.getRight())));
}
public FLabel getLblHand() {

View File

@@ -17,31 +17,38 @@
*/
package forge.view.arcane;
import forge.ImageCache;
import forge.Singletons;
import forge.card.CardCharacteristicName;
import forge.card.CardEdition;
import forge.card.mana.ManaCost;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.gui.CardContainer;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.screens.match.CMatchUI;
import forge.toolbox.CardFaceSymbols;
import forge.toolbox.IDisposable;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.view.arcane.util.OutlinedLabel;
import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import forge.ImageCache;
import forge.Singletons;
import forge.card.CardEdition;
import forge.card.mana.ManaCost;
import forge.gui.CardContainer;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.screens.match.CMatchUI;
import forge.toolbox.CardFaceSymbols;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.toolbox.IDisposable;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
import forge.view.arcane.util.OutlinedLabel;
/**
* <p>
* CardPanel class.
@@ -85,7 +92,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
*/
private static final float ROT_CENTER_TO_BOTTOM_CORNER = 0.7071067811865475244008443621048f;
private Card card;
private CardView card;
private CardPanel attachedToPanel;
private List<CardPanel> attachedPanels = new ArrayList<CardPanel>();
private boolean tapped;
@@ -110,7 +117,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
* @param newCard
* a {@link forge.game.card.Card} object.
*/
public CardPanel(final Card card0) {
public CardPanel(final CardView card0) {
this.card = card0;
this.setBackground(Color.black);
@@ -321,8 +328,8 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
// White border if card is known to have it.
if (this.getCard() != null && Singletons.getControl().mayShowCard(this.getCard()) && !this.getCard().isFaceDown()) {
CardEdition ed = FModel.getMagicDb().getEditions().get(this.getCard().getCurSetCode());
if (ed != null && ed.isWhiteBorder() && this.getCard().getFoil() == 0) {
CardEdition ed = FModel.getMagicDb().getEditions().get(this.getCard().getSetCode());
if (ed != null && ed.isWhiteBorder() && this.getCard().getFoilIndex() == 0) {
g2d.setColor(Color.white);
int ins = 1;
g2d.fillRoundRect(this.cardXOffset + ins, this.cardYOffset + ins, this.cardWidth - ins*2, this.cardHeight - ins*2, cornerSize-ins, cornerSize-ins);
@@ -351,12 +358,12 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
}
if (showCardManaCostOverlay() && this.cardWidth < 200) {
boolean showSplitMana = card.isSplitCard() && card.getCurState() == CardCharacteristicName.Original;
final boolean showSplitMana = card.isSplitCard();
if (!showSplitMana) {
drawManaCost(g, card.getManaCost(), 0);
drawManaCost(g, card.getState().getManaCost(), 0);
} else {
drawManaCost(g, card.getRules().getMainPart().getManaCost(), +12);
drawManaCost(g, card.getRules().getOtherPart().getManaCost(), -12);
drawManaCost(g, card.getOriginal().getManaCost(), +12);
drawManaCost(g, card.getAlternate().getManaCost(), -12);
}
}
@@ -382,17 +389,14 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
final int stateXSymbols = (this.cardXOffset + (this.cardWidth / 2)) - 16;
final int ySymbols = (this.cardYOffset + this.cardHeight) - (this.cardHeight / 8) - 16;
Combat combat = card.getGame().getCombat();
if (combat != null) {
if (combat.isAttacking(card)) {
CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols);
}
if (combat.isBlocking(card)) {
CardFaceSymbols.drawSymbol("defend", g, combatXSymbols, ySymbols);
}
if (card.isAttacking()) {
CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols);
}
if (card.isBlocking()) {
CardFaceSymbols.drawSymbol("defend", g, combatXSymbols, ySymbols);
}
if (card.isSick() && card.isInPlay()) {
if (card.isSick()) {
CardFaceSymbols.drawSymbol("summonsick", g, stateXSymbols, ySymbols);
}
@@ -409,9 +413,9 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
this.cardWidth, this.cardHeight, Math.round(this.cardWidth * BLACK_BORDER_SIZE));
}
public static void drawFoilEffect(Graphics g, Card card, int x, int y, int width, int height, int borderSize) {
public static void drawFoilEffect(final Graphics g, final CardView card2, final int x, final int y, final int width, final int height, final int borderSize) {
if (isPreferenceEnabled(FPref.UI_OVERLAY_FOIL_EFFECT)) {
int foil = card.getFoil();
int foil = card2.getFoilIndex();
if (foil > 0) {
CardFaceSymbols.drawOther(g, String.format("foil%02d", foil),
x + borderSize, y + borderSize, width - 2 * borderSize, height - 2 * borderSize);
@@ -479,7 +483,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
@Override
public final String toString() {
return this.getCard().getName();
return this.getCard().toString();
}
/**
@@ -610,27 +614,28 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
this.titleText.setText("");
}
else {
this.titleText.setText(card.getName());
this.titleText.setText(card.getState().getName());
}
int damage = card.getDamage();
this.damageText.setText(damage > 0 ? "\u00BB " + String.valueOf(damage) + " \u00AB" : "");
// Card Id overlay
this.cardIdText.setText(Integer.toString(card.getUniqueNumber()));
this.cardIdText.setText(Integer.toString(card.getId()));
}
public final void updatePTOverlay() {
// P/T overlay
final CardStateView state = card.getState();
String sPt = "";
if (card.isCreature() && card.isPlaneswalker()) {
sPt = String.format("%d/%d (%d)", card.getNetAttack(), card.getNetDefense(), card.getCurrentLoyalty());
if (state.isCreature() && state.isPlaneswalker()) {
sPt = String.format("%d/%d (%d)", state.getPower(), state.getToughness(), state.getLoyalty());
}
else if (card.isCreature()) {
sPt = String.format("%d/%d", card.getNetAttack(), card.getNetDefense());
else if (state.isCreature()) {
sPt = String.format("%d/%d", state.getPower(), state.getToughness());
}
else if (card.isPlaneswalker()) {
sPt = String.valueOf(card.getCurrentLoyalty());
else if (state.isPlaneswalker()) {
sPt = String.valueOf(state.getLoyalty());
}
this.ptText.setText(sPt);
}
@@ -641,28 +646,28 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
* @return the card
*/
@Override
public final Card getCard() {
public final CardView getCard() {
return this.card;
}
/** {@inheritDoc} */
@Override
public final void setCard(final Card card) {
if ((this.getCard() != null) && this.getCard().equals(card) && this.isAnimationPanel
public final void setCard(final CardView cardView) {
if ((this.getCard() != null) && this.getCard().equals(cardView) && this.isAnimationPanel
&& this.imagePanel.hasImage()) {
return;
}
if (this.card != card) {
if (this.card != cardView) {
this.updatePTOverlay(); //update PT Overlay if card changes
}
this.card = card;
this.card = cardView;
if (!this.isShowing()) {
return;
}
final BufferedImage image = card == null ? null : ImageCache.getImage(card, imagePanel.getWidth(), imagePanel.getHeight());
final BufferedImage image = cardView == null ? null : ImageCache.getImage(cardView, imagePanel.getWidth(), imagePanel.getHeight());
this.updateText();
this.setImage(image);

View File

@@ -17,21 +17,26 @@
*/
package forge.view.arcane;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
import forge.FThreads;
import forge.game.card.Card;
import forge.screens.match.CMatchUI;
import forge.toolbox.FScrollPane;
import forge.toolbox.FSkin.SkinnedPanel;
import forge.toolbox.special.CardZoomer;
import forge.view.CardView;
import forge.view.arcane.util.CardPanelMouseListener;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
/**
* Manages mouse events and common functionality for CardPanel containing
* components.
@@ -278,6 +283,29 @@ public abstract class CardPanelContainer extends SkinnedPanel {
protected abstract CardPanel getCardPanel(int x, int y);
/**
<<<<<<< .mine
* Must call from the Swing event thread.
*
* @param card
* a {@link forge.game.card.Card} object.
* @return a {@link forge.view.arcane.CardPanel} object.
*/
public CardPanel addCard(final CardView card) {
final CardPanel placeholder = new CardPanel(card);
placeholder.setDisplayEnabled(false);
this.getCardPanels().add(placeholder);
this.add(placeholder);
this.doLayout();
// int y = Math.min(placeholder.getHeight(),
// scrollPane.getVisibleRect().height);
this.scrollRectToVisible(new Rectangle(placeholder.getCardX(), placeholder.getCardY(), placeholder
.getCardWidth(), placeholder.getCardHeight()));
return placeholder;
}
/**
=======
>>>>>>> .r27195
* <p>
* getCardPanel.
* </p>
@@ -288,7 +316,7 @@ public abstract class CardPanelContainer extends SkinnedPanel {
*/
public final CardPanel getCardPanel(final int gameCardID) {
for (final CardPanel panel : this.getCardPanels()) {
if (panel.getCard().getUniqueNumber() == gameCardID) {
if (panel.getCard().getId() == gameCardID) {
return panel;
}
}
@@ -584,7 +612,7 @@ public abstract class CardPanelContainer extends SkinnedPanel {
*
* @return a {@link forge.game.card.Card} object.
*/
public final Card getHoveredCard(MouseEvent e) {
public final CardView getHoveredCard(final MouseEvent e) {
// re-evaluate cursor position so if we hovered over a card, alt-tabbed out of the application, then
// clicked back on the application somewhere else, the last hovered card won't register the click
// this cannot protect against alt tabbing off then re-focusing on the application by clicking on

View File

@@ -17,20 +17,26 @@
*/
package forge.view.arcane;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Lists;
import forge.FThreads;
import forge.game.card.Card;
import forge.screens.match.CMatchUI;
import forge.screens.match.controllers.CPrompt;
import forge.toolbox.FScrollPane;
import forge.toolbox.MouseTriggerEvent;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
import forge.view.arcane.util.Animation;
import forge.view.arcane.util.CardPanelMouseListener;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
/**
* <p>
* PlayArea class.
@@ -69,8 +75,8 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
private int extraCardSpacingX, cardSpacingX, cardSpacingY;
private int stackSpacingX, stackSpacingY;
private List<Card> model;
private final List<CardView> model;
/**
* <p>
* Constructor for PlayArea.
@@ -78,13 +84,13 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
*
* @param scrollPane
* @param mirror
* @param modelRef
* @param list
*/
public PlayArea(final FScrollPane scrollPane, final boolean mirror, List<Card> modelRef) {
public PlayArea(final FScrollPane scrollPane, final boolean mirror, final List<CardView> list) {
super(scrollPane);
this.setBackground(Color.white);
this.mirror = mirror;
this.model = modelRef;
this.model = list;
}
private final CardStackRow collectAllLands() {
@@ -93,7 +99,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
outerLoop:
//
for (final CardPanel panel : this.getCardPanels()) {
if (!panel.getCard().isLand() || panel.getCard().isCreature()) {
final CardView card = panel.getCard();
final CardStateView state = card.getState();
if (!state.isLand() || state.isCreature()) {
continue;
}
@@ -103,7 +112,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
for (int i = 0, n = allLands.size(); i < n; i++) {
final CardStack stack = allLands.get(i);
final CardPanel firstPanel = stack.get(0);
if (firstPanel.getCard().getName().equals(panel.getCard().getName())) {
if (firstPanel.getCard().getState().getName().equals(state.getName())) {
if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().isEnchanted()) {
// Put this land to the left of lands with the same name
// and attachments.
@@ -139,7 +148,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
outerLoop:
//
for (final CardPanel panel : this.getCardPanels()) {
if (!panel.getCard().isToken()) {
final CardView card = panel.getCard();
final CardStateView state = card.getState();
if (!card.isToken()) {
continue;
}
@@ -149,7 +161,10 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
for (int i = 0, n = allTokens.size(); i < n; i++) {
final CardStack stack = allTokens.get(i);
final CardPanel firstPanel = stack.get(0);
if (firstPanel.getCard().getName().equals(panel.getCard().getName())) {
final CardView firstCard = firstPanel.getCard();
final CardStateView firstState = firstCard.getState();
if (firstPanel.getCard().getState().getName().equals(state.getName())) {
if (!firstPanel.getAttachedPanels().isEmpty()) {
// Put this token to the left of tokens with the same
// name and attachments.
@@ -157,15 +172,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
break;
}
Set<String> keywords = new HashSet<>(panel.getCard().getIntrinsicKeyword());
Set<String> firstKeywords = new HashSet<>(firstPanel.getCard().getIntrinsicKeyword());
final String text = state.getText();
final String firstText = firstState.getText();
if (!panel.getAttachedPanels().isEmpty()
|| !panel.getCard().getCounters().equals(firstPanel.getCard().getCounters())
|| (panel.getCard().isSick() != firstPanel.getCard().isSick())
|| (panel.getCard().getNetAttack() != firstPanel.getCard().getNetAttack())
|| (panel.getCard().getNetDefense() != firstPanel.getCard().getNetDefense())
|| !(keywords.equals(firstKeywords))
|| !card.getCounters().equals(firstPanel.getCard().getCounters())
|| (card.isSick() != firstCard.isSick())
|| (state.getPower() != firstState.getPower())
|| (state.getToughness() != firstState.getToughness())
|| !(text.equals(firstText))
|| (stack.size() == tokenStackMax)) {
// If this token has attachments or the stack is full,
// put it to the right.
@@ -241,6 +256,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
}*/
@Override
public final CardPanel addCard(final CardView card) {
final CardPanel placeholder = new CardPanel(card);
placeholder.setDisplayEnabled(false);
this.getCardPanels().add(placeholder);
this.add(placeholder);
return placeholder;
}
@Override
public final void doLayout() {
final Rectangle rect = this.getScrollPane().getVisibleRect();
@@ -323,7 +347,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
for (int stackIndex = 0, stackCount = row.size(); stackIndex < stackCount; stackIndex++) {
final CardStack stack = row.get(stackIndex);
// Align others to the right.
if (RowType.Other.isGoodFor(stack.get(0).getCard())) {
if (RowType.Other.isGoodFor(stack.get(0).getCard().getState())) {
x = (this.playAreaWidth - PlayArea.GUTTER_X) + this.extraCardSpacingX;
for (int i = stackIndex, n = row.size(); i < n; i++) {
CardStack r = row.get(i);
@@ -570,20 +594,19 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
recalculateCardPanels(model);
}
private void recalculateCardPanels(final List<Card> model) {
List<Card> oldCards, toDelete;
oldCards = new ArrayList<Card>();
private void recalculateCardPanels(final List<CardView> model) {
final List<CardView> oldCards = Lists.newArrayList();
for (final CardPanel cpa : getCardPanels()) {
oldCards.add(cpa.getCard());
}
toDelete = new ArrayList<Card>(oldCards);
List<Card> toReplace = new ArrayList<Card>();
final List<CardView> toDelete = Lists.newArrayList(oldCards);
final List<CardView> toReplace = Lists.newArrayList();
// delete all cards that differ in timestamp (they have been blinked)
for (final Card c : model) {
for (final CardView c : model) {
for (int i = 0; i < toDelete.size(); i++) {
final Card c2 = toDelete.get(i);
if (c.equals(c2)) {
final CardView c2 = toDelete.get(i);
if (c.getId() == c2.getId()) {
if (c.getTimestamp() == c2.getTimestamp()) {
toDelete.remove(i);
} else {
@@ -595,17 +618,17 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
if (toDelete.size() == getCardPanels().size()) {
clear();
} else {
for (final Card card : toDelete) {
removeCardPanel(getCardPanel(card.getUniqueNumber()));
for (final CardView card : toDelete) {
removeCardPanel(getCardPanel(card.getId()));
}
}
List<Card> toAdd = new ArrayList<Card>(model);
List<CardView> toAdd = new ArrayList<CardView>(model);
toAdd.removeAll(oldCards);
toAdd.addAll(toReplace);
List<CardPanel> newPanels = new ArrayList<CardPanel>();
for (final Card card : toAdd) {
for (final CardView card : toAdd) {
if (card.getCardForUi() == card) { //only include cards that are meant for display
final CardPanel placeholder = new CardPanel(card);
placeholder.setDisplayEnabled(false);
@@ -624,15 +647,15 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
}
}
for (final Card card : model) {
for (final CardView card : model) {
updateCard(card, true);
}
invalidate();
repaint();
}
public void updateCard(final Card card, boolean fromRefresh) {
final CardPanel toPanel = getCardPanel(card.getUniqueNumber());
public void updateCard(final CardView card, boolean fromRefresh) {
final CardPanel toPanel = getCardPanel(card.getId());
if (null == toPanel) { return; }
if (card.isTapped()) {
@@ -643,42 +666,37 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
toPanel.setTappedAngle(0);
}
toPanel.getAttachedPanels().clear();
if (card.isEnchanted()) {
final ArrayList<Card> enchants = card.getEnchantedBy();
for (final Card e : enchants) {
final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
}
}
if (card.isEquipped()) {
final ArrayList<Card> enchants = card.getEquippedBy();
for (final Card e : enchants) {
final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
final Iterable<CardView> enchants = card.getEnchantedBy();
for (final CardView e : enchants) {
final CardPanel cardE = getCardPanel(e.getId());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
}
if (card.isFortified()) {
final ArrayList<Card> fortifications = card.getFortifiedBy();
for (final Card e : fortifications) {
final forge.view.arcane.CardPanel cardE = getCardPanel(e.getUniqueNumber());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
final Iterable<CardView> equips = card.getEquippedBy();
for (final CardView e : equips) {
final CardPanel cardE = getCardPanel(e.getId());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
}
if (card.isEnchantingCard()) {
toPanel.setAttachedToPanel(getCardPanel(card.getEnchantingCard().getUniqueNumber()));
} else if (card.isEquipping()) {
toPanel.setAttachedToPanel(getCardPanel(card.getEquipping().get(0).getUniqueNumber()));
} else if (card.isFortifying()) {
toPanel.setAttachedToPanel(getCardPanel(card.getFortifying().get(0).getUniqueNumber()));
final Iterable<CardView> fortifications = card.getFortifiedBy();
for (final CardView f : fortifications) {
final CardPanel cardE = getCardPanel(f.getId());
if (cardE != null) {
toPanel.getAttachedPanels().add(cardE);
}
}
if (card.getEnchantingCard() != null) {
toPanel.setAttachedToPanel(getCardPanel(card.getEnchantingCard().getId()));
} else if (card.getEquipping() != null) {
toPanel.setAttachedToPanel(getCardPanel(card.getEquipping().getId()));
} else if (card.getFortifying() != null) {
toPanel.setAttachedToPanel(getCardPanel(card.getFortifying().getId()));
} else {
toPanel.setAttachedToPanel(null);
}
@@ -695,12 +713,12 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
CreatureNonToken,
Other;
public boolean isGoodFor(final Card card) {
public boolean isGoodFor(final CardStateView stateView) {
switch (this) {
case Land: return card.isLand();
case Creature: return card.isCreature();
case CreatureNonToken: return card.isCreature() && !card.isToken();
case Other: return !card.isLand() && !card.isCreature();
case Land: return stateView.isLand();
case Creature: return stateView.isCreature();
case CreatureNonToken: return stateView.isCreature() && !stateView.getCard().isToken();
case Other: return !stateView.isLand() && !stateView.isCreature();
default: throw new RuntimeException("Unhandled type: " + this);
}
}
@@ -724,7 +742,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
private void addAll(final List<CardPanel> cardPanels, final RowType type) {
for (final CardPanel panel : cardPanels) {
if (!type.isGoodFor(panel.getCard()) || (panel.getAttachedToPanel() != null)) {
if (!type.isGoodFor(panel.getCard().getState()) || (panel.getAttachedToPanel() != null)) {
continue;
}
final CardStack stack = new CardStack();
@@ -741,14 +759,16 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
*/
private void addAllOthers(final List<CardPanel> cardPanels, final RowType type) {
for (final CardPanel panel : cardPanels) {
if (!type.isGoodFor(panel.getCard()) || (panel.getAttachedToPanel() != null)) {
if (!type.isGoodFor(panel.getCard().getState()) || (panel.getAttachedToPanel() != null)) {
continue;
}
boolean stackable = false;
for (CardStack s : this) {
Card otherCard = s.get(0).getCard();
Card thisCard = panel.getCard();
if (otherCard.getName().equals(thisCard.getName()) && s.size() < othersStackMax) {
for (final CardStack s : this) {
final CardView otherCard = s.get(0).getCard();
final CardStateView otherState = otherCard.getState();
final CardView thisCard = panel.getCard();
final CardStateView thisState = thisCard.getState();
if (otherState.getName().equals(thisState.getName()) && s.size() < othersStackMax) {
if (panel.getAttachedPanels().isEmpty()
&& thisCard.getCounters().equals(otherCard.getCounters())
&& (thisCard.isSick() == otherCard.isSick())

View File

@@ -16,7 +16,7 @@ public class CardDetailPanelTest {
@Test(groups = { "UnitTest", "fast" }, enabled = false)
public void cardDetailPanelTest1() {
try {
CardDetailPanel dialog = new CardDetailPanel(null);
CardDetailPanel dialog = new CardDetailPanel();
// dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
Assert.assertNotNull(dialog);

View File

@@ -8,8 +8,6 @@ import java.util.Map.Entry;
import com.google.common.collect.Sets;
import forge.GuiBase;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CardUtil;
@@ -20,6 +18,8 @@ import forge.item.InventoryItemFromSet;
import forge.item.PreconDeck;
import forge.item.SealedProduct;
import forge.util.Lang;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
public class CardDetailUtil {
private CardDetailUtil() {
@@ -51,12 +51,17 @@ public class CardDetailUtil {
}
}
public static DetailColors getBorderColor(final CardStateView card, final boolean canShow) {
return getBorderColors(card.getColors(), card.isLand(), canShow, false).iterator().next();
}
@Deprecated
public static DetailColors getBorderColor(final Card card, boolean canShow) {
return getBorderColors(card.determineColor(), card.isLand(), canShow, false).get(0);
}
public static DetailColors getBorderColor(final ColorSet cardColors, final boolean isLand, boolean canShow) {
return getBorderColors(cardColors, isLand, canShow, false).get(0);
}
@Deprecated
public static List<DetailColors> getBorderColors(final Card card, boolean canShow, boolean supportMultiple) {
return getBorderColors(card.determineColor(), card.isLand(), canShow, supportMultiple);
}
@@ -157,6 +162,7 @@ public class CardDetailUtil {
return item.getName();
}
@Deprecated
public static String formatCardType(final Card card) {
final ArrayList<String> list = card.getType();
final StringBuilder sb = new StringBuilder();
@@ -200,6 +206,50 @@ public class CardDetailUtil {
return sb.toString();
}
public static String formatCardType(final CardStateView card) {
final List<String> list = card.getType();
final StringBuilder sb = new StringBuilder();
final List<String> superTypes = new ArrayList<String>();
final List<String> cardTypes = new ArrayList<String>();
final List<String> subTypes = new ArrayList<String>();
final boolean allCreatureTypes = list.contains("AllCreatureTypes");
for (final String t : list) {
if (allCreatureTypes && t.equals("AllCreatureTypes")) {
continue;
}
if (CardType.isASuperType(t) && !superTypes.contains(t)) {
superTypes.add(t);
}
if (CardType.isACardType(t) && !cardTypes.contains(t)) {
cardTypes.add(t);
}
if (CardType.isASubType(t) && !subTypes.contains(t) && (!allCreatureTypes || !CardType.isACreatureType(t))) {
subTypes.add(t);
}
}
for (final String type : superTypes) {
sb.append(type).append(" ");
}
for (final String type : cardTypes) {
sb.append(type).append(" ");
}
if (!subTypes.isEmpty() || allCreatureTypes) {
sb.append("- ");
}
if (allCreatureTypes) {
sb.append("All creature types ");
}
for (final String type : subTypes) {
sb.append(type).append(" ");
}
return sb.toString();
}
@Deprecated
public static String formatPowerToughness(final Card card) {
StringBuilder ptText = new StringBuilder();
if (card.isCreature()) {
@@ -219,11 +269,37 @@ public class CardDetailUtil {
}
return ptText.toString();
}
public static String formatPowerToughness(final CardStateView card) {
StringBuilder ptText = new StringBuilder();
if (card.isCreature()) {
ptText.append(card.getPower()).append(" / ").append(card.getToughness());
}
if (card.isPlaneswalker()) {
if (ptText.length() > 0) {
ptText.insert(0, "P/T: ");
ptText.append(" - ").append("Loy: ");
}
else {
ptText.append("Loyalty: ");
}
ptText.append(card.getLoyalty());
}
return ptText.toString();
}
@Deprecated
public static String formatCardId(final Card card) {
return card.getUniqueNumber() > 0 ? "[" + card.getUniqueNumber() + "]" : "";
}
public static String formatCardId(final CardStateView card) {
final int id = card.getCard().getId();
return id > 0 ? "[" + id + "]" : "";
}
@Deprecated
public static String composeCardText(final Card card, final boolean canShow) {
final StringBuilder area = new StringBuilder();
@@ -438,21 +514,7 @@ public class CardDetailUtil {
if (area.length() != 0) {
area.append("\n");
}
area.append("*Enchanting ");
if (entity instanceof Card) {
final Card c = (Card) entity;
if (!GuiBase.getInterface().mayShowCard(c)) {
area.append("Morph (");
area.append(card.getUniqueNumber());
area.append(")");
} else {
area.append(entity);
}
} else {
area.append(entity);
}
area.append("*");
area.append("*Enchanting ").append(entity).append("*");
}
// enchanted by
@@ -538,8 +600,8 @@ public class CardDetailUtil {
area.append("Must block " + mustBlockThese);
}
//show current storm count for storm cards
if (card.getKeyword().contains("Storm")) {
/*show current storm count for storm cards
if (card.getKeyword().contains("Storm"))
Game game = GuiBase.getInterface().getGame();
if (game != null) {
if (area.length() != 0) {
@@ -547,51 +609,325 @@ public class CardDetailUtil {
}
area.append("Current Storm Count: " + game.getStack().getCardsCastThisTurn().size());
}
}
}*/
return area.toString();
}
public static String composeCardText(final CardStateView state, final boolean canShow) {
final CardView card = state.getCard();
final StringBuilder area = new StringBuilder();
// Token
if (card.isToken()) {
area.append("Token");
}
if (canShow) {
// card text
if (area.length() != 0) {
area.append("\n");
}
String text = state.getText();
// LEVEL [0-9]+-[0-9]+
// LEVEL [0-9]+\+
String regex = "LEVEL [0-9]+-[0-9]+ ";
text = text.replaceAll(regex, "$0\r\n");
regex = "LEVEL [0-9]+\\+ ";
text = text.replaceAll(regex, "\r\n$0\r\n");
// displays keywords that have dots in them a little better:
regex = "\\., ";
text = text.replaceAll(regex, ".\r\n");
area.append(text);
}
if (card.isPhasedOut()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Phased Out");
}
// text changes
final Map<String, String> changedColorWords = state.getChangedColorWords(),
changedTypes = state.getChangedTypes();
if (!(changedColorWords.isEmpty() && changedTypes.isEmpty())) {
if (area.length() != 0) {
area.append("\n");
}
}
for (final Entry<String, String> e : Sets.union(changedColorWords.entrySet(), changedTypes.entrySet())) {
// ignore lower case and plural form keys, to avoid duplicity
if (Character.isUpperCase(e.getKey().charAt(0)) &&
!CardUtil.singularTypes.containsKey(e.getKey())) {
area.append("Text changed: all instances of ");
if (e.getKey().equals("Any")) {
if (changedColorWords.containsKey(e.getKey())) {
area.append("color words");
} else if (forge.card.CardType.getBasicTypes().contains(e.getValue())) {
area.append("basic land types");
} else {
area.append("creature types");
}
} else {
area.append(e.getKey());
}
area.append(" are replaced by ");
area.append(e.getValue());
area.append(".\n");
}
}
// counter text
for (final Entry<CounterType, Integer> c : card.getCounters().entrySet()) {
if (c.getValue().intValue() != 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append(c.getKey().getName() + " counters: ");
area.append(c.getValue());
}
}
if (state.isCreature()) {
final int damage = card.getDamage();
if (damage > 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Damage: " + damage);
}
}
if (state.isCreature() || state.isPlaneswalker()) {
final int assigned = card.getAssignedDamage();
if (assigned > 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Assigned Damage: " + assigned);
}
}
// Regeneration Shields
final int regenShields = card.getRegenerationShields();
if (regenShields > 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Regeneration Shields: ").append(regenShields);
}
// Damage Prevention
final int preventNextDamage = card.getPreventNextDamage();
if (preventNextDamage > 0) {
area.append("\n");
area.append("Prevent the next ").append(preventNextDamage).append(" damage that would be dealt to ");
area.append(state.getName()).append(" this turn.");
}
// top revealed
/*
if ((card.hasKeyword("Play with the top card of your library revealed.") || card
.hasKeyword("Players play with the top card of their libraries revealed."))
&& card.getController() != null
&& (card.isInZone(ZoneType.Battlefield) || (card.isInZone(ZoneType.Command) && !card.isCommander()))
&& !card.getController().getZone(ZoneType.Library).isEmpty()) {
area.append("\r\nTop card of your library: ");
area.append(card.getController().getCardsIn(ZoneType.Library, 1));
if (card.hasKeyword("Players play with the top card of their libraries revealed.")) {
for (final Player p : card.getController().getAllOtherPlayers()) {
if (p.getZone(ZoneType.Library).isEmpty()) {
area.append(p.getName());
area.append("'s library is empty.");
} else {
area.append("\r\nTop card of ");
area.append(p.getName());
area.append("'s library: ");
area.append(p.getCardsIn(ZoneType.Library, 1));
}
}
}
}*/
// chosen type
if (!card.getChosenType().equals("")) {
if (area.length() != 0) {
area.append("\n");
}
area.append("(chosen type: ");
area.append(card.getChosenType());
area.append(")");
}
// chosen color
if (!card.getChosenColors().isEmpty()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("(chosen colors: ");
area.append(Lang.joinHomogenous(card.getChosenColors()));
area.append(")");
}
// chosen player
if (card.getChosenPlayer() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("(chosen player: " + card.getChosenPlayer() + ")");
}
// named card
if (!card.getNamedCard().equals("")) {
if (area.length() != 0) {
area.append("\n");
}
area.append("(named card: ");
area.append(card.getNamedCard());
area.append(")");
}
// equipping
if (card.getEquipping() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("=Equipping ");
area.append(card.getEquipping());
area.append("=");
}
// equipped by
if (card.getEquippedBy().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("=Equipped by ");
for (final Iterator<CardView> it = card.getEquippedBy().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
}
}
area.append("=");
}
// enchanting
if (card.getEnchantingCard() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("*Enchanting ").append(card.getEnchantingCard()).append("*");
}
if (card.getEnchantingPlayer() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("*Enchanting ").append(card.getEnchantingPlayer()).append("*");
}
// enchanted by
if (card.getEnchantedBy().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("*Enchanted by ");
for (final Iterator<CardView> it = card.getEnchantedBy().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
}
}
area.append("*");
}
// controlling
if (card.getGainControlTargets().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("+Controlling: ");
for (final Iterator<CardView> it = card.getGainControlTargets().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
}
}
area.append("+");
}
// cloned via
if (card.getCloneOrigin() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("^Cloned via: ");
area.append(card.getCloneOrigin().getState().getName());
area.append("^");
}
// Imprint
if (card.getImprinted().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Imprinting: ");
for (final Iterator<CardView> it = card.getImprinted().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
}
}
}
// Haunt
if (card.getHauntedBy().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Haunted by: ");
for (final Iterator<CardView> it = card.getHauntedBy().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
}
}
}
if (card.getHaunting() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Haunting " + card.getHaunting());
}
// must block
if (card.getMustBlock().iterator().hasNext()) {
if (area.length() != 0) {
area.append("\n");
}
final String mustBlockThese = Lang.joinHomogenous(card.getMustBlock());
area.append("Must block " + mustBlockThese);
}
/*show current storm count for storm cards
if (state.hasStorm()) {
Game game = GuiBase.getInterface().getGame();
if (game != null) {
if (area.length() != 0) {
area.append("\n\n");
}
area.append("Current Storm Count: " + game.getStack().getCardsCastThisTurn().size());
}
}*/
return area.toString();
}
@Deprecated
public static boolean isCardFlippable(Card card) {
return card.isDoubleFaced() || card.isFlipCard() || card.isFaceDown();
}
/**
* Card characteristic state machine.
* <p>
* Given a card and a state in terms of {@code CardCharacteristicName} this
* will determine whether there is a valid alternate {@code CardCharacteristicName}
* state for that card.
*
* @param card the {@code Card}
* @param currentState not necessarily {@code card.getCurState()}
* @return the alternate {@code CardCharacteristicName} state or default if not applicable
*/
public static CardCharacteristicName getAlternateState(final Card card, CardCharacteristicName currentState) {
// Default. Most cards will only ever have an "Original" state represented by a single image.
CardCharacteristicName alternateState = CardCharacteristicName.Original;
if (card.isDoubleFaced()) {
if (currentState == CardCharacteristicName.Original) {
alternateState = CardCharacteristicName.Transformed;
}
}
else if (card.isFlipCard()) {
if (currentState == CardCharacteristicName.Original) {
alternateState = CardCharacteristicName.Flipped;
}
}
else if (card.isFaceDown()) {
if (currentState == CardCharacteristicName.Original) {
alternateState = CardCharacteristicName.FaceDown;
}
else if (GuiBase.getInterface().mayShowCard(card)) {
alternateState = CardCharacteristicName.Original;
}
else {
alternateState = currentState;
}
}
return alternateState;
}
}

View File

@@ -1,5 +1,6 @@
package forge.control;
import com.google.common.collect.Sets;
import com.google.common.eventbus.Subscribe;
import forge.FThreads;
@@ -18,6 +19,7 @@ import forge.properties.ForgePreferences.FPref;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
import forge.util.maps.MapOfLists;
import forge.view.CardView;
import org.apache.commons.lang3.tuple.Pair;
@@ -76,12 +78,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
if (turnUpdPlanned.getAndSet(true)) { return null; }
final Game game = GuiBase.getInterface().getGame(); // to make sure control gets a correct game instance
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
turnUpdPlanned.set(false);
GuiBase.getInterface().updateTurn(event, game);
GuiBase.getInterface().updateTurn(event);
}
});
return null;
@@ -225,7 +226,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
return null;
}
private final Set<Card> cardsToUpdate = new HashSet<Card>();
private final Set<CardView> cardsToUpdate = Sets.newHashSet();
private final Runnable updCards = new Runnable() {
@Override
public void run() {
@@ -288,7 +289,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
return null;
}
private Void updateSingleCard(Card c) {
private Void updateSingleCard(final CardView c) {
boolean needUpdate = false;
synchronized (cardsToUpdate) {
needUpdate = cardsToUpdate.isEmpty();

View File

@@ -1,7 +1,7 @@
package forge.events;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.view.CardView;
import forge.view.GameEntityView;
/**
* TODO: Write javadoc for this type.
@@ -9,16 +9,16 @@ import forge.game.card.Card;
*/
public class UiEventAttackerDeclared extends UiEvent {
public final Card attacker;
public final GameEntity defender;
public final CardView attacker;
public final GameEntityView defender;
public UiEventAttackerDeclared(Card card, GameEntity currentDefender) {
public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) {
attacker = card;
defender = currentDefender;
}
@Override
public <T> T visit(IUiEventVisitor<T> visitor) {
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
@@ -27,6 +27,6 @@ public class UiEventAttackerDeclared extends UiEvent {
*/
@Override
public String toString() {
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender.getName() );
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender );
}
}

View File

@@ -1,19 +1,19 @@
package forge.events;
import forge.game.card.Card;
import forge.view.CardView;
public class UiEventBlockerAssigned extends UiEvent {
public final Card blocker;
public final Card attackerBeingBlocked;
public final CardView blocker;
public final CardView attackerBeingBlocked;
public UiEventBlockerAssigned(Card card, Card currentAttacker) {
public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) {
blocker = card;
attackerBeingBlocked = currentAttacker;
}
@Override
public <T> T visit(IUiEventVisitor<T> visitor) {
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}

View File

@@ -8,22 +8,21 @@ import forge.GuiBase;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.Deck;
import forge.game.Game;
import forge.game.GameType;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IButton;
import forge.interfaces.IGuiBase;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
import forge.view.IGameView;
public abstract class GauntletWinLoseController {
private final Game lastGame;
private final IGameView lastGame;
private final IWinLoseView<? extends IButton> view;
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, Game lastGame0) {
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final IGameView game0) {
view = view0;
lastGame = lastGame0;
lastGame = game0;
}
public void showOutcome() {
@@ -43,8 +42,6 @@ public abstract class GauntletWinLoseController {
// Generic event record.
lstEventRecords.set(gd.getCompleted(), "Ongoing");
final Match match = lastGame.getMatch();
// Match won't be saved until it is over. This opens up a cheat
// or failsafe mechanism (depending on your perspective) in which
// the player can restart Forge to replay a match.
@@ -53,14 +50,14 @@ public abstract class GauntletWinLoseController {
LobbyPlayer questPlayer = GuiBase.getInterface().getQuestPlayer();
// In all cases, update stats.
lstEventRecords.set(gd.getCompleted(), match.getGamesWonBy(questPlayer) + " - "
+ (match.getPlayedGames().size() - match.getGamesWonBy(questPlayer)));
lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - "
+ (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer)));
if (match.isMatchOver()) {
if (lastGame.isMatchOver()) {
gd.setCompleted(gd.getCompleted() + 1);
// Win match case
if (match.isWonBy(questPlayer)) {
if (lastGame.isMatchWonBy(questPlayer)) {
// Gauntlet complete: Remove save file
if (gd.getCompleted() == lstDecks.size()) {
icon = FSkinProp.ICO_QUEST_COIN;
@@ -112,7 +109,7 @@ public abstract class GauntletWinLoseController {
}
public final boolean actionOnContinue() {
if (lastGame.getMatch().isMatchOver()) {
if (lastGame.isMatchOver()) {
// To change the AI deck, we have to create a new match.
GauntletData gd = FModel.getGauntletData();
Deck aiDeck = gd.getDecks().get(gd.getCompleted());

View File

@@ -15,16 +15,11 @@ import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.deck.CardPool;
import forge.events.UiEvent;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.event.GameEventTurnBegan;
import forge.game.phase.PhaseType;
import forge.game.player.IHasIcon;
import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
@@ -33,7 +28,10 @@ import forge.match.input.InputQueue;
import forge.sound.IAudioClip;
import forge.sound.IAudioMusic;
import forge.util.ITriggerEvent;
import forge.view.CardView;
import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView;
public interface IGuiBase {
boolean isRunningOnDesktop();
@@ -42,55 +40,55 @@ public interface IGuiBase {
void invokeInEdtAndWait(final Runnable proc);
boolean isGuiThread();
String getAssetsDir();
boolean mayShowCard(Card card);
boolean mayShowCard(CardView card);
ISkinImage getSkinIcon(FSkinProp skinProp);
ISkinImage getUnskinnedIcon(String path);
void showBugReportDialog(String title, String text, boolean showExitAppBtn);
int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption);
int showCardOptionDialog(Card card, String message, String title, FSkinProp icon, String[] options, int defaultOption);
int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption);
<T> T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions);
<T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display);
<T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode);
final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode);
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
String showFileDialog(String title, String defaultDir);
File getSaveFile(File defaultFile);
void showCardList(final String title, final String message, final List<PaperCard> list);
boolean showBoxedProduct(final String title, final String message, final List<PaperCard> list);
void fireEvent(UiEvent e);
void setCard(Card card);
void setCard(CardView card);
void showCombat(Combat combat);
void setUsedToPay(Card card, boolean b);
void setHighlighted(Player player, boolean b);
void setUsedToPay(CardView card, boolean b);
void setHighlighted(PlayerView player, boolean b);
void showPromptMessage(String message);
boolean stopAtPhase(Player playerTurn, PhaseType phase);
boolean stopAtPhase(PlayerView playerTurn, PhaseType phase);
InputQueue getInputQueue();
Game getGame();
IGameView getGame();
IButton getBtnOK();
IButton getBtnCancel();
void focusButton(IButton button);
void flashIncorrectAction();
void updatePhase();
void updateTurn(GameEventTurnBegan event, Game game);
void updateTurn(PlayerView player);
void updatePlayerControl();
void enableOverlay();
void disableOverlay();
void finishGame();
Object showManaPool(Player player);
void hideManaPool(Player player, Object zoneToRestore);
boolean openZones(List<ZoneType> zones, Map<Player, Object> players);
void restoreOldZones(Map<Player, Object> playersToRestoreZonesFor);
Object showManaPool(PlayerView player);
void hideManaPool(PlayerView player, Object zoneToRestore);
boolean openZones(List<ZoneType> zones, Map<PlayerView, Object> players);
void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor);
void updateStack();
void updateZones(List<Pair<Player, ZoneType>> zonesToUpdate);
void updateCards(Set<Card> cardsToUpdate);
void refreshCardDetails(Collection<Card> cards);
void updateManaPool(List<Player> manaPoolUpdate);
void updateLives(List<Player> livesUpdate);
void updateZones(List<Pair<PlayerView, ZoneType>> zonesToUpdate);
void updateCards(Set<CardView> cardsToUpdate);
void refreshCardDetails(Collection<CardView> cards);
void updateManaPool(List<PlayerView> manaPoolUpdate);
void updateLives(List<PlayerView> livesUpdate);
void endCurrentGame();
void startMatch(GameType gauntletType, List<RegisteredPlayer> starter);
void setPanelSelection(Card hostCard);
Map<Card, Integer> getDamageToAssign(Card attacker, List<Card> blockers,
int damageDealt, GameEntity defender, boolean overrideOrder);
void setPanelSelection(CardView hostCard);
Map<CardView, Integer> getDamageToAssign(CardView attacker, List<CardView> blockers,
int damageDealt, GameEntityView defender, boolean overrideOrder);
SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent);
void hear(LobbyPlayer player, String message);
int getAvatarCount();

View File

@@ -1,23 +1,23 @@
package forge.limited;
import forge.GuiBase;
import forge.game.Game;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
import forge.view.IGameView;
public abstract class LimitedWinLoseController {
private final Game lastGame;
private final IGameView lastGame;
private final boolean wonMatch;
private final IWinLoseView<? extends IButton> view;
private GauntletMini gauntlet;
private boolean nextRound = false;
public LimitedWinLoseController(IWinLoseView<? extends IButton> view0, Game lastGame0) {
public LimitedWinLoseController(IWinLoseView<? extends IButton> view0, final IGameView game0) {
view = view0;
lastGame = lastGame0;
lastGame = game0;
gauntlet = FModel.getGauntletMini();
wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getGuiPlayer());
wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getGuiPlayer());
}
public void showOutcome() {
@@ -29,10 +29,9 @@ public abstract class LimitedWinLoseController {
resetView();
nextRound = false;
if (lastGame.getOutcome().isWinner(GuiBase.getInterface().getGuiPlayer())) {
if (lastGame.isWinner(GuiBase.getInterface().getGuiPlayer())) {
gauntlet.addWin();
}
else {
} else {
gauntlet.addLoss();
}
@@ -41,7 +40,7 @@ public abstract class LimitedWinLoseController {
showOutcome(new Runnable() {
@Override
public void run() {
if (!lastGame.getMatch().isMatchOver()) {
if (!lastGame.isMatchOver()) {
showTournamentInfo("Tournament Info");
return;
}

View File

@@ -5,12 +5,11 @@ import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.ITriggerEvent;
public interface Input {
void showMessageInitial();
boolean selectCard(Card c, ITriggerEvent triggerEvent);
boolean selectCard(Card card, ITriggerEvent triggerEvent);
void selectAbility(SpellAbility ab);
void selectPlayer(Player player, ITriggerEvent triggerEvent);

View File

@@ -248,9 +248,9 @@ public class InputAttack extends InputSyncronizedBase {
return false;
}
private final void setCurrentDefender(GameEntity def) {
private final void setCurrentDefender(final GameEntity def) {
currentDefender = def;
for (GameEntity ge : defenders) {
for (final GameEntity ge : defenders) {
if (ge instanceof Card) {
GuiBase.getInterface().setUsedToPay((Card)ge, ge == def);
}
@@ -262,16 +262,16 @@ public class InputAttack extends InputSyncronizedBase {
updateMessage();
}
private final void activateBand(AttackingBand band) {
private final void activateBand(final AttackingBand band) {
if (activeBand != null) {
for (Card card : activeBand.getAttackers()) {
for (final Card card : activeBand.getAttackers()) {
GuiBase.getInterface().setUsedToPay(card, false);
}
}
activeBand = band;
if (activeBand != null) {
for(Card card : activeBand.getAttackers()) {
for (final Card card : activeBand.getAttackers()) {
GuiBase.getInterface().setUsedToPay(card, true);
}
}
@@ -279,8 +279,8 @@ public class InputAttack extends InputSyncronizedBase {
//only enable banding message and actions if a creature that can attack has banding
private boolean isBandingPossible() {
List<Card> possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield);
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.hasKeyword("Banding"))) {
final List<Card> possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield);
for (final Card c : Iterables.filter(possibleAttackers, CardPredicates.hasKeyword("Banding"))) {
if (c.isCreature() && CombatUtil.canAttack(c, currentDefender, combat)) {
return true;
}

View File

@@ -108,7 +108,7 @@ public abstract class InputBase implements java.io.Serializable, Input {
}
@Override
public void selectAbility(SpellAbility ab) { }
public void selectAbility(final SpellAbility ab) { }
@Override
public final void selectButtonCancel() {
@@ -131,12 +131,12 @@ public abstract class InputBase implements java.io.Serializable, Input {
protected boolean onCardSelected(final Card c, final ITriggerEvent triggerEvent) {
return false;
}
protected void onPlayerSelected(final Player p, final ITriggerEvent triggerEvent) {}
protected void onPlayerSelected(final Player player, final ITriggerEvent triggerEvent) {}
protected void onCancel() {}
protected void onOk() {}
// to remove need for CMatchUI dependence
protected final void showMessage(String message) {
protected final void showMessage(final String message) {
GuiBase.getInterface().showPromptMessage(message);
}
@@ -144,7 +144,7 @@ public abstract class InputBase implements java.io.Serializable, Input {
GuiBase.getInterface().flashIncorrectAction();
}
protected String getTurnPhasePriorityMessage(Game game) {
protected String getTurnPhasePriorityMessage(final Game game) {
final PhaseHandler ph = game.getPhaseHandler();
final StringBuilder sb = new StringBuilder();

View File

@@ -17,19 +17,19 @@
*/
package forge.match.input;
import forge.FThreads;
import forge.GuiBase;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.ITriggerEvent;
import forge.util.gui.SOptionPane;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.atomic.AtomicReference;
import forge.FThreads;
import forge.GuiBase;
import forge.game.spellability.SpellAbility;
import forge.util.ITriggerEvent;
import forge.util.gui.SOptionPane;
import forge.view.CardView;
import forge.view.IGameView;
import forge.view.PlayerView;
/**
* <p>
* GuiInput class.
@@ -42,11 +42,11 @@ public class InputProxy implements Observer {
/** The input. */
private AtomicReference<Input> input = new AtomicReference<Input>();
private Game game = null;
private IGameView game = null;
// private static final boolean DEBUG_INPUT = true; // false;
public void setGame(Game game0) {
public void setGame(IGameView game0) {
game = game0;
GuiBase.getInterface().getInputQueue().addObserver(this);
}
@@ -120,8 +120,8 @@ public class InputProxy implements Observer {
* @param player
* a {@link forge.game.player.Player} object.
*/
public final void selectPlayer(final Player player, final ITriggerEvent triggerEvent) {
Input inp = getInput();
public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
inp.selectPlayer(player, triggerEvent);
}
@@ -132,20 +132,20 @@ public class InputProxy implements Observer {
* selectCard.
* </p>
*
* @param card
* @param cardView
* a {@link forge.game.card.Card} object.
* @param triggerEvent
*/
public final boolean selectCard(final Card card, final ITriggerEvent triggerEvent) {
Input inp = getInput();
public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
return inp.selectCard(card, triggerEvent);
return inp.selectCard(cardView, triggerEvent);
}
return false;
}
public final void selectAbility(SpellAbility ab) {
Input inp = getInput();
public final void selectAbility(final SpellAbility ab) {
final Input inp = getInput();
if (inp != null) {
inp.selectAbility(ab);
}

View File

@@ -17,7 +17,8 @@
*/
package forge.match.input;
import forge.game.Game;
import forge.view.IGameView;
import java.util.Observable;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
@@ -63,7 +64,7 @@ public class InputQueue extends Observable {
*
* @return a {@link forge.gui.input.InputBase} object.
*/
public final Input getActualInput(Game game) {
public final Input getActualInput(IGameView game) {
Input topMost = inputStack.peek(); // incoming input to Control
if (topMost != null && !game.isGameOver()) {
return topMost;

View File

@@ -1,9 +1,5 @@
package forge.player;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.game.Game;
import forge.game.player.RegisteredPlayer;
import forge.model.FModel;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
@@ -69,13 +65,4 @@ public final class GamePlayerUtil {
return newName;
}
public static RegisteredPlayer getGuiRegisteredPlayer(Game game) {
LobbyPlayer guiPlayer = GuiBase.getInterface().getGuiPlayer();
for (RegisteredPlayer player : game.getMatch().getPlayers()) {
if (player.getPlayer() == guiPlayer) {
return player;
}
}
return null;
}
}

View File

@@ -1,14 +1,30 @@
package forge.player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.Range;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import forge.LobbyPlayer;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
@@ -20,11 +36,14 @@ import forge.deck.DeckSection;
import forge.events.UiEventAttackerDeclared;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameLog;
import forge.game.GameLogEntryType;
import forge.game.GameObject;
import forge.game.GameOutcome;
import forge.game.GameType;
import forge.game.ability.effects.CharmEffect;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardShields;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
@@ -37,6 +56,7 @@ import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.player.PlayerController;
import forge.game.player.RegisteredPlayer;
import forge.game.replacement.ReplacementEffect;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
@@ -48,7 +68,17 @@ import forge.game.zone.MagicStack;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.match.input.*;
import forge.match.input.ButtonUtil;
import forge.match.input.InputAttack;
import forge.match.input.InputBase;
import forge.match.input.InputBlock;
import forge.match.input.InputConfirm;
import forge.match.input.InputConfirmMulligan;
import forge.match.input.InputPassPriority;
import forge.match.input.InputProliferate;
import forge.match.input.InputSelectCardsForConvoke;
import forge.match.input.InputSelectCardsFromList;
import forge.match.input.InputSelectEntitiesFromList;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.util.ITriggerEvent;
@@ -57,13 +87,12 @@ import forge.util.TextUtil;
import forge.util.gui.SGuiChoose;
import forge.util.gui.SGuiDialog;
import forge.util.gui.SOptionPane;
import org.apache.commons.lang3.Range;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import forge.view.CardView;
import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView;
import forge.view.StackItemView;
import forge.view.ViewUtil;
/**
@@ -71,13 +100,21 @@ import java.util.*;
*
* Handles phase skips for now.
*/
public class PlayerControllerHuman extends PlayerController {
public class PlayerControllerHuman extends PlayerController implements IGameView {
public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp) {
super(game0, p, lp);
// aggressively cache a view for each player
for (final Player player : game.getRegisteredPlayers()) {
getPlayerView(player);
}
// aggressively cache a view for each card
for (final Card c : game.getCardsInGame()) {
getCardView(c);
}
}
public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) {
return !GuiBase.getInterface().stopAtPhase(turn, phase);
return !GuiBase.getInterface().stopAtPhase(getPlayerView(turn), phase);
}
/**
@@ -162,27 +199,31 @@ public class PlayerControllerHuman extends PlayerController {
* @see forge.game.player.PlayerController#assignCombatDamage()
*/
@Override
public Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender, boolean overrideOrder) {
public Map<Card, Integer> assignCombatDamage(final Card attacker,
final List<Card> blockers, final int damageDealt,
final GameEntity defender, final boolean overrideOrder) {
// Attacker is a poor name here, since the creature assigning damage
// could just as easily be the blocker.
Map<Card, Integer> map;
final Map<Card, Integer> map = Maps.newHashMap();
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
map = new HashMap<Card, Integer>();
map.put(null, damageDealt);
}
else {
} else {
final List<CardView> vBlockers = Lists.transform(blockers, FN_GET_CARD_VIEW);
if ((attacker.hasKeyword("Trample") && defender != null) || (blockers.size() > 1)) {
map = GuiBase.getInterface().getDamageToAssign(attacker, blockers, damageDealt, defender, overrideOrder);
}
else {
map = new HashMap<Card, Integer>();
final CardView vAttacker = getCardView(attacker);
final GameEntityView vDefender = getGameEntityView(defender);
final Map<CardView, Integer> result = GuiBase.getInterface().getDamageToAssign(vAttacker, vBlockers, damageDealt, vDefender, overrideOrder);
for (final Entry<CardView, Integer> e : result.entrySet()) {
map.put(getCard(e.getKey()), e.getValue());
}
} else {
map.put(blockers.get(0), damageDealt);
}
}
return map;
}
private final boolean assignDamageAsIfNotBlocked(Card attacker) {
private final boolean assignDamageAsIfNotBlocked(final Card attacker) {
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")
|| (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
&& SGuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?"));
@@ -235,8 +276,9 @@ public class PlayerControllerHuman extends PlayerController {
Card singleChosen = chooseSingleEntityForEffect(sourceList, sa, title, isOptional);
return singleChosen == null ? Lists.<Card>newArrayList() : Lists.newArrayList(singleChosen);
}
GuiBase.getInterface().setPanelSelection(sa.getHostCard());
GuiBase.getInterface().setPanelSelection(getCardView(sa.getHostCard()));
// try to use InputSelectCardsFromList when possible
boolean cardsAreInMyHandOrBattlefield = true;
for(Card c : sourceList) {
@@ -255,7 +297,7 @@ public class PlayerControllerHuman extends PlayerController {
return Lists.newArrayList(sc.getSelected());
}
return SGuiChoose.many(title, "Chosen Cards", min, max, sourceList, sa.getHostCard());
return SGuiChoose.many(title, "Chosen Cards", min, max, sourceList, getCardView(sa.getHostCard()));
}
@Override
@@ -384,21 +426,27 @@ public class PlayerControllerHuman extends PlayerController {
}
@Override
public List<Card> orderBlockers(Card attacker, List<Card> blockers) {
GuiBase.getInterface().setPanelSelection(attacker);
return SGuiChoose.order("Choose Damage Order for " + attacker, "Damaged First", blockers, attacker);
}
@Override
public List<Card> orderBlocker(final Card attacker, final Card blocker, final List<Card> oldBlockers) {
GuiBase.getInterface().setPanelSelection(attacker);
return SGuiChoose.insertInList("Choose blocker after which to place " + attacker + " in damage order; cancel to place it first", blocker, oldBlockers);
public List<Card> orderBlockers(final Card attacker, final List<Card> blockers) {
final CardView vAttacker = getCardView(attacker);
GuiBase.getInterface().setPanelSelection(vAttacker);
final List<CardView> choices = SGuiChoose.order("Choose Damage Order for " + vAttacker, "Damaged First", getCardViews(blockers), vAttacker);
return getCards(choices);
}
@Override
public List<Card> orderAttackers(Card blocker, List<Card> attackers) {
GuiBase.getInterface().setPanelSelection(blocker);
return SGuiChoose.order("Choose Damage Order for " + blocker, "Damaged First", attackers, blocker);
public List<Card> orderBlocker(final Card attacker, final Card blocker, final List<Card> oldBlockers) {
final CardView vAttacker = getCardView(attacker);
GuiBase.getInterface().setPanelSelection(vAttacker);
final List<CardView> choices = SGuiChoose.insertInList("Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first", getCardView(blocker), getCardViews(oldBlockers));
return getCards(choices);
}
@Override
public List<Card> orderAttackers(final Card blocker, final List<Card> attackers) {
final CardView vBlocker = getCardView(blocker);
GuiBase.getInterface().setPanelSelection(vBlocker);
final List<CardView> choices = SGuiChoose.order("Choose Damage Order for " + vBlocker, "Damaged First", getCardViews(attackers), vBlocker);
return getCards(choices);
}
/* (non-Javadoc)
@@ -630,7 +678,7 @@ public class PlayerControllerHuman extends PlayerController {
//ensure they're declared and then delay slightly so user can see as much
for (Pair<Card, GameEntity> attacker : mandatoryAttackers) {
combat.addAttacker(attacker.getLeft(), attacker.getRight());
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(attacker.getLeft(), attacker.getRight()));
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(getCardView(attacker.getLeft()), getGameEntityView(attacker.getRight())));
}
try {
Thread.sleep(FControlGamePlayback.combatDelay);
@@ -1168,4 +1216,342 @@ public class PlayerControllerHuman extends PlayerController {
public boolean isGuiPlayer() {
return lobbyPlayer == GuiBase.getInterface().getGuiPlayer();
}
/*
* What follows are the View methods.
*/
/** Cache of players. */
private final BiMap<Player, PlayerView> players
= HashBiMap.create();
/** Cache of cards. */
private final BiMap<Card, CardView> cards
= HashBiMap.create();
/** Cache of stack items. */
private final BiMap<SpellAbilityStackInstance, StackItemView> stackItems
= HashBiMap.create();
/* (non-Javadoc)
* @see forge.view.IGameView#isCommander()
*/
@Override
public boolean isCommander() {
return game.getRules().hasAppliedVariant(GameType.Commander);
}
/* (non-Javadoc)
* @see forge.view.IGameView#getGameType()
*/
@Override
public GameType getGameType() {
return this.game.getMatch().getRules().getGameType();
}
@Override
public boolean isWinner(final LobbyPlayer p) {
return game.getOutcome() == null ? null : game.getOutcome().isWinner(p);
}
@Override
public LobbyPlayer getWinningPlayer() {
return game.getOutcome() == null ? null : game.getOutcome().getWinningLobbyPlayer();
}
@Override
public int getWinningTeam() {
return game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam();
}
/* (non-Javadoc)
* @see forge.view.IGameView#isFirstGameInMatch()
*/
@Override
public boolean isFirstGameInMatch() {
return this.game.getMatch().getPlayedGames().isEmpty();
}
@Override
public boolean isMatchOver() {
return this.game.getMatch().isMatchOver();
}
@Override
public int getNumPlayedGamesInMatch() {
return this.game.getMatch().getPlayedGames().size();
}
@Override
public boolean isMatchWonBy(final LobbyPlayer p) {
return this.game.getMatch().isWonBy(p);
}
@Override
public int getGamesWonBy(LobbyPlayer p) {
return this.game.getMatch().getGamesWonBy(p);
}
@Override
public GameOutcome.AnteResult getAnteResult() {
return this.game.getOutcome().anteResult.get(player);
}
/* (non-Javadoc)
* @see forge.view.IGameView#isCombatDeclareAttackers()
*/
@Override
public boolean isCombatDeclareAttackers() {
return game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS)
&& game.getCombat() != null;
}
/* (non-Javadoc)
* @see forge.view.IGameView#isGameOver()
*/
@Override
public boolean isGameOver() {
return game.isGameOver();
}
@Override
public int getPoisonCountersToLose() {
return game.getRules().getPoisonCountersToLose();
}
/* (non-Javadoc)
* @see forge.view.IGameView#subscribeToEvents(java.lang.Object)
*/
@Override
public void subscribeToEvents(final Object subscriber) {
game.subscribeToEvents(subscriber);
}
// the following methods should eventually be replaced by methods returning
// View classes
/* (non-Javadoc)
* @see forge.view.IGameView#getCombat()
*/
@Override
public Combat getCombat() {
return game.getCombat();
}
/* (non-Javadoc)
* @see forge.view.IGameView#getGameLog()
*/
@Override
public GameLog getGameLog() {
return game.getGameLog();
}
/* (non-Javadoc)
* @see forge.view.IGameView#getGuiRegisteredPlayer(forge.LobbyPlayer)
*/
@Override
public RegisteredPlayer getGuiRegisteredPlayer(final LobbyPlayer p) {
for (final RegisteredPlayer player : game.getMatch().getPlayers()) {
if (player.getPlayer() == p) {
return player;
}
}
return null;
}
/* (non-Javadoc)
* @see forge.view.IGameView#getRegisteredPlayers()
*/
@Override
public List<PlayerView> getPlayers() {
return Lists.transform(game.getRegisteredPlayers(), FN_GET_PLAYER_VIEW);
}
@Override
public PlayerView getPlayerTurn() {
return getPlayerView(game.getPhaseHandler().getPlayerTurn());
}
@Override
public PhaseType getPhase() {
return game.getPhaseHandler().getPhase();
}
/* (non-Javadoc)
* @see forge.view.IGameView#getStack()
*/
@Override
public List<StackItemView> getStack() {
final List<StackItemView> items = Collections.unmodifiableList(getStack(game.getStack()));
// clear the cache
stackItems.keySet().retainAll(items);
return items;
}
/* (non-Javadoc)
* @see forge.view.IGameView#peekStack()
*/
@Override
public StackItemView peekStack() {
final SpellAbilityStackInstance top =
Iterables.getFirst(game.getStack(), null);
if (top == null) {
return null;
}
return getStack(Lists.newArrayList(top)).iterator().next();
}
private List<StackItemView> getStack(final Iterable<SpellAbilityStackInstance> stack) {
final List<StackItemView> items = Lists.newLinkedList();
for (final SpellAbilityStackInstance si : stack) {
if (stackItems.containsKey(si)) {
items.add(stackItems.get(si));
} else {
final StackItemView newItem = new StackItemView(
si.getSpellAbility().toUnsuppressedString(),
si.getSpellAbility().getSourceTrigger(),
si.getStackDescription(), getCardView(si.getSourceCard()),
getPlayerView(si.getActivator()), si.isAbility(),
si.isOptionalTrigger());
items.add(newItem);
stackItems.put(si, newItem);
}
}
return items;
}
private GameEntityView getGameEntityView(final GameEntity e) {
if (e instanceof Card) {
return getCardView((Card)e);
} else if (e instanceof Player) {
return getPlayerView((Player)e);
}
return null;
}
private PlayerView getPlayerView(final Player p) {
if (p == null) {
return null;
}
final PlayerView view;
if (players.containsKey(p)) {
view = players.get(p);
getPlayerView(p, view);
} else {
view = new PlayerView(p.getLobbyPlayer(), p.getController());
getPlayerView(p, view);
players.put(p, view);
}
return view;
}
private final Function<Player, PlayerView> FN_GET_PLAYER_VIEW = new Function<Player, PlayerView>() {
@Override
public PlayerView apply(final Player input) {
return getPlayerView(input);
}
};
private Player getPlayer(final PlayerView p) {
return players.inverse().get(p);
}
private void getPlayerView(final Player p, final PlayerView view) {
view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; "));
view.setKeywords(p.getKeywords());
view.setLife(p.getLife());
view.setMaxHandSize(p.getMaxHandSize());
view.setNumDrawnThisTurn(p.getNumDrawnThisTurn());
view.setPoisonCounters(p.getPoisonCounters());
view.setPreventNextDamage(p.getPreventNextDamageTotalShields());
view.setHasUnlimitedHandSize(p.isUnlimitedHandSize());
view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante)));
view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield)));
view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile)));
view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false)));
view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard)));
view.setHandCards(getCardViews(p.getCardsIn(ZoneType.Hand)));
view.setLibraryCards(getCardViews(p.getCardsIn(ZoneType.Library)));
}
private CardView getCardView(final Card c) {
if (c == null) {
return null;
}
final CardView view;
if (cards.containsKey(c)) {
view = cards.get(c);
writeCardToView(c, view);
} else {
view = new CardView(c, c.getUniqueNumber());
writeCardToView(c, view);
cards.put(c, view);
}
return view;
}
private final Function<Card, CardView> FN_GET_CARD_VIEW = new Function<Card, CardView>() {
@Override
public CardView apply(final Card input) {
return getCardView(input);
}
};
private List<CardView> getCardViews(final List<Card> cards) {
return Lists.transform(cards, FN_GET_CARD_VIEW);
}
private Card getCard(final CardView c) {
return cards.inverse().get(c);
}
private final Function<CardView, Card> FN_GET_CARD = new Function<CardView, Card>() {
@Override
public Card apply(final CardView input) {
return getCard(input);
}
};
private List<Card> getCards(final List<CardView> cards) {
return Lists.transform(cards, FN_GET_CARD);
}
private void writeCardToView(final Card c, final CardView view) {
if (!c.canBeShownTo(player)) {
view.getOriginal().reset();
view.getAlternate().reset();
return;
}
// First, write the values independent of other views.
ViewUtil.writeNonDependentCardViewProperties(c, view);
// Next, write the values that depend on other views.
view.setOwner(getPlayerView(c.getOwner()));
view.setController(getPlayerView(c.getController()));
view.setAttacking(game.getCombat() != null && game.getCombat().isAttacking(c));
view.setBlocking(game.getCombat() != null && game.getCombat().isBlocking(c));
view.setChosenPlayer(getPlayerView(c.getChosenPlayer()));
view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null)));
view.setEquippedBy(getCardViews(c.getEquippedBy()));
view.setEnchantingCard(getCardView(c.getEnchantingCard()));
view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer()));
view.setEnchantedBy(getCardViews(c.getEnchantedBy()));
view.setFortifiedBy(getCardViews(c.getFortifiedBy()));
view.setGainControlTargets(getCardViews(c.getGainControlTargets()));
view.setCloneOrigin(getCardView(c.getCloneOrigin()));
view.setImprinted(getCardViews(c.getImprinted()));
view.setHauntedBy(getCardViews(c.getHauntedBy()));
view.setHaunting(getCardView(c.getHaunting()));
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : Iterables.transform(c.getMustBlockCards(), FN_GET_CARD_VIEW));
}
@Override
public boolean mayShowCard(final CardView c, final Player viewer) {
return cards.inverse().get(c).canBeShownTo(viewer);
}
@Override
public boolean getDisableAutoYields() {
return this.game.getDisableAutoYields();
}
@Override
public void setDisableAutoYields(final boolean b) {
this.game.setDisableAutoYields(b);
}
}

View File

@@ -34,6 +34,8 @@ import forge.game.zone.ZoneType;
import forge.match.input.InputSelectTargets;
import forge.util.Aggregates;
import forge.util.gui.SGuiChoose;
import forge.view.CardView;
import forge.view.SpellAbilityView;
import java.util.ArrayList;
import java.util.HashMap;
@@ -51,9 +53,8 @@ import java.util.Map;
public class TargetSelection {
private final SpellAbility ability;
public TargetSelection(final SpellAbility sa) {
this.ability = sa;
public TargetSelection(final SpellAbility currentAbility) {
this.ability = currentAbility;
}
private final TargetRestrictions getTgt() {
@@ -70,7 +71,7 @@ public class TargetSelection {
*/
public final boolean chooseTargets(Integer numTargets) {
TargetRestrictions tgt = getTgt();
final TargetRestrictions tgt = getTgt();
final boolean canTarget = tgt != null && tgt.doesTarget();
if (!canTarget) {
throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability);
@@ -81,8 +82,8 @@ public class TargetSelection {
final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability);
final int numTargeted = ability.getTargets().getNumTargeted();
boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets;
boolean hasAllTargets = numTargeted == maxTargets && maxTargets > 0;
final boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets;
final boolean hasAllTargets = numTargeted == maxTargets && maxTargets > 0;
if (maxTargets == 0) { return true; }
// if not enough targets chosen, cancel Ability
@@ -105,8 +106,8 @@ public class TargetSelection {
final boolean choiceResult;
final boolean random = tgt.isRandomTarget();
if (random) {
List<GameObject> candidates = tgt.getAllCandidates(this.ability, true);
GameObject choice = Aggregates.random(candidates);
final List<GameObject> candidates = tgt.getAllCandidates(this.ability, true);
final GameObject choice = Aggregates.random(candidates);
return ability.getTargets().add(choice);
}
else if (zone.size() == 1 && zone.get(0) == ZoneType.Stack) {
@@ -115,7 +116,7 @@ public class TargetSelection {
return this.chooseCardFromStack(mandatory);
}
else {
final List<Card> validTargets = this.getValidCardsToTarget();
final List<CardView> validTargets = this.getValidCardsToTarget();
if (validTargets.isEmpty()) {
//if no valid cards to target and only one valid non-card, auto-target the non-card
//this handles "target opponent" cards, along with any other cards that can only target a single non-card game entity
@@ -162,7 +163,7 @@ public class TargetSelection {
* </p>
* @return
*/
private final List<Card> getValidCardsToTarget() {
private final List<CardView> getValidCardsToTarget() {
final TargetRestrictions tgt = this.getTgt();
final Game game = ability.getActivatingPlayer().getGame();
final List<ZoneType> zone = tgt.getZone();

View File

@@ -7,22 +7,28 @@ import org.apache.commons.lang3.StringUtils;
*
*/
public enum QuestEventDifficulty {
EASY("easy"),
MEDIUM("medium"),
HARD("hard"),
EXPERT("very hard");
String inFile;
private QuestEventDifficulty(String storedInFile) {
EASY ("easy", 1. ),
MEDIUM("medium", 1.5),
HARD ("hard", 2. ),
EXPERT("very hard", 3. );
private final String inFile;
private final double multiplier;
private QuestEventDifficulty(final String storedInFile, final double multiplier) {
inFile = storedInFile;
this.multiplier = multiplier;
}
public final String getTitle() {
return inFile;
}
public static QuestEventDifficulty fromString(String src) {
public final double getMultiplier() {
return this.multiplier;
}
public static QuestEventDifficulty fromString(final String src) {
if ( StringUtils.isBlank(src) )
return MEDIUM; // player have custom files, that didn't specify a valid difficulty

View File

@@ -37,19 +37,21 @@ import forge.quest.data.QuestPreferences.DifficultyPrefs;
import forge.quest.data.QuestPreferences.QPref;
import forge.util.MyRandom;
import forge.util.gui.SGuiChoose;
import forge.view.IGameView;
import forge.view.PlayerView;
public abstract class QuestWinLoseController {
private final Game lastGame;
private final IGameView lastGame;
private final transient boolean wonMatch;
private final transient boolean isAnte;
private final transient QuestController qData;
private final transient QuestEvent qEvent;
public QuestWinLoseController(Game lastGame0) {
lastGame = lastGame0;
public QuestWinLoseController(final IGameView game0) {
lastGame = game0;
qData = FModel.getQuest();
qEvent = qData.getCurrentEvent();
wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getQuestPlayer());
wonMatch = lastGame.isMatchWonBy(GuiBase.getInterface().getQuestPlayer());
isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE);
}
@@ -58,21 +60,21 @@ public abstract class QuestWinLoseController {
final QuestController qc = FModel.getQuest();
// After the first game, reset the card shop pool to be able to buy back anted cards
if (lastGame.getMatch().getPlayedGames().size() == 1) {
if (lastGame.getNumPlayedGamesInMatch() == 1) {
qc.getCards().clearShopList();
qc.getCards().getShopList();
}
final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer();
Player player = null;
for (Player p : lastGame.getRegisteredPlayers()) {
PlayerView player = null;
for (final PlayerView p : lastGame.getPlayers()) {
if (p.getLobbyPlayer().equals(questLobbyPlayer)) {
player = p;
}
}
final Player questPlayer = player;
final PlayerView questPlayer = player;
final boolean matchIsNotOver = !lastGame.getMatch().isMatchOver();
final boolean matchIsNotOver = !lastGame.isMatchOver();
if (matchIsNotOver) {
view.getBtnQuit().setText("Quit (-15 Credits)");
}
@@ -91,11 +93,8 @@ public abstract class QuestWinLoseController {
@Override
public void run() {
if (isAnte) {
//do per-game actions
GameOutcome outcome = lastGame.getOutcome();
// Won/lost cards should already be calculated (even in a draw)
GameOutcome.AnteResult anteResult = outcome.anteResult.get(questPlayer);
GameOutcome.AnteResult anteResult = lastGame.getAnteResult();
if (anteResult != null) {
if (anteResult.wonCards != null) {
qc.getCards().addAllCards(anteResult.wonCards);
@@ -103,7 +102,7 @@ public abstract class QuestWinLoseController {
if (anteResult.lostCards != null) {
qc.getCards().loseCards(anteResult.lostCards);
}
anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.equals(outcome.getWinningPlayer()));
anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.getLobbyPlayer().equals(lastGame.getWinningPlayer()));
}
}
@@ -223,21 +222,14 @@ public abstract class QuestWinLoseController {
// Basic win bonus
final int base = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_BASE);
double multiplier = 1;
switch (qEvent.getDifficulty()) {
case EASY: multiplier = 1; break;
case MEDIUM: multiplier = 1.5; break;
case HARD: multiplier = 2; break;
case EXPERT: multiplier = 3; break;
}
final double multiplier = qEvent.getDifficulty().getMultiplier();
credBase = (int) (base * multiplier);
sb.append(StringUtils.capitalize(qEvent.getDifficulty().getTitle()));
sb.append(" opponent: ").append(credBase).append(" credits.\n");
int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences()
final int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences()
.getPref(QPref.REWARDS_WINS_MULTIPLIER)) * qData.getAchievements().getWin()));
credBase += creditsForPreviousWins;
@@ -247,8 +239,8 @@ public abstract class QuestWinLoseController {
// Gameplay bonuses (for each game win)
boolean hasNeverLost = true;
int lifeDifferenceCredits = 0;
LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer();
final LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer();
for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) {
if (!game.isWinner(localHuman)) {
hasNeverLost = false;

View File

@@ -14,7 +14,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.GuiBase;
import forge.game.card.Card;
import forge.view.CardView;
public class SGuiChoose {
/**
@@ -181,17 +181,17 @@ public class SGuiChoose {
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
}
public static <T> List<T> many(final String title, final String topCaption, int cnt, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> many(final String title, final String topCaption, int cnt, final List<T> sourceChoices, final CardView referenceCard) {
return order(title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false);
}
public static <T> List<T> many(final String title, final String topCaption, int min, int max, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> many(final String title, final String topCaption, int min, int max, final List<T> sourceChoices, final CardView referenceCard) {
int m2 = min >= 0 ? sourceChoices.size() - min : -1;
int m1 = max >= 0 ? sourceChoices.size() - max : -1;
return order(title, topCaption, m1, m2, sourceChoices, null, referenceCard, false);
}
public static <T> List<T> order(final String title, final String top, final List<T> sourceChoices, Card referenceCard) {
public static <T> List<T> order(final String title, final String top, final List<T> sourceChoices, final CardView referenceCard) {
return order(title, top, 0, 0, sourceChoices, null, referenceCard, false);
}
@@ -215,11 +215,10 @@ public class SGuiChoose {
}
private static <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode) {
return GuiBase.getInterface().order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode);
}
// If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine
public static <T> T sortedOneOrNone(final String message, final T[] choices, Comparator<T> comparer) {
if ((choices == null) || (choices.length == 0)) {

View File

@@ -2,8 +2,7 @@ package forge.util.gui;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.game.card.Card;
import forge.view.CardView;
public class SOptionPane {
public static final FSkinProp QUESTION_ICON = FSkinProp.ICO_QUESTION;
@@ -61,7 +60,7 @@ public class SOptionPane {
return GuiBase.getInterface().showOptionDialog(message, title, icon, options, defaultOption);
}
public static int showCardOptionDialog(Card card, String message, String title, FSkinProp icon, String[] options, int defaultOption) {
public static int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption) {
return GuiBase.getInterface().showCardOptionDialog(card, message, title, icon, options, defaultOption);
}