Package org.mage.card.arcane

Source Code of org.mage.card.arcane.CardPanel

package org.mage.card.arcane;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.swing.BorderFactory;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

import mage.Constants.CardType;
import mage.cards.MagePermanent;
import mage.cards.TextPopup;
import mage.cards.action.ActionCallback;
import mage.cards.action.TransferData;
import mage.components.ImagePanel;
import mage.utils.CardUtil;
import mage.view.AbilityView;
import mage.view.CardView;
import mage.view.PermanentView;
import mage.view.StackAbilityView;

import org.apache.log4j.Logger;
import org.mage.card.arcane.ScaledImagePanel.MultipassType;
import org.mage.card.arcane.ScaledImagePanel.ScalingType;
import org.mage.plugins.card.images.ImageCache;
import org.mage.plugins.card.utils.impl.ImageManagerImpl;


@SuppressWarnings({"unchecked","rawtypes"})
public class CardPanel extends MagePermanent implements MouseListener, MouseMotionListener {
  private static final long serialVersionUID = -3272134219262184410L;
 
  private static final Logger log = Logger.getLogger(CardPanel.class);
 
  static public final double TAPPED_ANGLE = Math.PI / 2;
  static public final float ASPECT_RATIO = 3.5f / 2.5f;
  static public final int POPUP_X_GAP = 1; // prevent popup window from blinking
  //static public final float ASPECT_RATIO = 1.0f;

  static public CardPanel dragAnimationPanel;

  public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
 
  static private final float ROUNDED_CORNER_SIZE = 0.1f;
  //static private final float SELECTED_BORDER_SIZE = 0.01f;
  static private final float BLACK_BORDER_SIZE = 0.03f;
  static private final int TEXT_GLOW_SIZE = 6;
  static private final float TEXT_GLOW_INTENSITY = 3f;
  static private final float rotCenterToTopCorner = 1.0295630140987000315797369464196f;
  static private final float rotCenterToBottomCorner = 0.7071067811865475244008443621048f;

  public CardView gameCard;
  public PermanentView gamePermanent;
  public CardPanel attachedToPanel;
  public List<CardPanel> attachedPanels = new ArrayList();
  public double tappedAngle = 0;
  public ScaledImagePanel imagePanel;
  public ImagePanel overlayPanel;

  private GlowText titleText;
  private GlowText ptText;
  private List<CardPanel> imageLoadListeners = new ArrayList(2);
  private boolean displayEnabled = true;
  private boolean isAnimationPanel;
  private int cardXOffset, cardYOffset, cardWidth, cardHeight;

  private boolean isSelected;
  private boolean showCastingCost;
  private boolean hasImage = false;
  private float alpha = 1.0f;
 
  private ActionCallback callback;
 
  protected boolean popupShowing;
  protected TextPopup popupText = new TextPopup();
  protected UUID gameId;
  private TransferData data = new TransferData();
 
  private boolean isPermanent;
  private boolean hasSickness;
 
