Updating player panels with new style (see issue #102). In this commit player health, poison and damage prevention are displayed as overlays on the player image. The non-turn player image is greyscaled. The four player zone toggle buttons are not yet functional except to display the number of cards in the zone. The name of the active zone is now displayed at the bottom of the game board unless it is the player's hand.

master
lodici 2015-03-17 18:00:49 +00:00
parent 63b7b7aa13
commit d2e985a33b
24 changed files with 1063 additions and 152 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -66,10 +66,14 @@ public enum MagicIcon {
POISON("poison.png"),
HAND("hand.gif"),
HAND2("hand2.png"),
HAND_ZONE("b_hand_zone.png"),
LIBRARY2("library2.gif"),
LIBRARY_ZONE("b_library_zone.png"),
GRAVEYARD("graveyard.gif"),
GRAVEYARD2("graveyard2.gif"),
GRAVEYARD_ZONE("b_graveyard_zone.png"),
EXILE("exile.png"),
EXILE_ZONE("b_exile_zone.png"),
DIFFICULTY("difficulty.png"),
CANNOTTAP("cannottap.png"),
SLEEP("sleep.gif"),

View File

@ -1,5 +1,10 @@
package magic.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import magic.model.action.MagicLoseGameAction;
import magic.model.choice.MagicBuilderManaCost;
import magic.model.event.MagicActivationPriority;
@ -8,15 +13,10 @@ import magic.model.event.MagicSourceManaActivation;
import magic.model.mstatic.MagicLayer;
import magic.model.mstatic.MagicPermanentStatic;
import magic.model.mstatic.MagicStatic;
import magic.model.player.AiPlayer;
import magic.model.target.MagicTarget;
import magic.model.target.MagicTargetType;
import magic.model.target.MagicTargetFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import magic.model.target.MagicTargetType;
public class MagicPlayer extends MagicObjectImpl implements MagicTarget, MagicMappable<MagicPlayer> {
@ -802,4 +802,8 @@ public class MagicPlayer extends MagicObjectImpl implements MagicTarget, MagicMa
public boolean isHuman() {
return !getPlayerDefinition().isArtificial();
}
public boolean isAiPlayerProfile() {
return getPlayerDefinition().getPlayerProfile() instanceof AiPlayer;
}
}

View File

@ -0,0 +1,8 @@
package magic.model;
public enum MagicPlayerZone {
HAND,
LIBRARY,
GRAVEYARD,
EXILE;
}

View File

@ -1,49 +1,17 @@
/*
* $Id$
*
* Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy).
*
* Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* Copyright (c) 2006 Romain Guy <romain.guy@mac.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package magic.ui;
import java.awt.AlphaComposite;
import java.awt.Color;
import magic.ui.MagicStyle;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsDevice.WindowTranslucency;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Paint;
import java.awt.Rectangle;
@ -55,11 +23,12 @@ import java.io.IOException;
import java.nio.file.Path;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import magic.data.GeneralConfig;
import magic.ui.theme.Theme;
import magic.utility.MagicFileSystem;
import magic.utility.MagicFileSystem.DataPath;
import magic.utility.MagicFileSystem;
/**
* <p><code>GraphicsUtilities</code> contains a set of tools to perform
@ -257,6 +226,58 @@ final public class GraphicsUtilities {
} else {
return CardImagesProvider.SMALL_SCREEN_IMAGE_SIZE;
}
}
}
public static BufferedImage getConvertedIcon(final ImageIcon icon) {
final BufferedImage bi =
GraphicsUtilities.getCompatibleBufferedImage(
icon.getIconWidth(), icon.getIconHeight(), Transparency.TRANSLUCENT);
final Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0, 0);
g.dispose();
return bi;
}
public static void drawStringWithOutline(final Graphics g, final String str, int x, int y, Color fillColor, Color outlineColor) {
g.setColor(outlineColor);
for (int i = 1; i <= 1; i++) {
g.drawString(str, x+i, y);
g.drawString(str, x-i, y);
g.drawString(str, x, y+i);
g.drawString(str, x, y-i);
}
g.setColor(fillColor);
g.drawString(str,x,y);
}
public static void drawStringWithOutline(final Graphics g, final String str, int x, int y) {
drawStringWithOutline(g, str, x, y, Color.WHITE, Color.BLACK);
}
public static void clearImage(final BufferedImage image) {
final Graphics2D g2d = image.createGraphics();
final Composite composite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
g2d.setComposite(composite);
g2d.dispose();
}
public static BufferedImage getGreyScaleImage(final BufferedImage colorImage) {
final BufferedImage greyscaleImage = new BufferedImage(
colorImage.getWidth(),
colorImage.getHeight(),
BufferedImage.TYPE_BYTE_GRAY
);
final Graphics g = greyscaleImage.createGraphics();
g.drawImage(colorImage, 0, 0, null);
g.dispose();
return greyscaleImage;
}
}

View File

@ -1,30 +1,5 @@
package magic.ui;
import magic.exception.UndoClickedException;
import magic.ui.duel.DuelPanel;
import magic.utility.MagicSystem;
import magic.ai.MagicAI;
import magic.data.GeneralConfig;
import magic.data.SoundEffects;
import magic.model.ILogBookListener;
import magic.model.MagicCardDefinition;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicLogBookEvent;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.phase.MagicPhaseType;
import magic.model.event.MagicEvent;
import magic.model.event.MagicEventAction;
import magic.model.event.MagicPriorityEvent;
import magic.model.target.MagicTarget;
import magic.model.target.MagicTargetNone;
import magic.ui.duel.viewer.ChoiceViewer;
import magic.ui.duel.viewer.UserActionPanel;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
@ -43,20 +18,41 @@ import java.util.concurrent.Callable;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import magic.ai.MagicAI;
import magic.data.DuelConfig;
import magic.data.GeneralConfig;
import magic.data.MagicIcon;
import magic.data.SoundEffects;
import magic.exception.InvalidDeckException;
import magic.exception.UndoClickedException;
import magic.game.state.GameState;
import magic.game.state.GameStateSnapshot;
import magic.game.state.GameStateFileWriter;
import magic.game.state.GameStateSnapshot;
import magic.model.ILogBookListener;
import magic.model.IUIGameController;
import magic.model.MagicCardDefinition;
import magic.model.MagicCardList;
import magic.model.MagicColor;
import magic.model.MagicGame;
import magic.model.MagicLogBookEvent;
import magic.model.MagicManaCost;
import magic.model.MagicObject;
import magic.model.MagicPlayer;
import magic.model.MagicPlayerZone;
import magic.model.MagicSource;
import magic.model.MagicSubType;
import magic.model.choice.MagicPlayChoiceResult;
import magic.model.event.MagicEvent;
import magic.model.event.MagicEventAction;
import magic.model.event.MagicPriorityEvent;
import magic.model.phase.MagicMainPhase;
import magic.model.phase.MagicPhaseType;
import magic.model.target.MagicTarget;
import magic.model.target.MagicTargetNone;
import magic.ui.card.AnnotatedCardPanel;
import magic.ui.duel.DuelPanel;
import magic.ui.duel.choice.ColorChoicePanel;
import magic.ui.duel.choice.ManaCostXChoicePanel;
import magic.ui.duel.choice.MayChoicePanel;
@ -64,10 +60,15 @@ import magic.ui.duel.choice.ModeChoicePanel;
import magic.ui.duel.choice.MulliganChoicePanel;
import magic.ui.duel.choice.MultiKickerChoicePanel;
import magic.ui.duel.choice.PlayChoicePanel;
import magic.ui.duel.player.IZoneButtonListener;
import magic.ui.duel.viewer.ChoiceViewer;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.duel.viewer.UserActionPanel;
import magic.ui.duel.viewer.ViewerInfo;
import magic.ui.screen.MulliganScreen;
import magic.utility.MagicSystem;
public class SwingGameController implements IUIGameController, ILogBookListener {
public class SwingGameController implements IUIGameController, ILogBookListener, IZoneButtonListener {
private static final GeneralConfig CONFIG = GeneralConfig.getInstance();
@ -198,6 +199,7 @@ public class SwingGameController implements IUIGameController, ILogBookListener
public void switchKeyPressed() {
game.setVisiblePlayer(game.getVisiblePlayer().getOpponent());
gamePanel.switchPlayers();
getViewerInfo().update(game);
gamePanel.updateView();
}
@ -933,4 +935,17 @@ public class SwingGameController implements IUIGameController, ILogBookListener
return choicePanel.getResult();
}
@Override
public void playerZoneSelected(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
gamePanel.setActivePlayerZone(playerInfo, zone);
}
@Override
public void playerZoneSelectedClicked(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
gamePanel.setFullScreenActivePlayerZone(playerInfo, zone);
}
public void setPlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
System.err.printf("TODO SwingGameController.setPlayerZone : %s, %s\n", playerInfo.name, zone);
}
}

View File

@ -1,10 +1,12 @@
package magic.ui.duel;
import magic.ui.duel.animation.PlayCardAnimation;
import javax.swing.JPanel;
import magic.model.MagicCardList;
import magic.model.MagicPlayerZone;
import magic.model.event.MagicEvent;
import magic.ui.duel.animation.PlayCardAnimation;
import magic.ui.duel.resolution.ResolutionProfileResult;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.duel.viewer.StackViewer;
@SuppressWarnings("serial")
@ -26,4 +28,7 @@ public abstract class BattlefieldPanel extends JPanel {
public abstract StackViewer getStackViewer();
public abstract void setActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone);
public abstract void setFullScreenActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone);
}

View File

@ -0,0 +1,58 @@
package magic.ui.duel;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import magic.ui.GraphicsUtilities;
public class BattlefieldTextOverlay {
private static final Font ZONE_FONT = new Font("Dialog", Font.BOLD, 12);
private BufferedImage textOverlayImage = null;
private String zoneName = "";
private boolean refreshOverlay = true;
public BufferedImage getOverlayImage(final int battlefieldWidth, final int batttlefieldHeight) {
final boolean createNewImage =
textOverlayImage == null ||
textOverlayImage.getHeight() != batttlefieldHeight ||
textOverlayImage.getWidth() != battlefieldWidth;
if (createNewImage) {
textOverlayImage = GraphicsUtilities.getCompatibleBufferedImage(
battlefieldWidth, batttlefieldHeight, Transparency.BITMASK
);
}
if (refreshOverlay) {
refreshOverlay = false;
GraphicsUtilities.clearImage(textOverlayImage);
final Graphics2D g2d = textOverlayImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
drawZoneName(g2d);
g2d.dispose();
}
return textOverlayImage;
}
private void drawZoneName(final Graphics2D g2d) {
g2d.setFont(ZONE_FONT);
final int textWidth = g2d.getFontMetrics(ZONE_FONT).stringWidth(zoneName);
final int textX = (textOverlayImage.getWidth() / 2) - (textWidth / 2);
final int textY = textOverlayImage.getHeight() - 4;
GraphicsUtilities.drawStringWithOutline(g2d, zoneName, textX, textY, Color.YELLOW, Color.DARK_GRAY);
}
public void setPlayerZoneName(final String text) {
this.zoneName = text;
refreshOverlay = true;
}
}

View File

@ -0,0 +1,103 @@
package magic.ui.duel;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import magic.ui.GraphicsUtilities;
public class CounterOverlay {
private static final Font VALUE_FONT = new Font("Dialog", Font.BOLD, 14);
private final BufferedImage image;
private int counterValue = 0;
private Color counterColor;
public CounterOverlay(final int width, final int height, final Color color) {
this.counterColor = color;
image = GraphicsUtilities.getCompatibleBufferedImage(width, height, Transparency.TRANSLUCENT);
drawCounter();
}
public BufferedImage getCounterImage() {
return image;
}
private void drawCounter() {
GraphicsUtilities.clearImage(image);
final Graphics2D g2d = image.createGraphics();
// drawBorder(g2d);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawCounterShape(g2d);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
drawCounterValue(g2d);
g2d.dispose();
}
private void drawCounterShape(final Graphics2D g2d) {
drawFillShape(g2d);
// drawOutlineShape(g2d);
}
private void setShapeFrame(final Ellipse2D shape, final float strokeWidth) {
final float strokeAdj = strokeWidth / 2.0f;
final float origin = strokeAdj;
final float sizeAdj = strokeWidth + 1.0f;
final float shapeWidth = (float)image.getWidth() - sizeAdj;
final float shapeHeight = (float)image.getHeight() - sizeAdj;
shape.setFrame(origin, origin, shapeWidth, shapeHeight);
}
private void drawFillShape(final Graphics2D g2d) {
final float strokeWidth = 1.0f;
final Ellipse2D shape = new Ellipse2D.Float();
setShapeFrame(shape, strokeWidth);
g2d.setStroke(new BasicStroke(strokeWidth));
g2d.setColor(counterColor);
g2d.fill(shape);
}
private void drawOutlineShape(final Graphics2D g2d) {
final float strokeWidth = 2.1f; // for some reason the circle appears asymmetrical when 2.0f.
final Ellipse2D shape = new Ellipse2D.Float();
setShapeFrame(shape, strokeWidth);
g2d.setStroke(new BasicStroke(strokeWidth));
g2d.setColor(counterColor);
g2d.draw(shape);
}
private void drawCounterValue(final Graphics2D g2d) {
g2d.setFont(VALUE_FONT);
// FontRenderContext frc = g2d.getFontRenderContext();
// final int textHeight = Math.round(VALUE_FONT.getLineMetrics(text, frc).getHeight());
final String text = Integer.toString(counterValue);
final FontMetrics metrics = g2d.getFontMetrics(VALUE_FONT);
final int textWidth = metrics.stringWidth(text);
final int textX = image.getWidth(null) / 2 - textWidth / 2;
final int textY = image.getHeight(null) / 2 + 4;
GraphicsUtilities.drawStringWithOutline(g2d, text, textX, textY);
}
public void setCounterValue(final int value) {
if (this.counterValue != value) {
this.counterValue = value;
drawCounter();
}
}
/**
* useful for debugging purposes.
*/
private void drawBorder(final Graphics2D g2d) {
g2d.setStroke(new BasicStroke(1));
g2d.setColor(new Color(255, 0, 0, 200));
g2d.fillRect(0, 0, image.getWidth()-1, image.getHeight()-1);
}
}

View File

@ -17,6 +17,7 @@ import magic.data.GeneralConfig;
import magic.exception.InvalidDeckException;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicPlayerZone;
import magic.model.event.MagicEvent;
import magic.ui.SwingGameController;
import magic.ui.MagicFrame;
@ -28,6 +29,7 @@ import magic.ui.duel.resolution.DefaultResolutionProfile;
import magic.ui.duel.resolution.ResolutionProfileResult;
import magic.ui.duel.resolution.ResolutionProfiles;
import magic.ui.duel.viewer.LogBookViewer;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.widget.ZoneBackgroundLabel;
import net.miginfocom.swing.MigLayout;
@ -226,7 +228,6 @@ public final class DuelPanel extends JPanel {
final Dimension size = getSize();
result = ResolutionProfiles.calculate(size);
backgroundLabel.setZones(result);
sidebarPanel.resizeComponents(result);
battlefieldPanel.resizeComponents(result);
setGamePanelLayout();
// defer until all pending events on the EDT have been processed.
@ -289,7 +290,6 @@ public final class DuelPanel extends JPanel {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
sidebarPanel.setStartEndTurnState();
sidebarPanel.getGameStatusPanel().showNewTurnNotification(game);
}
});
@ -312,11 +312,21 @@ public final class DuelPanel extends JPanel {
public void showEndGameMessage() {
dialogPanel.showEndGameMessage(controller);
sidebarPanel.setStartEndTurnState();
}
public JPanel getDialogPanel() {
return dialogPanel;
}
public void setActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
battlefieldPanel.setActivePlayerZone(playerInfo, zone);
}
public void setFullScreenActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
battlefieldPanel.setFullScreenActivePlayerZone(playerInfo, zone);
}
public void switchPlayers() {
sidebarPanel.switchPlayers();
}
}

