package algorithm.bsf.maze.frame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.SystemColor;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import javax.swing.JPanel;
import algorithm.bsf.maze.Map;
import algorithm.bsf.maze.Node;
/**
* @author Fan Hongtao
* @created 2009-3-16
*/
@SuppressWarnings("serial")
public class MapPanel extends JPanel
{
private Map map;
private Color[][] colors;
private HashMap<String, Pair<Node>> lineMap = new HashMap<String, Pair<Node>>();
public MapPanel(Map map)
{
super();
setLayout(null);
this.map = map;
setSize(map.getWidth() + 20, map.getHeight() + 20);
colors = new Color[map.getXSize()][map.getYSize()];
for (int i = 0; i < map.getXSize(); i++)
{
for (int j = 0; j < map.getYSize(); j++)
{
if (map.getMap()[i][j] != 0)
{
colors[i][j] = SystemColor.BLACK;
}
else
{
colors[i][j] = SystemColor.WHITE;
}
}
}
Node start = map.getStart();
Node stop = map.getStop();
colors[start.getX()][start.getY()] = Color.YELLOW;
colors[stop.getX()][stop.getY()] = Color.RED;
}
public void chageColor(int x, int y, Color color)
{
colors[x][y] = color;
repaint();
}
/**
* 增加from到to结点之间的连线,通常在搜索时使用
* @param from
* @param to
*/
public void addLine(Node from, Node to)
{
lineMap.put(getLineKey(from, to), new Pair<Node>(from, to));
}
private String getLineKey(Node from, Node to)
{
return String.format("%1d_%2d_%3d_%4d", from.getX(), from.getY(), to.getX(), to.getY());
}
/**
* 删除from到to结点之间的连线,通常在回退时使用
* @param from
* @param to
*/
public void deleteLine(Node from, Node to)
{
lineMap.remove(getLineKey(to, from));
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int length = map.getWidth();
int height = map.getHeight();
// 画网络
for (int i = 0; i <= length; i += Map.BOX_WIDTH)
{
g.drawLine(i, 0, i, height);
}
for (int j = 0; j <= height; j += Map.BOX_HEIGHT)
{
g.drawLine(0, j, length, j);
}
Node stop = map.getStop();
colors[stop.getX()][stop.getY()] = Color.RED;
// 填充网格
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < map.getXSize(); i++)
{
for (int j = 0; j < map.getYSize(); j++)
{
fillBox(g2, i, j, colors[i][j]);
}
}
// 绘制箭头
for (Pair<Node> pair : lineMap.values())
{
drawLine(g2, pair.getFirst(), pair.getSecond(), Color.BLACK);
}
}
private void fillBox(Graphics2D g2, int x, int y, Color color)
{
g2.setColor(color);
Rectangle2D rect = new Rectangle2D.Double(x * 20 + 2, y * 20 + 2, 16, 16);
g2.fill(rect);
}
private void drawLine(Graphics2D g2, Node from, Node to, Color color)
{
if (from.getX() == to.getX())
{
if (from.getY() < to.getY())
{
drawLineToDown(g2, from, to, color);
}
else
{
drawLineToUp(g2, from, to, color);
}
}
else
{
if (from.getX() < to.getX())
{
drawLineToRight(g2, from, to, color);
}
else
{
drawLineToLeft(g2, from, to, color);
}
}
}
private void drawLineToRight(Graphics2D g2, Node from, Node to, Color color)
{
g2.setColor(color);
GeneralPath path = new GeneralPath();
int startX = from.getX() * 20 + 10;
int startY = from.getY() * 20;
path.moveTo(startX + 2, startY + 8);
path.lineTo(startX + 12, startY + 8);
path.lineTo(startX + 12, startY + 4);
path.lineTo(startX + 16, startY + 10);
path.lineTo(startX + 12, startY + 16);
path.lineTo(startX + 12, startY + 12);
path.lineTo(startX + 2, startY + 12);
path.closePath();
g2.fill(path);
}
private void drawLineToLeft(Graphics2D g2, Node from, Node to, Color color)
{
g2.setColor(color);
GeneralPath path = new GeneralPath();
int startX = from.getX() * 20 - 10;
int startY = from.getY() * 20;
path.moveTo(startX + 18, startY + 8);
path.lineTo(startX + 8, startY + 8);
path.lineTo(startX + 8, startY + 4);
path.lineTo(startX + 4, startY + 10);
path.lineTo(startX + 8, startY + 16);
path.lineTo(startX + 8, startY + 12);
path.lineTo(startX + 18, startY + 12);
path.closePath();
g2.fill(path);
}
private void drawLineToDown(Graphics2D g2, Node from, Node to, Color color)
{
g2.setColor(color);
GeneralPath path = new GeneralPath();
int startX = from.getX() * 20;
int startY = from.getY() * 20 + 10;
path.moveTo(startX + 8, startY + 2);
path.lineTo(startX + 8, startY + 12);
path.lineTo(startX + 4, startY + 12);
path.lineTo(startX + 10, startY + 16);
path.lineTo(startX + 16, startY + 12);
path.lineTo(startX + 12, startY + 12);
path.lineTo(startX + 12, startY + 2);
path.closePath();
g2.fill(path);
}
private void drawLineToUp(Graphics2D g2, Node from, Node to, Color color)
{
g2.setColor(color);
GeneralPath path = new GeneralPath();
int startX = from.getX() * 20;
int startY = from.getY() * 20 - 10;
path.moveTo(startX + 8, startY + 18);
path.lineTo(startX + 8, startY + 8);
path.lineTo(startX + 4, startY + 8);
path.lineTo(startX + 10, startY + 4);
path.lineTo(startX + 16, startY + 8);
path.lineTo(startX + 12, startY + 8);
path.lineTo(startX + 12, startY + 18);
path.closePath();
g2.fill(path);
}
}
class Pair<T>
{
private T first;
private T second;
public Pair(T first, T second)
{
super();
this.first = first;
this.second = second;
}
public T getFirst()
{
return first;
}
public T getSecond()
{
return second;
}
}