package common.ui;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.table.TableCellRenderer;
import common.PubEntity;
import common.PubGroupMember;
import common.PubRoomEntity;
import common.gameevent.StatGameEvent.StatType;
public class EntityList<E extends PubEntity> extends JPanel {
private static final long serialVersionUID = 3833181437003642169L;
private static final Icon DEATH_ICON = new ImageIcon(EntityList.class.getClassLoader().getResource("clientrc/dead.png"));
private static final Icon PLAYER_ICON = new ImageIcon(EntityList.class.getClassLoader().getResource("clientrc/player.gif"));
private static final Icon NPC_ICON = new ImageIcon(EntityList.class.getClassLoader().getResource("clientrc/npc.gif"));
private static final Icon ITEM_ICON = new ImageIcon(EntityList.class.getClassLoader().getResource("clientrc/item.gif"));
private static final double ARROW_HEAD_WIDTH = Math.toRadians(90);
private static final double ARROW_HEAD_HEIGHT = 0.6;
private final EntityTableModel<E> model;
public EntityList(String name) {
super(new BorderLayout());
model = new EntityTableModel<E>(name);
final JProgressBar healthBar = makeHealthBar();
final JLabel entityLabel = new JLabel(".");
final JPanel entityPanel = makeEntityPanel(healthBar, entityLabel);
final JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(
new TableCellRenderer() {
public Component getTableCellRendererComponent(
JTable ltable, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
PubEntity entity = (PubEntity) value;
entityLabel.setText(entity.name);
entityLabel.setForeground(Color.black);
List<Icon> icons = new ArrayList<Icon>();
switch (entity.type) {
case PLAYER: icons.add(PLAYER_ICON); break;
case NPC: icons.add(NPC_ICON); break;
case ITEM: icons.add(ITEM_ICON); break;
}
if (entity.hp < 0) {
icons.add(DEATH_ICON);
}
if (entity instanceof PubGroupMember) {
PubGroupMember member = (PubGroupMember) entity;
if (member.showArrow) {
icons.add(makeArrowIcon(member.lastArrowDirection));
}
if (member.withYou) {
entityPanel.setBackground(Color.white);
}
else {
entityPanel.setBackground(Color.lightGray);
}
healthBar.setForeground(Color.red);
}
else {
PubRoomEntity roomEntity = (PubRoomEntity) entity;
entityPanel.setBackground(Color.white);
switch (roomEntity.type) {
case PLAYER: healthBar.setForeground(Color.red); break;
case NPC: healthBar.setForeground(Color.magenta); break;
case ITEM: healthBar.setForeground(Color.green); break;
default: System.err.println("Unknown room entity type: " + roomEntity.type);
}
}
if (icons.size() == 0) {
entityLabel.setIcon(null);
}
else {
entityLabel.setIcon(combineIcons(icons));
}
healthBar.setValue(entity.hp);
return entityPanel;
}
});
table.setRowHeight(entityPanel.getPreferredSize().height);
table.setFocusable(false);
JScrollPane scroller = new JScrollPane(table);
scroller.setPreferredSize(new Dimension(1, 1));
add(scroller, BorderLayout.CENTER);
}
private static Icon combineIcons(final Collection<Icon> icons) {
return new Icon() {
public int getIconHeight() {
return 16;
}
public int getIconWidth() {
return icons.size() * 21 - 5;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
int num = 0;
for (Icon icon : icons) {
icon.paintIcon(c, g, x + 21 * num++, y);
}
}
};
}
private static JProgressBar makeHealthBar() {
JProgressBar healthBar = new JProgressBar(0, 10000);
healthBar.setBorder(new CompoundBorder(new EmptyBorder(4, 0, 0, 0), new LineBorder(Color.black, 1)));
healthBar.setPreferredSize(new Dimension(0, 12));
healthBar.setBackground(Color.white);
healthBar.setBorderPainted(true);
healthBar.setOpaque(false);
return healthBar;
}
private static JPanel makeEntityPanel(JProgressBar healthBar, JLabel entityLabel) {
JPanel entityPanel = new JPanel(new BorderLayout());
entityPanel.setBorder(new CompoundBorder(new LineBorder(Color.black, 1), new EmptyBorder(2, 2, 2, 2)));
entityPanel.add(entityLabel, BorderLayout.NORTH);
entityPanel.add(healthBar, BorderLayout.SOUTH);
entityPanel.setOpaque(true);
entityPanel.setBackground(Color.white);
return entityPanel;
}
private static Icon makeArrowIcon(double radians) {
double dsize = 16.0;
double asize = dsize * ARROW_HEAD_HEIGHT;
BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) img.getGraphics();
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0, 0, 16, 16);
g.setColor(Color.black);
g.translate(8, 8);
Polygon arrowHead = new Polygon();
int x = (int) (asize * Math.cos(radians - ARROW_HEAD_WIDTH) / 2.0);
int y = (int) (asize * Math.sin(radians - ARROW_HEAD_WIDTH) / 2.0);
arrowHead.addPoint(x, y);
x = (int) (dsize * Math.cos(radians) / 2.0);
y = (int) (dsize * Math.sin(radians) / 2.0);
arrowHead.addPoint(x, y);
x = (int) (asize * Math.cos(radians + ARROW_HEAD_WIDTH) / 2.0);
y = (int) (asize * Math.sin(radians + ARROW_HEAD_WIDTH) / 2.0);
arrowHead.addPoint(x, y);
g.fill(arrowHead);
dsize *= (1.0 + ARROW_HEAD_HEIGHT) / 2.0;
x = (int) (dsize * Math.cos(radians) / 2.0);
y = (int) (dsize * Math.sin(radians) / 2.0);
g.setStroke(new BasicStroke(2.0f));
g.drawLine(-x, -y, x, y);
g.dispose();
return new ImageIcon(img);
}
public void statUpdate(int id, StatType statType, int current, int max) {
model.statUpdate(id, statType, current, max);
}
public void clear(E... entities) {
model.clear(entities);
}
public void add(E... entities) {
model.add(entities);
}
public void modify(E... entities) {
model.modify(entities);
}
public E get(E entity) {
return model.get(entity);
}
public void remove(E... entities) {
model.remove(entities);
}
public void health(int id, int hp) {
model.health(id, hp);
}
}