View File

@ -1,12 +1,10 @@
package magic.ui.duel;
import magic.ui.duel.viewer.PlayerViewer;
import javax.swing.JPanel;
import magic.data.GeneralConfig;
import magic.ui.SwingGameController;
import magic.ui.duel.player.GamePlayerPanel;
import magic.ui.duel.resolution.DefaultResolutionProfile;
import magic.ui.duel.resolution.ResolutionProfileResult;
import magic.ui.duel.resolution.ResolutionProfileType;
import magic.ui.duel.viewer.GameStatusPanel;
import magic.ui.duel.viewer.LogBookViewer;
import magic.ui.duel.viewer.LogStackViewer;
@ -19,17 +17,20 @@ public class DuelSideBarPanel extends JPanel {
private static final GeneralConfig CONFIG = GeneralConfig.getInstance();
private final PlayerViewer opponentViewer;
private final PlayerViewer playerViewer;
private final GamePlayerPanel opponentViewer;
private final GamePlayerPanel playerViewer;
private final LogStackViewer logStackViewer;
private final LogBookViewer logBookViewer;
private final GameStatusPanel gameStatusPanel;
private final SwingGameController controller;
private boolean isSwitchedPlayers = false;
DuelSideBarPanel(final SwingGameController controller, final StackViewer imageStackViewer) {
this.controller = controller;
setOpaque(false);
//
opponentViewer = new PlayerViewer(controller, true);
playerViewer = new PlayerViewer(controller, false);
opponentViewer = new GamePlayerPanel(controller, controller.getViewerInfo().getPlayerInfo(true));
playerViewer = new GamePlayerPanel(controller, controller.getViewerInfo().getPlayerInfo(false));
logBookViewer = new LogBookViewer(controller.getGame().getLogBook());
logBookViewer.setVisible(!CONFIG.isLogViewerDisabled());
logStackViewer = new LogStackViewer(logBookViewer, imageStackViewer);
@ -54,31 +55,25 @@ public class DuelSideBarPanel extends JPanel {
removeAll();
setLayout(new MigLayout("insets " + insets + ", gap 0 10, flowy"));
add(opponentViewer, "w " + maxWidth + "!, h " + DefaultResolutionProfile.PLAYER_VIEWER_HEIGHT_SMALL + "!");
add(isSwitchedPlayers ? playerViewer : opponentViewer, "w " + maxWidth + "!, h " + DefaultResolutionProfile.PLAYER_VIEWER_HEIGHT_SMALL + "!");
add(logStackViewer, "w " + maxWidth + "!, h 100%");
add(gameStatusPanel, "w " + maxWidth + "!, h " + DefaultResolutionProfile.GAME_VIEWER_HEIGHT + "!");
add(playerViewer, "w " + maxWidth + "!, h " + DefaultResolutionProfile.PLAYER_VIEWER_HEIGHT_SMALL + "!");
add(isSwitchedPlayers ? opponentViewer : playerViewer, "w " + maxWidth + "!, h " + DefaultResolutionProfile.PLAYER_VIEWER_HEIGHT_SMALL + "!");
logStackViewer.setLogStackLayout();
}
void doUpdate() {
opponentViewer.update();
playerViewer.update();
opponentViewer.updateDisplay(controller.getViewerInfo().getPlayerInfo(!isSwitchedPlayers));
playerViewer.updateDisplay(controller.getViewerInfo().getPlayerInfo(isSwitchedPlayers));
gameStatusPanel.update();
}
void resizeComponents(final ResolutionProfileResult result) {
opponentViewer.setSmall(result.getFlag(ResolutionProfileType.GamePlayerViewerSmall));
playerViewer.setBounds(result.getBoundary(ResolutionProfileType.GamePlayerViewer));
playerViewer.setSmall(result.getFlag(ResolutionProfileType.GamePlayerViewerSmall));
gameStatusPanel.setBounds(result.getBoundary(ResolutionProfileType.GameStatusPanel));
}
void setStartEndTurnState() {
opponentViewer.getAvatarPanel().setSelected(false);
playerViewer.getAvatarPanel().setSelected(false);
void switchPlayers() {
isSwitchedPlayers = !isSwitchedPlayers;
doSetLayout();
revalidate();
}
}

View File

@ -1,12 +1,17 @@
package magic.ui.duel;
import java.awt.Graphics;
import java.awt.Image;
import magic.ui.duel.animation.PlayCardAnimation;
import java.awt.Point;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import magic.model.MagicCardDefinition;
import magic.model.MagicCardList;
import magic.model.MagicPlayer;
import magic.model.MagicPlayerZone;
import magic.model.event.MagicEvent;
import magic.ui.SwingGameController;
import magic.ui.duel.resolution.ResolutionProfileResult;
@ -15,6 +20,7 @@ import magic.ui.duel.viewer.ImageBattlefieldViewer;
import magic.ui.duel.viewer.ImageCardListViewer;
import magic.ui.duel.viewer.ImageCombatViewer;
import magic.ui.duel.viewer.ImageHandGraveyardExileViewer;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.duel.viewer.StackViewer;
@SuppressWarnings("serial")
@ -22,6 +28,8 @@ public class ImageModeBattlefieldPanel extends BattlefieldPanel {
private PlayCardAnimation animationEvent = null;
private final BattlefieldTextOverlay textOverlay = new BattlefieldTextOverlay();
private final ImageHandGraveyardExileViewer imageHandGraveyardViewer;
private final ImageBattlefieldViewer imagePlayerPermanentViewer;
private final ImageBattlefieldViewer imageOpponentPermanentViewer;
@ -37,6 +45,16 @@ public class ImageModeBattlefieldPanel extends BattlefieldPanel {
imageCombatViewer = new ImageCombatViewer(controller);
imageStackViewer = new StackViewer(controller, true);
//
imageHandGraveyardViewer.addPropertyChangeListener(
ImageHandGraveyardExileViewer.CP_PLAYER_ZONE,
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
textOverlay.setPlayerZoneName((String) evt.getNewValue());
repaint();
}
});
//
setLayout(null);
add(imageStackViewer);
add(imageHandGraveyardViewer);
@ -137,5 +155,22 @@ public class ImageModeBattlefieldPanel extends BattlefieldPanel {
animationEvent = event;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Image overlayImage = textOverlay.getOverlayImage(getWidth(), getHeight());
g.drawImage(overlayImage, 0, 0, this);
}
@Override
public void setActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
imageHandGraveyardViewer.setActivePlayerZone(playerInfo, zone);
}
@Override
public void setFullScreenActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
imageHandGraveyardViewer.setFullScreenActivePlayerZone(playerInfo, zone);
}
}

