New feedback panel (supports mana symbols).

This commit is contained in:
magenoxx 2010-12-25 22:52:16 +03:00
parent faa09b45b7
commit b9eba43ccf
9 changed files with 429 additions and 12 deletions

View file

@ -66,6 +66,7 @@ import javax.swing.UIManager;
import mage.client.cards.CardsStorage;
import mage.client.components.MageComponents;
import mage.client.components.arcane.ManaSymbols;
import mage.client.dialog.*;
import mage.client.plugins.impl.Plugins;
import mage.client.remote.Session;
@ -151,6 +152,8 @@ public class MageFrame extends javax.swing.JFrame {
session.getUI().addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
desktopPane.add(cardInfoPane, JLayeredPane.POPUP_LAYER);
ManaSymbols.loadImages();
String filename = "/background.jpg";
try {
if (Plugins.getInstance().isThemePluginLoaded()) {

View file

@ -0,0 +1,68 @@
package mage.client.components;
import mage.client.components.arcane.ManaSymbols;
import mage.client.components.arcane.UI;
import mage.view.CardView;
import javax.swing.*;
import java.awt.*;
/**
* Component for displaying text in mage.
* Supports drawing mana symbols.
*
* @author nantuko
*/
public class MageTextArea extends JEditorPane {
public MageTextArea() {
UI.setHTMLEditorKit(this);
setEditable(false);
setBackground(new Color(0, 0, 0, 0)); // transparent background
setFocusable(false);
setBorder(BorderFactory.createLineBorder(Color.red));
//setSelectionColor(new Color(0, 0, 0, 0));
}
public void setText(String text) {
setText(text, null);
}
public void setText(String text, CardView source) {
if (text == null) return;
boolean smallImages = false;
int fontSize = 12;
String fontFamily = "arial";
final StringBuffer buffer = new StringBuffer(512);
buffer.append("<html><body style='font-family:");
buffer.append(fontFamily);
buffer.append(";font-size:");
buffer.append(fontSize);
buffer.append("pt;margin:3px 3px 3px 3px'>");
text = text.replaceAll("#([^#]+)#", "<i>$1</i>");
text = text.replaceAll("\\s*//\\s*", "<hr width='50%'>");
text = text.replace("\r\n", "<div style='font-size:5pt'></div>");
text += "<br>";
if (text.length() > 0) {
//buffer.append("<br>");
//text = text.replaceAll("\\{this\\}", card.getName());
//text = text.replaceAll("\\{source\\}", card.getName());
buffer.append(ManaSymbols.replaceSymbolsWithHTML(text, smallImages));
}
buffer.append("</body></html>");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MageTextArea.super.setText(buffer.toString());
//System.out.println(buffer.toString());
setCaretPosition(0);
}
});
}
}

View file

@ -0,0 +1,98 @@
package mage.client.components.arcane;
import mage.client.constants.Constants;
import mage.client.util.gui.BufferedImageBuilder;
import mage.client.util.gui.ImageResizeUtil;
import org.apache.log4j.Logger;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
public class ManaSymbols {
private static final Logger log = Logger.getLogger(ManaSymbols.class);
static private final Map<String, Image> manaImages = new HashMap<String, Image>();
static private final Map<String, Image> manaImagesOriginal = new HashMap<String, Image>();
static private Pattern replaceSymbolsPattern = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}");
static private boolean noManaSymbols = false;
static public void loadImages () {
String[] symbols = new String[] {"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9", "B", "BG",
"BR", "G", "GU", "GW", "R", "RG", "RW", "S", "T", "U", "UB", "UR", "W", "WB", "WU", "X" /*, "Y", "Z", "slash"*/};
for (String symbol : symbols) {
File file = new File(Constants.RESOURCE_PATH_MANA_LARGE + "/" + symbol + ".jpg");
BufferedImageBuilder builder = new BufferedImageBuilder();
Rectangle r = new Rectangle(11, 11);
try {
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
BufferedImage resized = ImageResizeUtil.getResizedImage(builder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
manaImages.put(symbol, resized);
} catch (Exception e) {
noManaSymbols = true;
}
file = new File(Constants.RESOURCE_PATH_MANA_MEDIUM + "/" + symbol + ".jpg");
try {
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
manaImagesOriginal.put(symbol, image);
} catch (Exception e) {}
}
}
static public Image getManaSymbolImage(String symbol) {
return manaImagesOriginal.get(symbol);
}
static public void draw (Graphics g, String manaCost, int x, int y) {
if (manaCost.length() == 0) return;
manaCost = manaCost.replace("\\", "");
manaCost = UI.getDisplayManaCost(manaCost);
StringTokenizer tok = new StringTokenizer(manaCost, " ");
while (tok.hasMoreTokens()) {
String symbol = tok.nextToken().substring(0);
Image image = manaImages.get(symbol);
if (image == null) {
//log.error("Symbol not recognized \"" + symbol + "\" in mana cost: " + manaCost);
continue;
}
g.drawImage(image, x, y, null);
x += symbol.length() > 2 ? 10 : 12; // slash.png is only 10 pixels wide.
}
}
static public String getStringManaCost(List<String> manaCost) {
StringBuilder sb = new StringBuilder();
for (String s : manaCost) {
sb.append(s);
}
return sb.toString().replace("{", "").replace("}", " ").trim();
}
static public int getWidth(String manaCost) {
int width = 0;
manaCost = manaCost.replace("\\", "");
StringTokenizer tok = new StringTokenizer(manaCost, " ");
while (tok.hasMoreTokens()) {
String symbol = tok.nextToken().substring(0);
width += symbol.length() > 2 ? 10 : 12; // slash.png is only 10 pixels wide.
}
return width;
}
static public synchronized String replaceSymbolsWithHTML (String value, boolean small) {
if (noManaSymbols) {
return value;
} else {
if (small)
return replaceSymbolsPattern.matcher(value).replaceAll("<img src='file:plugins/images/symbols/small/$1$2.jpg' alt='$1$2' width=11 height=11>");
else {
value = value.replace("{slash}", "<img src='file:plugins/images/symbols/medium/slash.jpg' alt='slash' width=10 height=13>");
return replaceSymbolsPattern.matcher(value).replaceAll("<img src='file:plugins/images/symbols/medium/$1$2.jpg' alt='$1$2' width=13 height=13>");
}
}
}
}