  public CardPanel(CardView newGameCard, UUID gameId, boolean loadImage, ActionCallback callback) {
    this.gameCard = newGameCard;
    this.callback = callback;
    this.gameId = gameId;
    this.isPermanent = this.gameCard instanceof PermanentView;
   
    if (isPermanent) {
      this.gamePermanent = (PermanentView) this.gameCard;
      this.hasSickness = this.gamePermanent.hasSummoningSickness();
    }
   
    //for container debug (don't remove)
    //setBorder(BorderFactory.createLineBorder(Color.green));

    setBackground(Color.black);
    setOpaque(false);
   
    addMouseListener(this);
    addMouseMotionListener(this);
   
    titleText = new GlowText();
    setText(gameCard);
    titleText.setFont(getFont().deriveFont(Font.BOLD, 13f));
    titleText.setForeground(Color.white);
    titleText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
    titleText.setWrap(true);
    add(titleText);

    ptText = new GlowText();
    if (CardUtil.isCreature(gameCard)) {
      ptText.setText(gameCard.getPower() + "/" + gameCard.getToughness());
    } else if (CardUtil.isPlaneswalker(gameCard)) {
      ptText.setText(gameCard.getLoyalty());
    }
    ptText.setFont(getFont().deriveFont(Font.BOLD, 13f));
    ptText.setForeground(Color.white);
    ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
    add(ptText);
   
    BufferedImage sickness = ImageManagerImpl.getInstance().getSicknessImage();
    overlayPanel = new ImagePanel(sickness, ImagePanel.SCALED);
    overlayPanel.setOpaque(false);
    add(overlayPanel);

    imagePanel = new ScaledImagePanel();
    imagePanel.setBorder(BorderFactory.createLineBorder(Color.white));
    add(imagePanel);
    imagePanel.setScaleLarger(true);
    imagePanel.setScalingType(ScalingType.nearestNeighbor);
    imagePanel.setScalingBlur(true);
    imagePanel.setScalingMultiPassType(MultipassType.none);
   
    String cardType = getType(newGameCard);
    popupText.setText(getText(cardType, newGameCard));
   
    if (!loadImage) return;
   
    Util.threadPool.submit(new Runnable() {
      public void run () {
        try {
          tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
          BufferedImage srcImage = ImageCache.getImageOriginal(gameCard);
          srcImage = ImageCache.getNormalSizeImage(srcImage);
          if (srcImage != null) {
            hasImage = true;
            setText(gameCard);
            setImage(srcImage, srcImage);
          } else {
            log.warn("image wasn't found, card=" + gameCard.getName() + ", set=" + gameCard.getExpansionSetCode() + ", cid=" + gameCard.getCardNumber());
          }
        } catch (Exception e) {
          e.printStackTrace();
        } catch (Error err) {
          err.printStackTrace();
        }
      }
    });
  }
 
  private void setText(CardView card) {
    if (hasImage) {
      titleText.setText("");
    } else {
      titleText.setText(card.getName());
    }
  }

  private void setImage (Image srcImage, Image srcImageBlurred) {
    synchronized (imagePanel) {
      imagePanel.setImage(srcImage, srcImageBlurred);
      repaint();
      for (CardPanel cardPanel : imageLoadListeners) {
        cardPanel.setImage(srcImage, srcImageBlurred);
        cardPanel.repaint();
      }
      imageLoadListeners.clear();
    }
    layout();
  }

  public void setImage (final CardPanel panel) {
    synchronized (panel.imagePanel) {
      if (panel.imagePanel.hasImage())
        setImage(panel.imagePanel.srcImage, panel.imagePanel.srcImageBlurred);
      else
        panel.imageLoadListeners.add(this);
    }
  }

  public void setScalingType (ScalingType scalingType) {
    imagePanel.setScalingType(scalingType);
  }

  public void setDisplayEnabled (boolean displayEnabled) {
    this.displayEnabled = displayEnabled;
  }

  public boolean isDisplayEnabled () {
    return displayEnabled;
  }

  public void setAnimationPanel (boolean isAnimationPanel) {
    this.isAnimationPanel = isAnimationPanel;
  }

  public void setSelected (boolean isSelected) {
    this.isSelected = isSelected;
    repaint();
  }
 
  public void setAttacking (boolean isAttacking) {
    //TODO:uncomment
    //this.gameCard.setAttacking(isAttacking);
    repaint();
  }
 
  public boolean getSelected() {
    return this.isSelected;
  }
 
  public void setShowCastingCost (boolean showCastingCost) {
    this.showCastingCost = showCastingCost;
  }

  public void paint (Graphics g) {
    if (!displayEnabled) return;
    if (!isValid()) super.validate();
    Graphics2D g2d = (Graphics2D)g;
    if (tappedAngle > 0) {
      g2d = (Graphics2D)g2d.create();
      float edgeOffset = cardWidth / 2f;
      g2d.rotate(tappedAngle, cardXOffset + edgeOffset, cardYOffset + cardHeight - edgeOffset);
    }
    super.paint(g2d);
  }

  protected void paintComponent (Graphics g) {
    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
   
    if (alpha != 1.0f) {
      AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha);
      g2d.setComposite(composite);
    }
   