View File

@ -1,13 +1,15 @@
package magic.ui.duel;
import magic.ui.duel.animation.PlayCardAnimation;
import magic.model.MagicCardList;
import magic.model.MagicPlayerZone;
import magic.model.event.MagicEvent;
import magic.ui.SwingGameController;
import magic.ui.duel.animation.PlayCardAnimation;
import magic.ui.duel.resolution.ResolutionProfileResult;
import magic.ui.duel.resolution.ResolutionProfileType;
import magic.ui.duel.viewer.BattlefieldViewer;
import magic.ui.duel.viewer.HandGraveyardExileViewer;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.duel.viewer.StackCombatViewer;
import magic.ui.duel.viewer.StackViewer;
@ -81,4 +83,13 @@ public class TextModeBattlefieldPanel extends BattlefieldPanel {
// not implemented
}
@Override
public void setActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
// not applicable in text mode, do nothing.
}
@Override
public void setFullScreenActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
// not applicable in text mode, do nothing.
}
}

View File

@ -0,0 +1,88 @@
package magic.ui.duel.player;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import magic.model.player.AiPlayer;
import magic.ui.SwingGameController;
import magic.ui.duel.viewer.ChoiceViewer;
import magic.ui.duel.viewer.PlayerViewerInfo;
import magic.ui.theme.ThemeFactory;
import magic.ui.widget.PanelButton;
import magic.ui.widget.TexturedPanel;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class GamePlayerPanel extends TexturedPanel implements ChoiceViewer {
private PlayerViewerInfo playerInfo;
private PlayerZoneButtonsPanel zoneButtonsPanel;
private PlayerImagePanel avatarPanel;
private final PanelButton avatarButton;
public GamePlayerPanel(final SwingGameController controller, final PlayerViewerInfo playerInfo) {
this.playerInfo = playerInfo;
setOpaque(true);
setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
setPreferredSize(new Dimension(0, 80));
setMinimumSize(getPreferredSize());
zoneButtonsPanel = new PlayerZoneButtonsPanel(playerInfo);
assert controller instanceof IZoneButtonListener;
zoneButtonsPanel.addZoneButtonListener(controller);
avatarPanel = new PlayerImagePanel(playerInfo, controller.getGame());
avatarButton = new PanelButton() {
@Override
public Color getValidColor() {
return ThemeFactory.getInstance().getCurrentTheme().getChoiceColor();
}
@Override
public void mouseClicked() {
controller.processClick(playerInfo.player);
}
};
avatarButton.setComponent(avatarPanel);
setLayout(new MigLayout("flowy, insets 0, gap 4 1, wrap 2"));
add(avatarButton, "w 80!, h 80!, spany 2");
add(getPlayerLabel(), "gaptop 3");
add(zoneButtonsPanel, "w 100%, h 100%");
if (controller != null) {
controller.registerChoiceViewer(this);
}
}
private JLabel getPlayerLabel() {
final StringBuffer sb = new StringBuffer(playerInfo.name);
if (playerInfo.player.isAiPlayerProfile()) {
final AiPlayer aiPlayer = (AiPlayer)playerInfo.player.getPlayerDefinition().getPlayerProfile();
sb.append(", level ").append(aiPlayer.getAiLevel()).append(" AI (").append(aiPlayer.getAiType().name()).append(")");
}
final JLabel lbl = new JLabel(sb.toString());
lbl.setFont(new Font("dialog", Font.PLAIN, 9));
return lbl;
}
@Override
public void showValidChoices(Set<?> validChoices) {
avatarButton.setValid(!validChoices.isEmpty() ? validChoices.contains(playerInfo.player) : false);
}
public void updateDisplay(final PlayerViewerInfo playerInfo) {
this.playerInfo = playerInfo;
avatarPanel.updateDisplay(playerInfo);
zoneButtonsPanel.updateDisplay(playerInfo);
}
}

