Support showing source card images within stack items

Update CHANGES.txt
This commit is contained in:
drdev
2014-03-27 04:53:16 +00:00
parent d43dfb788d
commit 4f485594fc
6 changed files with 123 additions and 246 deletions

View File

@@ -83,7 +83,6 @@ public enum CSubmenuPreferences implements ICDoc {
lstControls.add(Pair.of(view.getCbUseThemes(), FPref.UI_THEMED_COMBOBOX));
lstControls.add(Pair.of(view.getCbPromptFreeBlocks(), FPref.MATCHPREF_PROMPT_FREE_BLOCKS));
lstControls.add(Pair.of(view.getCbCompactPrompt(), FPref.UI_COMPACT_PROMPT));
lstControls.add(Pair.of(view.getCbStackCardView(), FPref.UI_STACK_CARD_VIEW));
lstControls.add(Pair.of(view.getCbHideReminderText(), FPref.UI_HIDE_REMINDER_TEXT));
for(final Pair<JCheckBox, FPref> kv : lstControls) {

View File

@@ -74,7 +74,6 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final JCheckBox cbUseThemes = new OptionsCheckBox("Enable Themes");
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox("Free Block Handling");
private final JCheckBox cbCompactPrompt = new OptionsCheckBox("Compact Prompt");
private final JCheckBox cbStackCardView = new OptionsCheckBox("Card View for Stack");
private final JCheckBox cbHideReminderText = new OptionsCheckBox("Hide Reminder Text");
private final Map<FPref, KeyboardShortcutField> shortcutFields = new HashMap<FPref, KeyboardShortcutField>();
@@ -495,10 +494,6 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
return cbCompactPrompt;
}
public final JCheckBox getCbStackCardView() {
return cbStackCardView;
}
public final JCheckBox getCbHideReminderText() {
return cbHideReminderText;
}

View File

@@ -456,7 +456,6 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
for (VCommand c : view.getCommandViews()) {
panels.addAll(c.getTabletop().getCardPanels());
}
panels.addAll(VStack.SINGLETON_INSTANCE.getStackArea().getCardPanels());
return panels;
}

View File