    //TODO:uncomment
    if (!hasImage /*&& gameCard.getTableID() > 0*/) {
      g2d.setColor(new Color(30,200,200,120));
    } else {
      g2d.setColor(new Color(0,0,0,200))
    }
   
    //for debug repainting
    //g2d.setColor(new Color(MyRandom.random.nextInt(255),MyRandom.random.nextInt(255),MyRandom.random.nextInt(255),150));
    int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
    g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
    if (isSelected) {
      //g2d.setColor(new Color(0,250,0,200));
      g2d.setColor(new Color(200,120,40,200));
      g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize);
    }
   
    //TODO:uncomment
    /*
    if (gameCard.isAttacking()) {
      g2d.setColor(new Color(200,10,10,200));
      g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize);
    }*/
   
    /*if (isSelected) {
      g2d.setColor(Color.green);
      int offset = gameCard.isTapped() ? 1 : 0;
      for (int i = 1, n = Math.max(1, Math.round(cardWidth * SELECTED_BORDER_SIZE)); i <= n; i++)
        g2d.drawRoundRect(cardXOffset - i, cardYOffset - i + offset, cardWidth + i * 2 - 1, cardHeight + i * 2 - 1,
          cornerSize, cornerSize);
    }*/
   
   
    //for debugging
    // REMOVEME
    /*
    Point component = getLocation();
   
    int cx = getCardX() + component.x;
    int cy = getCardY() + component.y;
    int cw = getCardWidth();
    int ch = getCardHeight();
   
    g2d.setColor(Color.white);
    g2d.drawRect(getCardX() - component.x, getCardY() - component.y, cw, ch);
    */
  }

  protected void paintChildren (Graphics g) {
    super.paintChildren(g);

    if (showCastingCost && !isAnimationPanel && cardWidth < 200 && cardWidth > 60) {
      String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
      int width = ManaSymbols.getWidth(manaCost);
      if (hasImage) {
                ManaSymbols.draw(g, manaCost, cardXOffset + cardWidth - width - 5, cardYOffset + 5);
      } else {
                ManaSymbols.draw(g, manaCost, cardXOffset + 8, cardHeight - 9);
          }
    }
  }

  public void layout() {
    int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE);
    imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
    imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
   
    if (hasSickness && CardUtil.isCreature(gameCard) && isPermanent) {
      overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
      overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
    } else {
      overlayPanel.setVisible(false);
    }
   
    int fontHeight = Math.round(cardHeight * (27f / 680));
    boolean showText = (!isAnimationPanel && fontHeight < 12);
    titleText.setVisible(showText);
    ptText.setVisible(showText);

    int titleX = Math.round(cardWidth * (20f / 480));
    int titleY = Math.round(cardHeight * (9f / 680));
    titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight);

    Dimension ptSize = ptText.getPreferredSize();
    ptText.setSize(ptSize.width, ptSize.height);
    int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2;
    int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height;
   
    int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f);
   
    ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);

    if (isAnimationPanel || cardWidth < 200)
      imagePanel.setScalingType(ScalingType.nearestNeighbor);
    else
      imagePanel.setScalingType(ScalingType.bilinear);
  }

  public String toString () {
    return gameCard.toString();
  }

  @Override
  public void setCardBounds (int x, int y, int width, int height) {
    cardWidth = width;
    cardHeight = height;
    int rotCenterX = Math.round(width / 2f);
    int rotCenterY = height - rotCenterX;
    int rotCenterToTopCorner = Math.round(width * CardPanel.rotCenterToTopCorner);
    int rotCenterToBottomCorner = Math.round(width * CardPanel.rotCenterToBottomCorner);
    int xOffset = rotCenterX - rotCenterToBottomCorner;
    int yOffset = rotCenterY - rotCenterToTopCorner;
    cardXOffset = -xOffset;
    cardYOffset = -yOffset;
    width = -xOffset + rotCenterX + rotCenterToTopCorner;
    height = -yOffset + rotCenterY + rotCenterToBottomCorner;
    setBounds(x + xOffset, y + yOffset, width, height);
  }

  public void repaint () {
    Rectangle b = getBounds();
    JRootPane rootPane = SwingUtilities.getRootPane(this);
    if (rootPane == null) return;
    Point p = SwingUtilities.convertPoint(getParent(), b.x, b.y, rootPane);
    rootPane.repaint(p.x, p.y, b.width, b.height);
  }

  public int getCardX () {
    return getX() + cardXOffset;
  }

  public int getCardY () {
    return getY() + cardYOffset;
  }

  public int getCardWidth () {
    return cardWidth;
  }

  public int getCardHeight () {
    return cardHeight;
  }

  public Point getCardLocation () {
    Point p = getLocation();
    p.x += cardXOffset;
    p.y += cardYOffset;
    return p;
  }

  public CardView getCard() {
    return this.gameCard;
  }
 
  @Override
  public void setAlpha(float alpha) {
    this.alpha = alpha;
  }
 
  public float getAlpha() {
    return alpha;
  }
 
  public int getCardXOffset() {
    return cardXOffset;
  }

  public int getCardYOffset() {
    return cardYOffset;
  }
 
  public void updateImage() {
    if (!hasImage) {
      Util.threadPool.submit(new Runnable() {
        public void run () {
          //TODO: BufferedImage srcImage = ImageCache.getImageOriginal(gameCard);
          //BufferedImage srcImage = null;
          //tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0;
          /*if (srcImage != null) {
            hasImage = true;
            setText(gameCard);
            setImage(srcImage, srcImage);
          }*/
        }
      });
    }
  }

  @Override
  public List<MagePermanent> getLinks() {
    List<MagePermanent> list = new ArrayList<MagePermanent>();
    if (attachedPanels == null) return list;
    for (MagePermanent p : attachedPanels) {
      list.add(p);
    }
    return list;
  }

  @Override
  public boolean isTapped() {
    if (isPermanent) {
      return ((PermanentView)gameCard).isTapped();
    }
    return false;
  }

  @Override
  public void onBeginAnimation() {
  }

  @Override
  public void onEndAnimation() {
  }

  @Override
  public void update(CardView card) {
    if (isPermanent) {
      if (isTapped() != ((PermanentView)card).isTapped()) {
        Animation.tapCardToggle(this, this);
      }
    }
    if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) {
      ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")");
    } else if (CardUtil.isCreature(card)) {
      ptText.setText(card.getPower() + "/" + card.getToughness());
    } else if (CardUtil.isPlaneswalker(card)) {
      ptText.setText(card.getLoyalty());
    } else {
      ptText.setText("");
    }
    setText(card);
    this.gameCard = card;
   
    String cardType = getType(card);
    popupText.setText(getText(cardType, card));
   
    if (hasSickness && CardUtil.isCreature(gameCard) && isPermanent) {
      overlayPanel.setVisible(true);
    } else {
      overlayPanel.setVisible(false);
    }
   
    repaint();
  }

  @Override
  public boolean contains(int x, int y) {
    if (containsThis(x, y, true)) return true;

    /*
     * if (attachedCount > 0) { for (MWCardImpl card :
     * mwAttachedCards.keySet()) { if (card.contains(x, y)) return true; } }
     */

    return false;
  }
 
  public boolean containsThis(int x, int y, boolean root) {
    //log.info("x="+x+", y="+y);
    Point component = getLocation();
   
    //int dy = component.y;
    //if (root) dy = 0;
   
    int cx = getCardX() - component.x;
    int cy = getCardY() - component.y;
    int cw = getCardWidth();
    int ch = getCardHeight();
    if (isTapped()) {
      cy = ch - cw + cx /*+ attachedDy*attachedCount*/;
      ch = cw;
      cw = getCardHeight();
    }
    //int dx = drawIcons ? 19 : 0;
    //int dx = 0;
   
    if (x >= cx && x <= cx + cw && y >= cy && y <= cy + ch) {
      //log.info("!cx="+cx+", cy="+cy+", dx="+cw +", ch="+ch);
      //log.info(getOriginal().getId());
      return true;
    } else {
      //log.info("cx="+cx+", cy="+cy+", dx="+cw +", ch="+ch); 
    }
      return false;
    }
 
  @Override
  public CardView getOriginal() {
    return this.gameCard;
  }

  @Override
  public Image getImage() {
    return ImageCache.getImageOriginal(gameCard);
  }

  @Override
  public void mouseClicked(MouseEvent e) {
  }

  @Override
  public void mouseEntered(MouseEvent e) {
    if (!popupShowing) {
      synchronized (this) {
        if (!popupShowing) {
          popupShowing = true;
          callback.mouseEntered(e, getTransferDataForMouseEntered());
        }
      }
    }
  }
 
  @Override
  public void mouseDragged(MouseEvent e) {}

  @Override
  public void mouseMoved(MouseEvent e) {
    data.component = this;
    callback.mouseMoved(e, data);
  }

  @Override
  public void mouseExited(MouseEvent e) {
    if(getMousePosition(true) != null) return;
    if (popupShowing) {
      synchronized (this) {
        if (popupShowing) {
          popupShowing = false;
          data.component = this;
          data.card = this.gameCard;
          data.popupText = popupText;
          callback.mouseExited(e, data);
        }
      }
    }
  }

  @Override
  public void mousePressed(MouseEvent e) {
    data.component = this;
    data.card = this.gameCard;
    data.gameId = this.gameId;
    callback.mousePressed(e, data);
  }

  @Override
  public void mouseReleased(MouseEvent e) {}

  /**
   * Prepares data to be sent to action callback on client side.
   *
   * @return
   */
  private TransferData getTransferDataForMouseEntered() {
    data.component = this;
    data.card = this.gameCard;
    data.popupText = popupText;
    data.popupOffsetX = isTapped() ? cardHeight + cardXOffset + POPUP_X_GAP : cardWidth + cardXOffset + POPUP_X_GAP;
    data.popupOffsetY = 40;
    data.locationOnScreen = this.getLocationOnScreen();
    return data;
  }
 
  protected String getType(CardView card) {
    StringBuilder sbType = new StringBuilder();

    for (String superType: card.getSuperTypes()) {
      sbType.append(superType).append(" ");
    }

    for (mage.Constants.CardType cardType: card.getCardTypes()) {
      sbType.append(cardType.toString()).append(" ");
    }

    if (card.getSubTypes().size() > 0) {
      sbType.append("- ");
      for (String subType: card.getSubTypes()) {
        sbType.append(subType).append(" ");
      }
    }

    return sbType.toString();
  }
 
  protected String getText(String cardType, CardView card) {
    StringBuilder sb = new StringBuilder();
    if (card instanceof StackAbilityView || card instanceof AbilityView) {
      for (String rule: card.getRules()) {
        sb.append("\n").append(rule);
      }
    }
    else {
      sb.append(card.getName());
      if (card.getManaCost().size() > 0) {
        sb.append("\n").append(card.getManaCost());
      }
      sb.append("\n").append(cardType);
      if (card.getColor().hasColor()) {
        sb.append("\n").append(card.getColor().toString());
      }
      if (card.getCardTypes().contains(CardType.CREATURE)) {
        sb.append("\n").append(card.getPower()).append("/").append(card.getToughness());
      }
      else if (card.getCardTypes().contains(CardType.PLANESWALKER)) {
        sb.append("\n").append(card.getLoyalty());
      }
      for (String rule: card.getRules()) {
        sb.append("\n").append(rule);
      }
      if (card.getExpansionSetCode() != null && card.getExpansionSetCode().length() > 0) {
        sb.append("\n").append(card.getCardNumber()).append(" - ");
        //sb.append(Sets.getInstance().get(card.getExpansionSetCode()).getName()).append(" - ");
        sb.append(card.getExpansionSetCode()).append(" - ");
        sb.append(card.getRarity().toString());
      }
    }
//    sb.append("\n").append(card.getId());
    return sb.toString();
  }

  @Override
  public void update(PermanentView card) {
    update((CardView)card);
    this.hasSickness = card.hasSummoningSickness();
  }

  @Override
  public PermanentView getOriginalPermanent() {
    throw new IllegalStateException("Is not permanent.");
  }
}
TOP

Related Classes of org.mage.card.arcane.CardPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.