View File

@ -0,0 +1,9 @@
package magic.ui.duel.player;
import magic.model.MagicPlayerZone;
import magic.ui.duel.viewer.PlayerViewerInfo;
public interface IZoneButtonListener {
void playerZoneSelected(PlayerViewerInfo playerInfo, MagicPlayerZone zone);
void playerZoneSelectedClicked(PlayerViewerInfo playerInfo, MagicPlayerZone zone);
}

View File

@ -0,0 +1,121 @@
package magic.ui.duel.player;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import magic.model.MagicGame;
import magic.ui.GraphicsUtilities;
import magic.ui.IconImages;
import magic.ui.duel.CounterOverlay;
import magic.ui.duel.viewer.PlayerViewerInfo;
@SuppressWarnings("serial")
public class PlayerImagePanel extends JPanel {
private static final Font HEALTH_FONT = new Font("Dialog", Font.BOLD, 20);
private final MagicGame game;
private final CounterOverlay poisonCounter;
private final CounterOverlay damageCounter;
private final BufferedImage activeImage;
private final BufferedImage inactiveImage;
private PlayerViewerInfo playerInfo;
public PlayerImagePanel(final PlayerViewerInfo player, final MagicGame game) {
this.playerInfo = player;
this.game = game;
activeImage = getPlayerAvatarImage();
inactiveImage = GraphicsUtilities.getGreyScaleImage(activeImage);
poisonCounter = new CounterOverlay(20, 20, Color.GREEN);
damageCounter = new CounterOverlay(20, 20, Color.CYAN);
}
private BufferedImage getPlayerAvatarImage() {
final ImageIcon icon = IconImages.getIconSize3(this.playerInfo.player.getPlayerDefinition());
return GraphicsUtilities.scale(GraphicsUtilities.getConvertedIcon(icon), 74, 74);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D g2d = (Graphics2D) g;
if (playerInfo.player == game.getTurnPlayer()) {
g2d.drawImage(activeImage, 0, 0, this);
// drawPlayerHighlight(g2d);
} else {
g2d.drawImage(inactiveImage, 0, 0, this);
}
// counters
drawPoisonCountersOverlay(g2d);
drawShieldDamageOverlay(g2d);
// health
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
drawHealthValueOverlay(g2d, 0, 0, activeImage);
}
private void drawPlayerHighlight(final Graphics2D g2d) {
g2d.setStroke(new BasicStroke(6.0f));
g2d.setColor(new Color(255, 255, 0, 220));
g2d.drawRect(0, 0, getWidth(), getHeight());
}
private void drawHealthValueOverlay(final Graphics2D g2d, final int x, final int y, final Image image) {
g2d.setFont(HEALTH_FONT);
final String text = Integer.toString(playerInfo.life);
final int textX = x + 4;
final int textY = y + image.getHeight(null) - 6;
GraphicsUtilities.drawStringWithOutline(g2d, text, textX, textY);
}
public void updateDisplay(final PlayerViewerInfo playerInfo) {
this.playerInfo = playerInfo;
repaint();
}
private void drawPoisonCountersOverlay(final Graphics2D g2d) {
if (playerInfo.poison > 0) {
poisonCounter.setCounterValue(playerInfo.poison);
final BufferedImage counterImage = poisonCounter.getCounterImage();
g2d.drawImage(
counterImage,
getWidth() - counterImage.getWidth() - 4,
getHeight() - counterImage.getHeight() - 4,
null);
}
}
private void drawShieldDamageOverlay(final Graphics2D g2d) {
if (playerInfo.preventDamage > 0) {
damageCounter.setCounterValue(playerInfo.preventDamage);
final BufferedImage counterImage = damageCounter.getCounterImage();
g2d.drawImage(
counterImage,
getWidth() - counterImage.getWidth() - 4,
4,
null);
}
}
// private void drawHealthGauge(final Graphics2D g2d) {
// g2d.setStroke(new BasicStroke(1));
// g2d.setColor(Color.BLACK);
// final int w = 10;
// g2d.drawRect(avatarX-w, avatarY, w, avatarImage.getHeight(null) - 1);
// final Paint borderColor = new GradientPaint(avatarX-w, avatarY, Color.GREEN, avatarX-w, avatarY + avatarImage.getHeight(null), Color.RED, false);
// g2d.setPaint(borderColor);
// g2d.fillRect(avatarX-w+1, avatarY+1, w-1, avatarImage.getHeight(null) - 2);
// }
}

