Draw CardPanel to a buffered image and cache it across instances

Speeds up GUI performance.
This commit is contained in:
draxdyn 2016-06-01 20:36:18 +02:00
parent 892cfdce45
commit b8e5f5f942

View file

@ -1,5 +1,7 @@
package org.mage.card.arcane; package org.mage.card.arcane;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
@ -23,6 +25,7 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.UUID; import java.util.UUID;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
@ -38,6 +41,7 @@ import mage.cards.action.TransferData;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.adapters.MageActionCallback; import mage.client.plugins.adapters.MageActionCallback;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.util.ImageCaches;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.client.util.audio.AudioManager; import mage.client.util.audio.AudioManager;
import mage.components.ImagePanel; import mage.components.ImagePanel;
@ -52,6 +56,7 @@ import mage.view.PermanentView;
import mage.view.StackAbilityView; import mage.view.StackAbilityView;
import net.java.truevfs.access.TFile; import net.java.truevfs.access.TFile;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL; import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
import org.mage.plugins.card.dl.sources.DirectLinksForDownload; import org.mage.plugins.card.dl.sources.DirectLinksForDownload;
import org.mage.plugins.card.images.ImageCache; import org.mage.plugins.card.images.ImageCache;
@ -158,6 +163,111 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
// if this is set, it's opened if the user right clicks on the card panel // if this is set, it's opened if the user right clicks on the card panel
private JPopupMenu popupMenu; private JPopupMenu popupMenu;
private static Map<Key, BufferedImage> IMAGE_CACHE;
private final static class Key
{
final int width;
final int height;
final int cardWidth;
final int cardHeight;
final int cardXOffset;
final int cardYOffset;
final boolean hasImage;
final boolean isSelected;
final boolean isChoosable;
final boolean isPlayable;
final boolean canAttack;
public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) {
this.width = width;
this.height = height;
this.cardWidth = cardWidth;
this.cardHeight = cardHeight;
this.cardXOffset = cardXOffset;
this.cardYOffset = cardYOffset;
this.hasImage = hasImage;
this.isSelected = isSelected;
this.isChoosable = isChoosable;
this.isPlayable = isPlayable;
this.canAttack = canAttack;
}
@Override
public int hashCode() {
int hash = 3;
hash = 19 * hash + this.width;
hash = 19 * hash + this.height;
hash = 19 * hash + this.cardWidth;
hash = 19 * hash + this.cardHeight;
hash = 19 * hash + this.cardXOffset;
hash = 19 * hash + this.cardYOffset;
hash = 19 * hash + (this.hasImage ? 1 : 0);
hash = 19 * hash + (this.isSelected ? 1 : 0);
hash = 19 * hash + (this.isChoosable ? 1 : 0);
hash = 19 * hash + (this.isPlayable ? 1 : 0);
hash = 19 * hash + (this.canAttack ? 1 : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Key other = (Key) obj;
if (this.width != other.width) {
return false;
}
if (this.height != other.height) {
return false;
}
if (this.cardWidth != other.cardWidth) {
return false;
}
if (this.cardHeight != other.cardHeight) {
return false;
}
if (this.cardXOffset != other.cardXOffset) {
return false;
}
if (this.cardYOffset != other.cardYOffset) {
return false;
}
if (this.hasImage != other.hasImage) {
return false;
}
if (this.isSelected != other.isSelected) {
return false;
}
if (this.isChoosable != other.isChoosable) {
return false;
}
if (this.isPlayable != other.isPlayable) {
return false;
}
if (this.canAttack != other.canAttack) {
return false;
}
return true;
}
}
static {
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function<Key, BufferedImage>() {
@Override
public BufferedImage apply(Key key) {
return createImage(key);
}
}));
}
public CardPanel(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) { public CardPanel(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
this.gameCard = newGameCard; this.gameCard = newGameCard;
this.callback = callback; this.callback = callback;
@ -475,15 +585,28 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g; Graphics2D g2d = (Graphics2D)(g.create());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (alpha != 1.0f) { if (alpha != 1.0f) {
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha); AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha);
g2d.setComposite(composite); g2d.setComposite(composite);
} }
if (!hasImage) { g2d.drawImage(IMAGE_CACHE.get(new Key(getWidth(), getHeight(), cardWidth, cardHeight, cardXOffset, cardYOffset, hasImage, isSelected, isChoosable, isPlayable, canAttack)), 0, 0, null);
g2d.dispose();
}
private static BufferedImage createImage(Key key) {
int cardWidth = key.cardWidth;
int cardHeight = key.cardHeight;
int cardXOffset = key.cardXOffset;
int cardYOffset = key.cardYOffset;
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(key.width, key.height);
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (!key.hasImage) {
g2d.setColor(new Color(30, 200, 200, 120)); g2d.setColor(new Color(30, 200, 200, 120));
} else { } else {
g2d.setColor(new Color(0, 0, 0, 0)); g2d.setColor(new Color(0, 0, 0, 0));
@ -492,19 +615,19 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE)); int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
if (isSelected) { if (key.isSelected) {
g2d.setColor(Color.green); g2d.setColor(Color.green);
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
} else if (isChoosable) { } else if (key.isChoosable) {
g2d.setColor(new Color(250, 250, 0, 230)); g2d.setColor(new Color(250, 250, 0, 230));
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
} else if (isPlayable) { } else if (key.isPlayable) {
g2d.setColor(new Color(153, 102, 204, 200)); g2d.setColor(new Color(153, 102, 204, 200));
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); //g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
} }
if (canAttack) { if (key.canAttack) {
g2d.setColor(new Color(0, 0, 255, 230)); g2d.setColor(new Color(0, 0, 255, 230));
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
} }
@ -515,6 +638,9 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
g2d.setColor(new Color(200,10,10,200)); g2d.setColor(new Color(200,10,10,200));
g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize); g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize);
}*/ }*/
g2d.dispose();
return image;
} }
@Override @Override