@@ -17,7 +17,8 @@
*/
package forge.gui.match.views;
import forge.Singletons;
import forge.ImageCache;
import forge.game.card.Card;
import forge.game.card.CardUtil;
import forge.game.player.LobbyPlayer;
import forge.game.player.PlayerController;
@@ -30,26 +31,21 @@ import forge.gui.framework.IVDoc;
import forge.gui.match.CMatchUI;
import forge.gui.match.controllers.CStack;
import forge.gui.toolbox.FMouseAdapter;
import forge.gui.toolbox.FScrollPane;
import forge.gui.toolbox.FScrollPanel;
import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FSkin.SkinnedTextArea;
import forge.properties.ForgePreferences.FPref;
import forge.view.arcane.CardArea;
import forge.view.arcane.CardPanel;
import forge.view.arcane.CardPanelContainer;
import forge.view.arcane.util.Animation;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.border.Border;
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.util.ArrayList;
import java.util.List;
import java.awt.image.BufferedImage;
/**
* Assembles Swing components of stack report.
@@ -62,21 +58,15 @@ public enum VStack implements IVDoc<CStack> {
// Fields used with interface IVDoc
private DragCell parentCell;
private boolean cardView;
private final DragTab tab = new DragTab("Stack");
// Top-level containers
private final FScrollPane scroller = new FScrollPane(null, true,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
private final StackArea stackArea = new StackArea(scroller);
private final FScrollPanel scroller = new FScrollPanel(new MigLayout("insets 1%, gap 1%, wrap"), true);
// Other fields
private List<JTextArea> stackTARs = new ArrayList<JTextArea>();
private OptionalTriggerMenu otMenu = new OptionalTriggerMenu();
private static OptionalTriggerMenu otMenu = new OptionalTriggerMenu();
private VStack() {
scroller.setViewportView(stackArea);
stackArea.setOpaque(false);
}
//========= Overridden methods
@@ -86,22 +76,8 @@ public enum VStack implements IVDoc<CStack> {
*/
@Override
public void populate() {
cardView = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_STACK_CARD_VIEW);
if (cardView) {
final JPanel pnl = parentCell.getBody();
pnl.setLayout(new MigLayout("insets 0, gap 0"));
pnl.add(scroller, "w 100%, h 100%!");
}
}
/**
* Gets the stack area.
*
* @return {@link forge.gui.match.views.VStack.StackArea}
*/
public StackArea getStackArea() {
return this.stackArea;
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0"));
parentCell.getBody().add(scroller, "w 100%, h 100%!");
}
/* (non-Javadoc)
@@ -150,138 +126,130 @@ public enum VStack implements IVDoc<CStack> {
* @param stack
* @param viewer */
public void updateStack(final MagicStack stack, final LobbyPlayer viewer) {
// No need to update this unless it's showing
if (!parentCell.getSelected().equals(this)) { return; }
int count = 1;
Border border = null;
tab.setText("Stack : " + stack.size());
if (cardView) {
stackArea.clear();
}
else {
parentCell.getBody().removeAll();
parentCell.getBody().setLayout(new MigLayout("insets 1%, gap 1%, wrap"));
border = new EmptyBorder(5, 5, 5, 5);
stackTARs.clear();
}
// No need to update the rest unless it's showing
if (!parentCell.getSelected().equals(this)) { return; }
scroller.removeAll();
boolean isFirst = true;
for (final SpellAbilityStackInstance spell : stack) {
String isOptional = spell.getSpellAbility().isOptionalTrigger()
&& spell.getSourceCard().getController().getController().getLobbyPlayer().equals(viewer) ? "(OPTIONAL) " : "";
String txt = (count++) + ". " + isOptional + spell.getStackDescription();
StackInstanceTextArea tar = new StackInstanceTextArea(spell, viewer);
if (cardView) {
Animation.moveCard(stackArea.addCard(spell.getSourceCard()));
}
else {
SkinnedTextArea tar = new SkinnedTextArea(txt);
tar.setToolTipText(txt);
tar.setOpaque(true);
tar.setBorder(border);
this.setSpellColor(tar, spell);
scroller.add(tar, "w 98%!");
tar.setFocusable(false);
tar.setEditable(false);
tar.setLineWrap(true);
tar.setWrapStyleWord(true);
/*
* TODO - we should figure out how to display cards on the stack in
* the Picture/Detail panel The problem not is that when a computer
* casts a Morph, the real card shows because Picture/Detail checks
* isFaceDown() which will be false on for spell.getHostCard() on
* the stack.
*/
// this functionality was present in v 1.1.8
tar.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent e) {
if (!spell.getStackDescription().startsWith("Morph ")) {
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSpellAbility().getHostCard());
}
}
});
if (spell.getSpellAbility().isOptionalTrigger() && spell.getSpellAbility().getActivatingPlayer().getLobbyPlayer() == viewer) {
tar.addMouseListener(new FMouseAdapter() {
@Override
public void onRightClick(MouseEvent e) {
otMenu.setStackInstance(spell);
otMenu.show(e.getComponent(), e.getX(), e.getY());
}
});
}
parentCell.getBody().add(tar, "w 98%!");
stackTARs.add(tar);
}
/*
* This updates the Card Picture/Detail when the spell is added to
* the stack. This functionality was not present in v 1.1.8.
*
* Problem is described in TODO right above this.
*/
//update the Card Picture/Detail when the spell is added to the stack
if (isFirst) {
isFirst = false;
if (!spell.getStackDescription().startsWith("Morph ")) {
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSourceCard());
}
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSourceCard());
}
}
if (!cardView) {
parentCell.getBody().validate();
parentCell.getBody().repaint();
}
scroller.revalidate();
scroller.repaint();
}
private void setSpellColor(SkinnedTextArea tar, SpellAbilityStackInstance s0) {
if (s0.getStackDescription().startsWith("Morph ")) {
tar.setBackground(new Color(0, 0, 0, 0));
tar.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
@SuppressWarnings("serial")
private static class StackInstanceTextArea extends SkinnedTextArea {
private static final int PADDING = 3;
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;
public StackInstanceTextArea(final SpellAbilityStackInstance spell, final LobbyPlayer viewer) {
sourceCard = spell.getSourceCard();
String txt = spell.getStackDescription();
if (spell.getSpellAbility().isOptionalTrigger()
&& spell.getSourceCard().getController().getController().getLobbyPlayer().equals(viewer)) {
txt = "(OPTIONAL) " + txt;
}
setText(txt);
setToolTipText(txt);
setOpaque(true);
setBorder(new EmptyBorder(PADDING, CARD_WIDTH + 2 * PADDING, PADDING, PADDING));
setFocusable(false);
setEditable(false);
setLineWrap(true);
setWrapStyleWord(true);
setMinimumSize(new Dimension(CARD_WIDTH + 2 * PADDING, CARD_HEIGHT + 2 * PADDING));
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(final MouseEvent e) {
if (!spell.getStackDescription().startsWith("Morph ")) {
CMatchUI.SINGLETON_INSTANCE.setCard(spell.getSpellAbility().getHostCard());
}
}
});
if (spell.getSpellAbility().isOptionalTrigger() && spell.getSpellAbility().getActivatingPlayer().getLobbyPlayer() == viewer) {
addMouseListener(new FMouseAdapter() {
@Override
public void onRightClick(MouseEvent e) {
otMenu.setStackInstance(spell);
otMenu.show(e.getComponent(), e.getX(), e.getY());
}
});
}
if (spell.getStackDescription().startsWith("Morph ")) {
setBackground(new Color(0, 0, 0, 0));
setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
}
else if (CardUtil.getColors(spell.getSourceCard()).isMulticolor()) {
setBackground(new Color(253, 175, 63));
setForeground(Color.black);
}
else if (sourceCard.isBlack()) {
setBackground(Color.black);
setForeground(Color.white);
}
else if (sourceCard.isBlue()) {
setBackground(new Color(71, 108, 191));
setForeground(Color.white);
}
else if (sourceCard.isGreen()) {
setBackground(new Color(23, 95, 30));
setForeground(Color.white);
}
else if (sourceCard.isRed()) {
setBackground(new Color(214, 8, 8));
setForeground(Color.white);
}
else if (sourceCard.isWhite()) {
setBackground(Color.white);
setForeground(Color.black);
}
else if (sourceCard.isArtifact() || sourceCard.isLand()) {
setBackground(new Color(111, 75, 43));
setForeground(Color.white);
}
else {
setBackground(new Color(0, 0, 0, 0));
setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
}
}
else if (CardUtil.getColors(s0.getSourceCard()).isMulticolor()) {
tar.setBackground(new Color(253, 175, 63));
tar.setForeground(Color.black);
}
else if (s0.getSourceCard().isBlack()) {
tar.setBackground(Color.black);
tar.setForeground(Color.white);
}
else if (s0.getSourceCard().isBlue()) {
tar.setBackground(new Color(71, 108, 191));
tar.setForeground(Color.white);
}
else if (s0.getSourceCard().isGreen()) {
tar.setBackground(new Color(23, 95, 30));
tar.setForeground(Color.white);
}
else if (s0.getSourceCard().isRed()) {
tar.setBackground(new Color(214, 8, 8));
tar.setForeground(Color.white);
}
else if (s0.getSourceCard().isWhite()) {
tar.setBackground(Color.white);
tar.setForeground(Color.black);
}
else if (s0.getSourceCard().isArtifact() || s0.getSourceCard().isLand()) {
tar.setBackground(new Color(111, 75, 43));
tar.setForeground(Color.white);
}
else {
tar.setBackground(new Color(0, 0, 0, 0));
tar.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D g2d = (Graphics2D) g;
//draw image for source card
BufferedImage img = ImageCache.getImage(sourceCard, CARD_WIDTH, CARD_HEIGHT);
if (img != null) {
g2d.drawImage(img, null, PADDING, PADDING);
}
}
}
//========= Custom class handling
private final class OptionalTriggerMenu extends JPopupMenu {
private final static class OptionalTriggerMenu extends JPopupMenu {
private static final long serialVersionUID = 1548494191627807962L;
private final JCheckBoxMenuItem jmiAccept;
private final JCheckBoxMenuItem jmiDecline;
@@ -291,7 +259,6 @@ public enum VStack implements IVDoc<CStack> {
private Integer triggerID = 0;
public OptionalTriggerMenu(){
jmiAccept = new JCheckBoxMenuItem("Always Accept");
jmiDecline = new JCheckBoxMenuItem("Always Decline");
jmiAsk = new JCheckBoxMenuItem("Always Ask");
@@ -347,95 +314,4 @@ public enum VStack implements IVDoc<CStack> {
}
}
}
@SuppressWarnings("serial")
public class StackArea extends CardPanelContainer {
private static final float STACK_SPACING_Y = 0.1f;
private Dimension size;
public StackArea(final FScrollPane scrollPane) {
super(scrollPane);
}
/** {@inheritDoc} */
@Override
public final void doLayout() {
if (this.getCardPanels().isEmpty()) {
return;
}
final Rectangle rect = this.getScrollPane().getVisibleRect();
final Insets insets = this.getScrollPane().getInsets();
rect.width -= insets.left;
rect.height -= insets.top;
rect.width -= insets.right;
rect.height -= insets.bottom;
int maxWidth = rect.width - CardArea.GUTTER_X * 2;
int maxHeight = rect.height - CardArea.GUTTER_Y * 2;
int cardWidth = Math.min(maxWidth, this.getCardWidthMax());
int cardHeight = Math.round(cardWidth * CardPanel.ASPECT_RATIO);
if (cardHeight > maxHeight) {
cardHeight = maxHeight;
cardWidth = Math.round(cardHeight / CardPanel.ASPECT_RATIO);
}
int x = CardArea.GUTTER_X + (maxWidth - cardWidth) / 2;
int y = CardArea.GUTTER_Y;
int cardSpacingY = Math.round(cardHeight * STACK_SPACING_Y);
List<CardPanel> panels = this.getCardPanels();
for (int i = panels.size() - 1; i >= 0; i--) {
CardPanel panel = panels.get(i);
panel.setCardBounds(x, y, cardWidth, cardHeight);
this.setComponentZOrder(panel, i);
y += cardSpacingY;
}
maxWidth = rect.width;
maxHeight = Math.max(rect.height, y - cardSpacingY + cardHeight);
final Dimension oldPreferredSize = this.getPreferredSize();
this.setPreferredSize(new Dimension(maxWidth, maxHeight));
if ((oldPreferredSize.width != maxWidth) || (oldPreferredSize.height != maxHeight)) {
this.getParent().invalidate();
this.getParent().validate();
}
}
@Override
public final void paint(final Graphics g) {
Dimension newSize = this.getScrollPane().getSize();
if (this.size == null || !this.size.equals(newSize)) {
if (this.size != null) {
this.revalidate();
}
this.size = newSize;
}
super.paint(g);
}
@Override
protected CardPanel getCardPanel(int x, int y) {
// TODO Auto-generated method stub
return null;
}
/** {@inheritDoc} */
@Override
public final void mouseOver(final CardPanel panel, final MouseEvent evt) {
super.mouseOver(panel, evt);
}
/** {@inheritDoc} */
@Override
public final void mouseLeftClicked(final CardPanel panel, final MouseEvent evt) {
super.mouseLeftClicked(panel, evt);
}
/** {@inheritDoc} */
@Override
public final void mouseRightClicked(final CardPanel panel, final MouseEvent evt) {
super.mouseRightClicked(panel, evt);
}
}
}

View File

@@ -58,7 +58,6 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
UI_SCALE_LARGER ("true"),
UI_RANDOM_ART_IN_POOLS ("true"),
UI_COMPACT_PROMPT ("false"),
UI_STACK_CARD_VIEW ("false"),
UI_CARD_SIZE ("small"),
UI_BUGZ_NAME (""),
UI_BUGZ_PWD (""),