View File

@ -0,0 +1,158 @@
package magic.ui.duel.player;
import java.awt.Cursor;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import magic.data.MagicIcon;
import magic.model.MagicPlayerZone;
import magic.ui.duel.viewer.PlayerViewerInfo;
import net.miginfocom.swing.MigLayout;
@SuppressWarnings("serial")
public class PlayerZoneButtonsPanel extends JPanel {
private static ButtonGroup buttonGroup = new ButtonGroup();
private final ZoneToggleButton libraryZoneButton;
private final ZoneToggleButton handZoneButton;
private final ZoneToggleButton graveyardZoneButton;
private final ZoneToggleButton exileZoneButton;
private final List<IZoneButtonListener> zoneButtonlisteners = new ArrayList<>();
private PlayerViewerInfo playerInfo;
public PlayerZoneButtonsPanel(final PlayerViewerInfo playerInfo) {
this.playerInfo = playerInfo;
setLayout(new MigLayout("insets 0 2 0 0"));
libraryZoneButton = getZoneToggleButton(
MagicPlayerZone.LIBRARY, MagicIcon.LIBRARY_ZONE, playerInfo.library.size(), "Library", false, true);
handZoneButton = getZoneToggleButton(
MagicPlayerZone.HAND, MagicIcon.HAND_ZONE, playerInfo.hand.size(), "Hand", false, true);
graveyardZoneButton = getZoneToggleButton(
MagicPlayerZone.GRAVEYARD, MagicIcon.GRAVEYARD_ZONE, playerInfo.graveyard.size(), "Graveyard", false, true);
exileZoneButton = getZoneToggleButton(
MagicPlayerZone.EXILE, MagicIcon.EXILE_ZONE, playerInfo.exile.size(), "Exile", false, true);
add(libraryZoneButton);
add(handZoneButton);
add(graveyardZoneButton);
add(exileZoneButton);
// add(new JLabel(IconImages.getIcon(MagicIcon.WAITING)));
if (buttonGroup.getButtonCount() > 0) {
buttonGroup.getElements().nextElement().setSelected(true);
}
setOpaque(false);
}
public synchronized void addZoneButtonListener(final IZoneButtonListener listener) {
zoneButtonlisteners.add(listener);
}
public synchronized void removeZoneButtonListener(final IZoneButtonListener listener) {
zoneButtonlisteners.remove(listener);
}
private ZoneToggleButton getZoneToggleButton(
final MagicPlayerZone zone,
final MagicIcon icon,
final int cardCount,
final String tooltip,
final boolean isActive,
final boolean isAnimated) {
final ZoneToggleButton btn = new ZoneToggleButton(zone, icon, cardCount, isActive, isAnimated);
btn.setToolTipText(tooltip);
if (isActive) {
buttonGroup.add(btn);
} else {
btn.setEnabled(false);
}
// btn.addChangeListener(new ChangeListener() {
// @Override
// public void stateChanged(ChangeEvent ev) {
// final JToggleButton btn = (JToggleButton) ev.getSource();
// System.out.println("isSelected=" + btn.isSelected());
// }
// });
btn.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent ev) {
if (ev.getStateChange() == ItemEvent.SELECTED) {
final ZoneToggleButton b = (ZoneToggleButton) ev.getSource();
notifyToggleButtonSelected(b.getPlayerZone());
}
}
});
btn.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent ev) {
final JToggleButton btn = (JToggleButton) ev.getSource();
if (btn.isEnabled()) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
}
@Override
public void mouseExited(MouseEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
@Override
public void mousePressed(MouseEvent ev) {
final ZoneToggleButton b = (ZoneToggleButton) ev.getSource();
if (b.isSelected()) {
notifyToggleButtonSelectedClicked(b.getPlayerZone());
}
}
});
return btn;
}
private void notifyToggleButtonSelectedClicked(final MagicPlayerZone zone) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (final IZoneButtonListener listener : zoneButtonlisteners) {
listener.playerZoneSelectedClicked(playerInfo, zone);
}
}
});
}
private void notifyToggleButtonSelected(final MagicPlayerZone zone) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (final IZoneButtonListener listener : zoneButtonlisteners) {
listener.playerZoneSelected(playerInfo, zone);
}
}
});
}
void updateDisplay(final PlayerViewerInfo playerInfo) {
this.playerInfo = playerInfo;
if (playerInfo != null) {
handZoneButton.setNumberOfCardsInZone(playerInfo.hand.size());
libraryZoneButton.setNumberOfCardsInZone(playerInfo.library.size());
graveyardZoneButton.setNumberOfCardsInZone(playerInfo.graveyard.size());
exileZoneButton.setNumberOfCardsInZone(playerInfo.exile.size());
}
}
public static void clearButtonGroup() {
buttonGroup = new ButtonGroup();
}
}