View file

@ -0,0 +1,163 @@
package mage.client.components.arcane;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.ImageView;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Hashtable;
/**
* UI utility functions.
*/
public class UI {
static private Hashtable<URL, Image> imageCache = new Hashtable<URL, Image>();
static public JToggleButton getToggleButton () {
JToggleButton button = new JToggleButton();
button.setMargin(new Insets(2, 4, 2, 4));
return button;
}
static public JButton getButton () {
JButton button = new JButton();
button.setMargin(new Insets(2, 4, 2, 4));
return button;
}
static public void setTitle (JPanel panel, String title) {
Border border = panel.getBorder();
if (border instanceof TitledBorder) {
((TitledBorder)panel.getBorder()).setTitle(title);
panel.repaint();
} else
panel.setBorder(BorderFactory.createTitledBorder(title));
}
@SuppressWarnings("deprecation")
static public URL getFileURL (String path) {
File file = new File(path);
if (file.exists()) {
try {
return file.toURL();
} catch (MalformedURLException ignored) {
}
}
return UI.class.getResource(path);
}
static public ImageIcon getImageIcon (String path) {
try {
InputStream stream;
stream = UI.class.getResourceAsStream(path);
if (stream == null && new File(path).exists()) stream = new FileInputStream(path);
if (stream == null) throw new RuntimeException("Image not found: " + path);
byte[] data = new byte[stream.available()];
stream.read(data);
return new ImageIcon(data);
} catch (IOException ex) {
throw new RuntimeException("Error reading image: " + path);
}
}
static public void setHTMLEditorKit (JEditorPane editorPane) {
editorPane.getDocument().putProperty("imageCache", imageCache); // Read internally by ImageView, but never written.
// Extend all this shit to cache images.
editorPane.setEditorKit(new HTMLEditorKit() {
private static final long serialVersionUID = -54602188235105448L;
public ViewFactory getViewFactory () {
return new HTMLFactory() {
public View create (Element elem) {
Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
if (o instanceof HTML.Tag) {
HTML.Tag kind = (HTML.Tag)o;
if (kind == HTML.Tag.IMG) return new ImageView(elem) {
public URL getImageURL () {
URL url = super.getImageURL();
// Put an image into the cache to be read by other ImageView methods.
if (url != null && imageCache.get(url) == null)
imageCache.put(url, Toolkit.getDefaultToolkit().createImage(url));
return url;
}
};
}
return super.create(elem);
}
};
}
});
}
static public void setVerticalScrollingView (JScrollPane scrollPane, final Component view) {
final JViewport viewport = new JViewport();
viewport.setLayout(new ViewportLayout() {
private static final long serialVersionUID = 7701568740313788935L;
public void layoutContainer (Container parent) {
viewport.setViewPosition(new Point(0, 0));
Dimension viewportSize = viewport.getSize();
int width = viewportSize.width;
int height = Math.max(view.getPreferredSize().height, viewportSize.height);
viewport.setViewSize(new Dimension(width, height));
}
});
viewport.setView(view);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setViewport(viewport);
}
static public String getDisplayManaCost (String manaCost) {
manaCost = manaCost.replace("/", "{slash}");
// A pipe in the cost means "process left of the pipe as the card color, but display right of the pipe as the cost".
int pipePosition = manaCost.indexOf("{|}");
if (pipePosition != -1) manaCost = manaCost.substring(pipePosition + 3);
return manaCost;
}
static public void invokeLater (Runnable runnable) {
EventQueue.invokeLater(runnable);
}
static public void invokeAndWait (Runnable runnable) {
if (EventQueue.isDispatchThread()) {
runnable.run();
return;
}
try {
EventQueue.invokeAndWait(runnable);
} catch (InterruptedException ex) {
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
static public void setSystemLookAndFeel () {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
System.err.println("Error setting look and feel:");
ex.printStackTrace();
}
}
static public void setDefaultFont (Font font) {
for (Object key : Collections.list(UIManager.getDefaults().keys())) {
Object value = UIManager.get(key);
if (value instanceof javax.swing.plaf.FontUIResource) UIManager.put(key, font);
}
}
}

View file

@ -26,10 +26,11 @@
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.client.util;
package mage.client.constants;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import java.io.File;
/**
*
@ -73,4 +74,12 @@ public final class Constants {
public static final double SCALE_FACTOR = 0.5;
public static final String PLUGINS_DIRECTORY = "plugins/";
public static final String RESOURCE_PATH_MANA_LARGE = IO.imageBaseDir + "symbols" + File.separator + "large";
public static final String RESOURCE_PATH_MANA_MEDIUM = IO.imageBaseDir + "symbols" + File.separator + "medium";
public interface IO {
public static final String imageBaseDir = "plugins" + File.separator + "images" + File.separator;
public static final String IMAGE_PROPERTIES_FILE = "image.url.properties";
}
}

View file

@ -45,6 +45,7 @@ import java.util.UUID;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import mage.client.MageFrame;
import mage.client.components.MageTextArea;
import mage.client.remote.Session;
import mage.util.Logging;
@ -182,7 +183,8 @@ public class FeedbackPanel extends javax.swing.JPanel {
btnRight = new javax.swing.JButton();
btnLeft = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
lblMessage = new javax.swing.JTextArea();
//lblMessage = new javax.swing.JTextArea();
lblMessage = new MageTextArea();
btnSpecial = new javax.swing.JButton();
setBackground(new java.awt.Color(204, 204, 204));
@ -204,14 +206,16 @@ public class FeedbackPanel extends javax.swing.JPanel {
jScrollPane1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
lblMessage.setBackground(new java.awt.Color(204, 204, 204));
lblMessage.setColumns(20);
//lblMessage.setBackground(new java.awt.Color(204, 204, 204));
/*lblMessage.setColumns(20);
lblMessage.setEditable(false);
lblMessage.setLineWrap(true);
lblMessage.setRows(2);
lblMessage.setWrapStyleWord(true);
lblMessage.setWrapStyleWord(true);*/
lblMessage.setBorder(null);
jScrollPane1.setViewportView(lblMessage);
jScrollPane1.setBorder(null);
btnSpecial.setText("Special");
btnSpecial.addActionListener(new java.awt.event.ActionListener() {
@ -265,12 +269,10 @@ public class FeedbackPanel extends javax.swing.JPanel {
}//GEN-LAST:event_btnSpecialActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnLeft;
private javax.swing.JButton btnRight;
private javax.swing.JButton btnSpecial;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea lblMessage;
// End of variables declaration//GEN-END:variables
//private javax.swing.JTextArea lblMessage;
private MageTextArea lblMessage;
}

View file

@ -0,0 +1,58 @@
package mage.client.util.gui;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
public class BufferedImageBuilder {
private static final int DEFAULT_IMAGE_TYPE = BufferedImage.TYPE_INT_RGB;
public BufferedImage bufferImage(Image image) {
return bufferImage(image, DEFAULT_IMAGE_TYPE);
}
public BufferedImage bufferImage(Image image, int type) {
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(image, null, null);
//waitForImage(bufferedImage);
return bufferedImage;
}
private void waitForImage(BufferedImage bufferedImage) {
final ImageLoadStatus imageLoadStatus = new ImageLoadStatus();
bufferedImage.getHeight(new ImageObserver() {
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
if (infoflags == ALLBITS) {
imageLoadStatus.heightDone = true;
return true;
}
return false;
}
});
bufferedImage.getWidth(new ImageObserver() {
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
if (infoflags == ALLBITS) {
imageLoadStatus.widthDone = true;
return true;
}
return false;
}
});
while (!imageLoadStatus.widthDone && !imageLoadStatus.heightDone) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
}
}
}
class ImageLoadStatus {
public boolean widthDone = false;
public boolean heightDone = false;
}
}

View file

@ -1,10 +1,8 @@
package mage.client.util.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
@ -17,8 +15,8 @@ import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import mage.client.constants.Constants;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Constants;
public class ColorsChooser extends JComboBox implements ListCellRenderer {

View file

@ -0,0 +1,18 @@
package mage.client.util.gui;
import com.mortennobel.imagescaling.ResampleOp;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* @author nantuko
*/
public class ImageResizeUtil {
public static BufferedImage getResizedImage(BufferedImage original, Rectangle sizeNeed) {
ResampleOp resampleOp = new ResampleOp(sizeNeed.width, sizeNeed.height);
BufferedImage image = resampleOp.filter(original, null);
return image;
}
}