package featurecat.lizzie.gui; import static java.lang.Math.max; import static java.lang.Math.min; import featurecat.lizzie.Lizzie; import featurecat.lizzie.rules.Board; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; public class LizzieLayout extends BorderLayout implements LayoutManager2, java.io.Serializable { int hgap; int vgap; private Component north; private Component west; private Component east; private Component south; private Component mainBoard; private Component subBoard; private Component winratePane; private Component variationPane; private Component basicInfoPane; private Component commentPane; private Component consolePane; public static final String NORTH = "North"; public static final String SOUTH = "South"; public static final String EAST = "East"; public static final String WEST = "West"; public static final String MAIN_BOARD = "mainBoard"; public static final String SUB_BOARD = "subBoard"; public static final String WINRATE = "winratePane"; public static final String VARIATION = "variationPane"; public static final String BASIC_INFO = "basicInfoPane"; public static final String COMMENT = "commentPane"; public static final String CONSOLE = "consolePane"; public static final int MODE_FUSION = 0; public static final int MODE_SEPARATION = 1; private int mode = 0; public int ponderingX; public int ponderingY; public LizzieLayout() { this(3, 0); } public LizzieLayout(int hgap, int vgap) { this.hgap = hgap; this.vgap = vgap; } public int getHgap() { return hgap; } public void setHgap(int hgap) { this.hgap = hgap; } public int getVgap() { return vgap; } public void setVgap(int vgap) { this.vgap = vgap; } public void addLayoutComponent(Component comp, Object constraints) { synchronized (comp.getTreeLock()) { if ((constraints == null) || (constraints instanceof String)) { addLayoutComponent((String) constraints, comp); } else { throw new IllegalArgumentException( "cannot add to layout: constraint must be a string (or null)"); } } } /** @deprecated replaced by <code>addLayoutComponent(Component, Object)</code>. */ @Deprecated public void addLayoutComponent(String name, Component comp) { synchronized (comp.getTreeLock()) { if (name == null) { name = MAIN_BOARD; } if (NORTH.equals(name)) { north = comp; } else if (SOUTH.equals(name)) { south = comp; } else if (EAST.equals(name)) { east = comp; } else if (WEST.equals(name)) { west = comp; } else if (BASIC_INFO.equals(name)) { basicInfoPane = comp; } else if (MAIN_BOARD.equals(name)) { mainBoard = comp; } else if (VARIATION.equals(name)) { variationPane = comp; } else if (WINRATE.equals(name)) { winratePane = comp; } else if (SUB_BOARD.equals(name)) { subBoard = comp; } else if (COMMENT.equals(name)) { commentPane = comp; } else if (CONSOLE.equals(name)) { consolePane = comp; } else { throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name); } } } public void removeLayoutComponent(Component comp) { synchronized (comp.getTreeLock()) { if (comp == north) { north = null; } else if (comp == south) { south = null; } else if (comp == east) { east = null; } else if (comp == west) { west = null; } else if (comp == basicInfoPane) { basicInfoPane = null; } else if (comp == mainBoard) { mainBoard = null; } else if (comp == variationPane) { variationPane = null; } else if (comp == winratePane) { winratePane = null; } else if (comp == subBoard) { subBoard = null; } if (comp == commentPane) { commentPane = null; } else if (comp == consolePane) { consolePane = null; } } } public Component getLayoutComponent(Object constraints) { if (NORTH.equals(constraints)) { return north; } else if (SOUTH.equals(constraints)) { return south; } else if (WEST.equals(constraints)) { return west; } else if (EAST.equals(constraints)) { return east; } else if (BASIC_INFO.equals(constraints)) { return basicInfoPane; } else if (MAIN_BOARD.equals(constraints)) { return mainBoard; } else if (SUB_BOARD.equals(constraints)) { return subBoard; } else if (VARIATION.equals(constraints)) { return variationPane; } else if (WINRATE.equals(constraints)) { return winratePane; } else if (COMMENT.equals(constraints)) { return commentPane; } else if (CONSOLE.equals(constraints)) { return consolePane; } else { throw new IllegalArgumentException( "cannot get component: unknown constraint: " + constraints); } } public Component getLayoutComponent(Container target, Object constraints) { boolean ltr = target.getComponentOrientation().isLeftToRight(); Component result = null; if (NORTH.equals(constraints)) { return north; } else if (SOUTH.equals(constraints)) { return south; } else if (WEST.equals(constraints)) { return west; } else if (EAST.equals(constraints)) { return east; } else if (MAIN_BOARD.equals(constraints)) { result = mainBoard; } else if (SUB_BOARD.equals(constraints)) { result = subBoard; } else if (COMMENT.equals(constraints)) { result = commentPane; } else if (VARIATION.equals(constraints)) { result = variationPane; } else if (WINRATE.equals(constraints)) { result = winratePane; } else if (BASIC_INFO.equals(constraints)) { result = basicInfoPane; } else { throw new IllegalArgumentException( "cannot get component: invalid constraint: " + constraints); } return result; } public Object getConstraints(Component comp) { if (comp == null) { return null; } if (comp == north) { return NORTH; } else if (comp == south) { return SOUTH; } else if (comp == west) { return WEST; } else if (comp == east) { return EAST; } else if (comp == basicInfoPane) { return BASIC_INFO; } else if (comp == mainBoard) { return MAIN_BOARD; } else if (comp == subBoard) { return SUB_BOARD; } else if (comp == variationPane) { return VARIATION; } else if (comp == winratePane) { return WINRATE; } else if (comp == commentPane) { return COMMENT; } else if (comp == consolePane) { return CONSOLE; } return null; } public Dimension minimumLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(WINRATE, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(VARIATION, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(BASIC_INFO, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(MAIN_BOARD, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } if ((c = getChild(SUB_BOARD, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension preferredLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(WINRATE, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(VARIATION, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(BASIC_INFO, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if ((c = getChild(MAIN_BOARD, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } if ((c = getChild(SUB_BOARD, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public float getLayoutAlignmentX(Container parent) { return 0.5f; } public float getLayoutAlignmentY(Container parent) { return 0.5f; } public void invalidateLayout(Container target) {} public void layoutContainer(Container target) { if (mode != MODE_FUSION) { return; } synchronized (target.getTreeLock()) { Container main = getMain(target); Insets insets = target.getInsets(); int x = 0; // target.getX(); int y = 0; // target.getY(); int width = target.getWidth(); int height = target.getHeight(); // layout parameters int top = insets.top; int bottom = height - insets.bottom; int left = insets.left; int right = width - insets.right; boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(NORTH, ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, top, right - left, d.height); top += d.height + vgap; } if ((c = getChild(SOUTH, ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, bottom - d.height, right - left, d.height); bottom -= d.height + vgap; } if ((c = getChild(EAST, ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(right - d.width, top, d.width, bottom - top); right -= d.width + hgap; } if ((c = getChild(WEST, ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(left, top, d.width, bottom - top); left += d.width + hgap; } x = left; y = top; width = right - left; height = bottom - top; int maxBound = Math.max(width, height); boolean noWinrate = (getChild(WINRATE, ltr) == null || !Lizzie.config.showWinrate); boolean noVariation = (getChild(VARIATION, ltr) == null || !Lizzie.config.showVariationGraph); boolean noBasic = (getChild(BASIC_INFO, ltr) == null || !Lizzie.config.showCaptured); boolean noSubBoard = (getChild(SUB_BOARD, ltr) == null || !Lizzie.config.showSubBoard); boolean noComment = (getChild(COMMENT, ltr) == null || !Lizzie.config.showComment); // boolean onlyMainBoard = noWinrate && noVariation && noBasic && noSubBoard && // noComment; // board int maxSize0 = (int) (min(width, height)); int maxw = maxSize0; // Board.boardWidth > Board.boardHeight ? (width) * 3 / // 4 : maxSize0; int maxh = maxSize0; if (noBasic && noWinrate && noSubBoard) { maxw = width; } else if (noVariation && noComment) { maxw = (width) * 3 / 4; } int[] mainBoardParam = BoardRenderer.availableLength( max(maxw, Board.boardWidth + 5), max(maxh, Board.boardHeight + 5), Lizzie.config.showCoordinates, true); // don't let maxWidth become too small int boardX = x + (width - mainBoardParam[0]) / 8 * ((main == null || !(main instanceof LizzieMain)) ? Lizzie.config.boardPositionProportion : ((LizzieMain) main).boardPositionProportion); if (noBasic && noWinrate && noSubBoard) { boardX = x; } else if (noVariation && noComment) { boardX = x + (width - mainBoardParam[0]); } int boardY = y + (height - mainBoardParam[3]) / 2; int panelMargin = (int) (mainBoardParam[0] * 0.02); // captured stones int capx = x; int capy = y; int capw = boardX - panelMargin - x; int caph = maxSize0 / 8; // move statistics (winrate bar) // boardX equals width of space on each side int statx = capx; int staty = capy + caph; int statw = capw; int stath = maxSize0 / 10; // winrate graph int grx = statx; int gry = staty + stath; int grw = statw; int grh = maxSize0 / 3; // variation tree container int vx = boardX + mainBoardParam[0] + panelMargin; int vy = capy; int vw = right - vx; int vh = bottom - vy; // pondering message double ponderingSize = .02; ponderingX = x; ponderingY = bottom - 2 - (int) (maxBound * ponderingSize); // subboard int subBoardY = gry + grh + 1; int subBoardWidth = grw; int subBoardHeight = ponderingY - subBoardY; int[] subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); int subBoardX = statx + (statw - subBoardParam[0]) / 2; if (width >= height) { // Landscape mode if (Lizzie.config.showLargeSubBoard() && !noSubBoard) { boardX = x + width - mainBoardParam[0] - panelMargin; int spaceW = boardX - panelMargin - x; int spaceH = height; int panelW = spaceW / 2; int panelH = spaceH / 4; // captured stones capw = (noVariation && noComment) ? spaceW : panelW; caph = (int) (panelH * 0.2); // move statistics (winrate bar) staty = capy + caph; statw = capw; stath = (int) (panelH * 0.4); // winrate graph gry = staty + stath; grw = statw; grh = panelH - caph - stath; // variation tree container vx = statx + statw; vw = panelW; vh = panelH; // subboard subBoardY = gry + grh; subBoardWidth = spaceW; subBoardHeight = ponderingY - subBoardY; subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); subBoardX = statx + (spaceW - subBoardParam[0]) / 2; } else if (Lizzie.config.showLargeWinrate() && !noWinrate) { boardX = x + width - mainBoardParam[0] - panelMargin; int spaceW = boardX - panelMargin - x; int spaceH = height; int panelW = spaceW / 2; int panelH = spaceH / 4; // captured stones capy = y + panelH + 1; capw = spaceW; caph = (int) ((ponderingY - y - panelH) * 0.15); // move statistics (winrate bar) staty = capy + caph; statw = capw; stath = caph; // winrate graph gry = staty + stath; grw = statw; grh = ponderingY - gry; // variation tree container vx = x + panelW; vw = panelW; vh = panelH; // subboard subBoardY = y; subBoardWidth = panelW - x; subBoardHeight = panelH; subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); subBoardX = statx + (vw - subBoardParam[0]) / 2; } } else { // Portrait mode if (Lizzie.config.showLargeSubBoard() && !noSubBoard) { // board mainBoardParam = BoardRenderer.availableLength( (int) (maxSize0 * 0.8), (int) (maxSize0 * 0.8), Lizzie.config.showCoordinates, true); boardY = height - mainBoardParam[3]; int spaceW = width; int spaceH = boardY - panelMargin - y; int panelW = spaceW / 2; int panelH = spaceH / 2; boardX = x + (spaceW - mainBoardParam[0]) / 2 + x; // captured stones capw = panelW / 2; caph = panelH / 2; // move statistics (winrate bar) staty = capy + caph; statw = capw; stath = caph; // winrate graph gry = staty + stath; grw = statw; grh = spaceH - caph - stath; // variation tree container vx = capx + capw; vw = panelW / 2; vh = spaceH; // subboard subBoardX = vx + vw; subBoardWidth = panelW; subBoardHeight = boardY - y; subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); subBoardY = capy + (gry + grh - capy - subBoardParam[0]) / 2; // pondering message ponderingY = height; } else if (Lizzie.config.showLargeWinrate() && !noWinrate) { // board mainBoardParam = BoardRenderer.availableLength( (int) (maxSize0 * 0.8), (int) (maxSize0 * 0.8), Lizzie.config.showCoordinates, true); boardY = height - mainBoardParam[3]; int spaceW = width; int spaceH = boardY - panelMargin - y; int panelW = spaceW / 2; int panelH = spaceH / 2; boardX = (spaceW - mainBoardParam[0]) / 2 + x; // captured stones capw = panelW / 2; caph = panelH / 4; // move statistics (winrate bar) statx = capx; staty = capy + caph; statw = spaceW; stath = boardY - caph - 1; // winrate graph gry = staty + stath; grw = spaceW; grh = boardY - gry - 1; // variation tree container vx = capx + capw; vy = capy; vw = panelW; vh = caph; // subboard subBoardY = capy; subBoardWidth = panelW / 2; subBoardHeight = caph; subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); subBoardX = vx + vw; // pondering message ponderingY = height; } else { // Normal // board boardY = (height - mainBoardParam[3] + y) / 2; int spaceW = width; int spaceH = boardY - panelMargin - y; int panelW = spaceW / 2; int panelH = spaceH / 2; // captured stones capw = panelW * 3 / 4; caph = panelH / 2; // move statistics (winrate bar) statx = capx + capw; staty = capy; statw = width - capx - capw; stath = caph; // winrate graph grx = statx; gry = staty + stath; grw = statw; grh = boardY - gry; // subboard subBoardWidth = capw; subBoardHeight = boardY - caph - capy; subBoardParam = BoardRenderer.availableLength(subBoardWidth, subBoardHeight, false, false); subBoardX = capx + (capw - subBoardParam[0]) / 2; subBoardY = capy + caph + (boardY - capy - caph - subBoardParam[3]) / 2; // variation tree container vx = capx; vy = boardY + mainBoardParam[3]; vw = spaceW; vh = ponderingY - vy; } } // variation tree int treex = vx; int treey = vy; int treew = vw; int treeh = vh; // comment panel int cx = vx, cy = vy, cw = vw, ch = vh; if (Lizzie.config.showComment) { if (width >= height) { if (Lizzie.config.showVariationGraph) { treeh = vh / 2; cy = vy + treeh; ch = treeh; } } else { if (Lizzie.config.showVariationGraph) { if (Lizzie.config.showLargeSubBoard()) { treeh = vh / 2; cy = vy + treeh; ch = treeh; } else { treew = vw / 2; cx = vx + treew; cw = treew; } } } } if ((c = getChild(MAIN_BOARD, ltr)) != null) { c.setBounds(boardX, boardY, mainBoardParam[0], mainBoardParam[3]); if (c instanceof LizziePane) { ((LizziePane) c).boardParams = mainBoardParam; } // c.repaint(); } if ((c = getChild(SUB_BOARD, ltr)) != null) { c.setBounds(subBoardX, subBoardY, subBoardParam[0], subBoardParam[3]); if (c instanceof LizziePane) { ((LizziePane) c).boardParams = subBoardParam; } // c.repaint(); } if ((c = getChild(BASIC_INFO, ltr)) != null) { c.setBounds(capx, capy, capw, caph); } if ((c = getChild(WINRATE, ltr)) != null) { c.setBounds(statx, staty, statw, stath + grh); } if ((c = getChild(VARIATION, ltr)) != null) { c.setBounds(treex, treey, treew, treeh); } if ((c = getChild(COMMENT, ltr)) != null) { // ((CommentPane)c).setCommentBounds(cx, cy, cw, ch); c.setBounds(cx, cy, cw, ch); c.repaint(); } } } private Component getChild(String key, boolean ltr) { Component result = null; if (key == NORTH) { result = north != null && north.isVisible() ? north : null; } else if (key == SOUTH) { result = south != null && south.isVisible() ? south : null; } else if (key == WEST) { result = west != null && west.isVisible() ? west : null; } else if (key == EAST) { result = east != null && east.isVisible() ? east : null; } else if (key == MAIN_BOARD) { result = mainBoard; } else if (key == SUB_BOARD) { result = subBoard; } else if (key == VARIATION) { result = variationPane; } else if (key == WINRATE) { result = winratePane; } else if (key == COMMENT) { result = commentPane; } else if (key == BASIC_INFO) { result = basicInfoPane; } return result; } public String toString() { return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; } private Container getMain(Container target) { Container p = (target != null) ? target.getParent() : null; while (p != null && !(p instanceof LizzieMain)) { p = p.getParent(); } return p; } public int getMode() { return mode; } public void setMode(int mode) { this.mode = mode; } }