View File

@ -0,0 +1,174 @@
package magic.ui.duel.player;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import javax.swing.JToggleButton;
import magic.data.MagicIcon;
import magic.model.MagicPlayerZone;
import magic.ui.GraphicsUtilities;
import magic.ui.IconImages;
import magic.ui.MagicStyle;
import org.pushingpixels.trident.Timeline;
import org.pushingpixels.trident.callback.TimelineCallback;
@SuppressWarnings("serial")
public class ZoneToggleButton extends JToggleButton implements TimelineCallback {
enum ValueStyle {
NORMAL,
OUTLINE
}
private static final Font ZONE_FONT = new Font("Dialog", Font.BOLD, 14);
private BufferedImage zoneIconImage = null;
private final MagicIcon magicIcon;
private String cardCountString = "0";
private final ValueStyle valueStyle;
private final MagicPlayerZone playerZone;
private Timeline timeline1;
private int imageOffset = 0;
private boolean animateOnChange = false;
public int getImageOffset() {
return imageOffset;
}
public void setImageOffset(int value) {
this.imageOffset = value * 2;
repaint();
}
// CTR
private ZoneToggleButton(
final MagicPlayerZone playerZone,
final MagicIcon icon,
final int cardCount,
final ValueStyle valueStyle,
final boolean isActive,
final boolean isAnimated) {
this.playerZone = playerZone;
this.magicIcon = icon;
this.valueStyle = valueStyle;
this.animateOnChange = false;
setEnabled(isActive);
setNumberOfCardsInZone(cardCount);
setMinimumSize(new Dimension(40, 60));
}
// CTR
ZoneToggleButton(
final MagicPlayerZone playerZone,
final MagicIcon icon,
final int cardCount,
final boolean isActive,
final boolean isAnimated) {
this(playerZone, icon, cardCount, ValueStyle.NORMAL, isActive, isAnimated);
}
public MagicPlayerZone getPlayerZone() {
return playerZone;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Image image = getZoneIconAsImage();
final int x = getWidth() / 2 - image.getWidth(null) / 2;
if (animateOnChange) {
g.drawImage(image, x, 4, x+32, 4+32, 0+imageOffset, 0+imageOffset, 32-imageOffset, 32-imageOffset, null);
} else {
g.drawImage(image, x, 4, null);
}
drawZoneValueOverlay((Graphics2D)g, cardCountString, x, getHeight(), image);
if (isSelected()) {
drawSelectedBorder(g);
}
}
private void drawSelectedBorder(Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(4.0f));
g2d.setColor(MagicStyle.HIGHLIGHT_COLOR);
g2d.drawRect(0, 0, getWidth(), getHeight());
}
private BufferedImage getZoneIconAsImage() {
if (zoneIconImage == null) {
zoneIconImage = GraphicsUtilities.getCompatibleBufferedImage(32, 32, Transparency.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) zoneIconImage.getGraphics();
final Image iconImage = GraphicsUtilities.getConvertedIcon(IconImages.getIcon(magicIcon));
g2d.drawImage(iconImage, 0, 0, this);
g2d.dispose();
}
return zoneIconImage;
}
private void drawZoneValueOverlay(Graphics2D g2d, String text, int x, int y, final Image iconImage) {
g2d.setFont(ZONE_FONT);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
FontRenderContext frc = g2d.getFontRenderContext();
final int textHeight = Math.round(ZONE_FONT.getLineMetrics(text, frc).getHeight());
final FontMetrics metrics = g2d.getFontMetrics(ZONE_FONT);
int textWidth = metrics.stringWidth(text);
int textX = x + ((iconImage.getWidth(null) / 2) - (textWidth / 2));
int textY = y - 6;
if (valueStyle == ValueStyle.OUTLINE) {
GraphicsUtilities.drawStringWithOutline(g2d, text, textX, textY);
} else {
g2d.drawString(text, textX, textY);
}
}
final void setNumberOfCardsInZone(final int cardCount) {
final boolean isModified = !Integer.toString(cardCount).equals(cardCountString);
cardCountString = Integer.toString(cardCount);
if (isModified) {
if (animateOnChange) {
doAlertAnimation();
} else {
repaint();
}
}
}
public void doAlertAnimation() {
timeline1 = new Timeline();
timeline1.addCallback(this);
timeline1.setDuration(200);
// timeline1.setEase(new Spline(0.8f));
timeline1.addPropertyToInterpolate(
Timeline.property("imageOffset").on(this).from(0).to(4));
timeline1.playLoop(2, Timeline.RepeatBehavior.REVERSE);
}
@Override
public void onTimelineStateChanged(Timeline.TimelineState oldState, Timeline.TimelineState newState, float durationFraction, float timelinePosition) {
// do nothing.
}
@Override
public void onTimelinePulse(float durationFraction, float timelinePosition) {
// do nothing.
}
}

