// GameTreeNode.java package net.sf.gogui.gui; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseListener; import java.awt.font.LineMetrics; import javax.swing.JComponent; import net.sf.gogui.game.ConstNode; import net.sf.gogui.game.NodeUtil; import net.sf.gogui.go.GoColor; import static net.sf.gogui.go.GoColor.BLACK; import static net.sf.gogui.go.GoColor.BLACK_WHITE_EMPTY; import net.sf.gogui.go.Move; import static net.sf.gogui.gui.I18n.i18n; class GameTreeNode extends JComponent { public GameTreeNode(ConstNode node, int moveNumber, GameTreePanel gameTreePanel, MouseListener mouseListener, Font font, Image imageBlack, Image imageWhite, Image imageSetup, Dimension size) { m_gameTreePanel = gameTreePanel; m_node = node; m_moveNumber = moveNumber; addMouseListener(mouseListener); setOpaque(false); setFocusable(false); setFocusTraversalKeysEnabled(false); if (font != null) setFont(font); m_imageBlack = imageBlack; m_imageWhite = imageWhite; m_imageSetup = imageSetup; updateToolTip(); setPreferredSize(size); } public ConstNode getNode() { return m_node; } public void paintComponent(Graphics graphics) { int size = m_gameTreePanel.getNodeSize(); int fullSize = m_gameTreePanel.getNodeFullSize(); int halfSize = size / 2; int numberChildren = m_node.getNumberChildren(); boolean isExpanded = m_gameTreePanel.isExpanded(m_node); if (m_gameTreePanel.isCurrent(m_node)) { graphics.setColor(COLOR_CURSOR); graphics.fillRect(0, 0, size, size > 10 ? size : fullSize - 1); } graphics.setColor(COLOR_GRID); if (numberChildren > 0) graphics.drawLine(size, halfSize, fullSize, halfSize); if (numberChildren > 1 && isExpanded) graphics.drawLine(halfSize, size, halfSize, fullSize); Move move = m_node.getMove(); if (m_node.hasSetup()) graphics.drawImage(m_imageSetup, 0, 0, null); else if (move == null) { graphics.setColor(COLOR_GRID); int[] xPoints = { halfSize, size, halfSize, 0 }; int[] yPoints = { 0, halfSize, size, halfSize }; graphics.fillPolygon(xPoints, yPoints, 4); } else { if (move.getColor() == BLACK) graphics.drawImage(m_imageBlack, 0, 0, null); else graphics.drawImage(m_imageWhite, 0, 0, null); drawText(graphics); } if (m_node.hasComment()) { graphics.setColor(COLOR_LIGHT_BLUE); int y = size + (fullSize - size) / 4; int d = size / 5; graphics.drawLine(d, y, size - d, y); } } public final void updateToolTip() { StringBuilder toolTip = new StringBuilder(128); Move move = m_node.getMove(); GoColor player = m_node.getPlayer(); if (move != null) { toolTip.append(m_moveNumber); toolTip.append(' '); toolTip.append(move); } else if (m_node.hasSetup() || player != null) { toolTip.append(i18n("TT_NODE_SETUP")); toolTip.append(" ("); boolean anyStones = false; for (GoColor c : BLACK_WHITE_EMPTY) { int n = m_node.getSetup(c).size(); if (n == 0) continue; if (anyStones) toolTip.append(", "); anyStones = true; toolTip.append(c.getUppercaseLetter()); toolTip.append(' '); toolTip.append(n); } if (player != null) { if (anyStones) toolTip.append(", "); toolTip.append(i18n("TT_NODE_PLAYER")); toolTip.append(' '); toolTip.append(player.getUppercaseLetter()); } toolTip.append(')'); } String comment = NodeUtil.getCommentStart(m_node, false, 80); if (comment != null) { comment = comment.replaceAll("\n *\n", "\n"); comment = comment.replaceAll("\n", "<br>"); if (comment.length() > 50) { toolTip.append("<p width=\"250\">"); toolTip.append(comment); toolTip.append("</p>"); } else { toolTip.append("<p>"); toolTip.append(comment); toolTip.append("</p>"); } } if (toolTip.length() > 0) setToolTipText("<html>" + toolTip.toString() + "</html>"); } private final int m_moveNumber; private static final Color COLOR_LIGHT_BLUE = new Color(103, 122, 164); private static final Color COLOR_CURSOR = new Color(142, 168, 226); private static final Color COLOR_GRID = new Color(148, 148, 148); private final GameTreePanel m_gameTreePanel; private final ConstNode m_node; private final Image m_imageBlack; private final Image m_imageWhite; private final Image m_imageSetup; private void drawText(Graphics graphics) { GameTreePanel.Label labelMode = m_gameTreePanel.getLabelMode(); if (labelMode == GameTreePanel.Label.NONE) return; Move move = m_node.getMove(); int size = m_gameTreePanel.getNodeSize(); String text; if (labelMode == GameTreePanel.Label.MOVE) { if (move.getPoint() == null) return; text = move.getPoint().toString(); } else text = Integer.toString(m_moveNumber); FontMetrics fontMetrics = graphics.getFontMetrics(); LineMetrics lineMetrics = fontMetrics.getLineMetrics(text, graphics); int textWidth = fontMetrics.stringWidth(text); int ascent = (int)lineMetrics.getAscent(); int xText = (size - textWidth) / 2; int yText = (ascent + size) / 2; if (move.getColor() == BLACK) graphics.setColor(Color.white); else graphics.setColor(Color.black); graphics.drawString(text, xText, yText); } }