View File

@ -11,40 +11,41 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
import magic.model.MagicPlayerZone;
import magic.ui.ScreenController;
import magic.ui.MagicStyle;
@SuppressWarnings("serial")
public class ImageHandGraveyardExileViewer extends JPanel implements ChangeListener {
private static final long serialVersionUID = 1L;
// fired when contents of player zone is changed
public static final String CP_PLAYER_ZONE = "activeZoneName";
private final ViewerInfo viewerInfo;
private final SwingGameController controller;
private final TabSelector tabSelector;
private final ImageCardListViewer cardListViewer;
private final MagicCardList other = new MagicCardList();
private JToggleButton selectedTab = null;
public ImageHandGraveyardExileViewer(final SwingGameController controller) {
viewerInfo = controller.getViewerInfo();
this.controller = controller;
setOpaque(false);
setLayout(new BorderLayout(6,0));
setLayout(new BorderLayout(6, 0));
final String playerName=viewerInfo.getPlayerInfo(false).name;
final String opponentName=viewerInfo.getPlayerInfo(true).name;
final Theme theme = MagicStyle.getTheme();
tabSelector = new TabSelector(this, true);
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_HAND), getHandZoneName(getUserPlayer()));
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_GRAVEYARD), getGraveyardZoneName(getUserPlayer()));
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_GRAVEYARD), getGraveyardZoneName(getAiPlayer()));
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_EXILE), getExileZoneName(getUserPlayer()));
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_EXILE), getExileZoneName(getAiPlayer()));
tabSelector.addTab(theme.getIcon(Theme.ICON_SMALL_HAND), "Other : " + getUserPlayer().name);
add(tabSelector, BorderLayout.WEST);
tabSelector=new TabSelector(this,true);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_HAND),"Hand : "+playerName);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_GRAVEYARD),"Graveyard : "+playerName);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_GRAVEYARD),"Graveyard : "+opponentName);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_EXILE),"Exile : "+playerName);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_EXILE),"Exile : "+opponentName);
tabSelector.addTab(MagicStyle.getTheme().getIcon(Theme.ICON_SMALL_HAND),"Other : "+playerName);
add(tabSelector,BorderLayout.WEST);
cardListViewer=new ImageCardListViewer(controller);
add(cardListViewer,BorderLayout.CENTER);
cardListViewer = new ImageCardListViewer(controller);
add(cardListViewer, BorderLayout.CENTER);
}
public void setSelectedTab(final int selectedTab) {
@ -64,55 +65,73 @@ public class ImageHandGraveyardExileViewer extends JPanel implements ChangeListe
private void showCards(
final MagicCardList cards,
final boolean useCardZoneScreen,
final boolean showFullScreen,
final String cardZoneTitle,
final boolean aShowInfo) {
if (useCardZoneScreen) {
useCardZoneScreen(cards, cardZoneTitle);
final boolean showCardIcons) {
if (showFullScreen) {
showFullScreenZone(cards, cardZoneTitle);
} else {
cardListViewer.setCardList(cards, aShowInfo);
cardListViewer.setCardList(cards, showCardIcons);
firePropertyChange(CP_PLAYER_ZONE, null, cardZoneTitle);
}
}
private void update(final boolean useCardZoneScreen) {
if (cardListViewer!=null) {
private void update(final boolean showFullScreen) {
if (cardListViewer != null) {
switch (tabSelector.getSelectedTab()) {
case 0:
showCards(
viewerInfo.getPlayerInfo(false).hand,
useCardZoneScreen, "Player Hand", true);
getUserPlayer().hand,
showFullScreen, getHandZoneName(getUserPlayer()), true);
controller.setPlayerZone(getUserPlayer(), MagicPlayerZone.HAND);
break;
case 1:
showCards(
viewerInfo.getPlayerInfo(false).graveyard,
useCardZoneScreen, "Player Graveyard", false);
getUserPlayer().graveyard,
showFullScreen, getGraveyardZoneName(getUserPlayer()), false);
controller.setPlayerZone(getUserPlayer(), MagicPlayerZone.GRAVEYARD);
break;
case 2:
showCards(
viewerInfo.getPlayerInfo(true).graveyard,
useCardZoneScreen, "Computer Graveyard", false);
getAiPlayer().graveyard,
showFullScreen, getGraveyardZoneName(getAiPlayer()), false);
controller.setPlayerZone(getAiPlayer(), MagicPlayerZone.GRAVEYARD);
break;
case 3:
showCards(
viewerInfo.getPlayerInfo(false).exile,
useCardZoneScreen, "Player Exile", false);
getUserPlayer().exile,
showFullScreen, getExileZoneName(getUserPlayer()), false);
controller.setPlayerZone(getUserPlayer(), MagicPlayerZone.EXILE);
break;
case 4:
showCards(
viewerInfo.getPlayerInfo(true).exile,
useCardZoneScreen, "Computer Exile", false);
getAiPlayer().exile,
showFullScreen, getExileZoneName(getAiPlayer()), false);
controller.setPlayerZone(getAiPlayer(), MagicPlayerZone.EXILE);
break;
case 5:
showCards(
other,
useCardZoneScreen, "Other", false);
showFullScreen, "Other", false);
break;
}
repaint();
}
}
private void useCardZoneScreen(final MagicCardList aCardList, final String zoneName) {
private String getHandZoneName(final PlayerViewerInfo player) {
return player.isAi ? player.name + " Hand" : "";
}
private String getGraveyardZoneName(final PlayerViewerInfo player) {
return player.name + " Graveyard";
}
private String getExileZoneName(final PlayerViewerInfo player) {
return player.name + " Exile";
}
private void showFullScreenZone(final MagicCardList aCardList, final String zoneName) {
ScreenController.showCardZoneScreen(aCardList, zoneName, false);
}
@ -125,4 +144,79 @@ public class ImageHandGraveyardExileViewer extends JPanel implements ChangeListe
public ImageCardListViewer getCardListViewer() {
return cardListViewer;
}
public void setActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
tabSelector.setIsUserClick(false);
if (playerInfo.isAi) {
switch (zone) {
case HAND: // TODO
break;
case GRAVEYARD:
setSelectedTab(2);
break;
case EXILE: setSelectedTab(4);
break;
}
} else {
switch (zone) {
case HAND:
setSelectedTab(0);
break;
case GRAVEYARD:
setSelectedTab(1);
break;
case EXILE:
setSelectedTab(3);
break;
}
}
}
public void setFullScreenActivePlayerZone(PlayerViewerInfo playerInfo, MagicPlayerZone zone) {
tabSelector.setIsUserClick(true);
if (playerInfo.isAi) {
switch (zone) {
case HAND: // TODO
break;
case GRAVEYARD:
setSelectedTab(2);
break;
case EXILE: setSelectedTab(4);
break;
}
} else {
switch (zone) {
case HAND:
setSelectedTab(0);
break;
case GRAVEYARD:
setSelectedTab(1);
break;
case EXILE:
setSelectedTab(3);
break;
}
}
}
/**
* Returns the latest instance of PlayerViewInfo.
* <p>
* <b>Do not retain a reference toPlayerViewerInfo since a new instance
* is created whenever ViewerInfo is updated.</b>
*/
private PlayerViewerInfo getUserPlayer() {
return controller.getViewerInfo().getPlayerInfo(false);
}
/**
* Returns the latest instance of PlayerViewInfo.
* <p>
* <b>Do not retain a reference toPlayerViewerInfo since a new instance
* is created whenever ViewerInfo is updated.</b>
*/
private PlayerViewerInfo getAiPlayer() {
return controller.getViewerInfo().getPlayerInfo(true);
}
}

View File

@ -23,6 +23,7 @@ public class PlayerViewerInfo {
public final MagicCardList exile;
public final MagicCardList library;
public final List<PermanentViewerInfo> permanents;
public final boolean isAi;
public PlayerViewerInfo(final MagicGame game,final MagicPlayer player) {
this.player=player;
@ -36,6 +37,7 @@ public class PlayerViewerInfo {
graveyard=new MagicCardList(player.getGraveyard());
exile=new MagicCardList(player.getExile());
library=new MagicCardList(player.getLibrary());
isAi = player.getPlayerDefinition().isArtificial();
permanents=new ArrayList<PermanentViewerInfo>();
for (final MagicPermanent permanent : player.getPermanents()) {
permanents.add(new PermanentViewerInfo(game,permanent));

View File

@ -1,12 +1,5 @@
package magic.ui.widget;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
@ -15,11 +8,16 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class TabSelector extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private static final Dimension HORIZONTAL_BUTTON_DIMENSION=new Dimension(28,20);
private static final Dimension VERTICAL_BUTTON_DIMENSION=new Dimension(24,24);
@ -53,7 +51,7 @@ public class TabSelector extends JPanel implements ActionListener {
buttonDimension=HORIZONTAL_BUTTON_DIMENSION;
}
buttons=new ArrayList<JToggleButton>();
buttons=new ArrayList<>();
}
@ -91,18 +89,12 @@ public class TabSelector extends JPanel implements ActionListener {
}
}
// public void addTab(final ImageIcon icon) {
//
// addTab(icon,null);
// }
private void showTab(final JToggleButton selectedButton) {
showTab(selectedButton, false);
showTab(selectedButton, isUserClick);
}
private void showTab(final JToggleButton selectedButton, final boolean userClick) {
this.isUserClick = userClick;
for (final JToggleButton button : buttons) {
button.setSelected(button==selectedButton);
}
@ -119,4 +111,8 @@ public class TabSelector extends JPanel implements ActionListener {
return isUserClick;
}
public void setIsUserClick(final boolean b) {
this.isUserClick = b;
}
}