// ArrayCanvas.java import java.awt.*; public class ArrayCanvas extends Canvas { public static final int M = 0, S = 1; private static final double sqrt2 = Math.sqrt(2); private int[][] A; private int cellsInRow, cellSize, type, offset = 25; private Font plainFont = new Font("Monospaced", Font.PLAIN, 12), italicsFont = new Font("Monospaced", Font.ITALIC, 14), smallItalicsFont = new Font("Monospaced", Font.ITALIC, 12); private Image offscreenImage; private ScrollPane arrayPane; private String alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public ArrayCanvas(int _type) { type = _type; } public void setData(int[][] _A, ScrollPane _arrayPane) { A = _A; cellsInRow = A[0].length - 2 - type; arrayPane = _arrayPane; setSize(getPreferredSize()); arrayPane.doLayout(); arrayPane.setScrollPosition(0, 0); repaint(); } public void clear() { A = null; setSize(getPreferredSize()); if (arrayPane != null) { arrayPane.doLayout(); repaint(); } } public Dimension getPreferredSize() { if (A == null) return new Dimension(0, 0); else { cellSize = findMaxSpacing(); int paneWidth = cellsInRow * (int)(cellSize * sqrt2) + 2 * offset, arrayWidth = arrayPane.getSize().width, arrayHeight = arrayPane.getSize().height, paneHeight; if (type == M) paneHeight = (cellsInRow + 1) * (int)(cellSize / sqrt2) + 2 * offset; else paneHeight = cellsInRow * (int)(cellSize / sqrt2) + 2 * offset; return new Dimension(paneWidth, paneHeight); } } private int calculateRowCenter() { return this.getSize().width / 2; } private int findMaxSpacing() { int maxOfValues, maxOfIndices, whiteSpace = 0; maxOfValues = maxOfIndices = Integer.MAX_VALUE * -1; for(int r = 1; r <= cellsInRow; r++) { int indexSpacing = getFontMetrics(plainFont).stringWidth(Integer.toString(r)); for(int c = 1; c <= cellsInRow; c++) { int valueSpacing = getFontMetrics(plainFont).stringWidth(Integer.toString(A[r][c])); if (valueSpacing > maxOfValues) maxOfValues = valueSpacing; if (indexSpacing > maxOfIndices) maxOfIndices = indexSpacing; } } if (maxOfValues > maxOfIndices) return maxOfValues + 8; else return maxOfIndices + 14; } private int avgLabelPos() { return (int)(cellSize * cellsInRow / sqrt2) / 2; } public void update(Graphics g) { int width = this.getSize().width, height = this.getSize().height; if ((offscreenImage == null) || ((offscreenImage.getWidth(this) != width) || (offscreenImage.getHeight(this) != height))) offscreenImage = this.createImage(width, height); Graphics gr = offscreenImage.getGraphics(); paint(gr); g.drawImage(offscreenImage, 0, 0, this); } public void paint(Graphics g) { int width = this.getSize().width, height = this.getSize().height; g.clearRect(0, 0, width, height); if (A != null) { int middle, absoluteMiddle; middle = calculateRowCenter(); absoluteMiddle = middle; g.setFont(italicsFont); String title; if (type == M) title = "m"; else title = "s"; g.drawString(title, middle - getFontMetrics(italicsFont).stringWidth(title) / 2, offset - 10); g.setFont(smallItalicsFont); int alp = avgLabelPos(), offsetFor1; if ((type == S) && (cellsInRow == 1)) offsetFor1 = 15; else offsetFor1 = 0; g.drawString("j", absoluteMiddle - alp - cellSize, offset + alp - cellSize + offsetFor1); g.drawString("i", absoluteMiddle + alp + cellSize - g.getFontMetrics(smallItalicsFont).stringWidth("i"), offset + alp - cellSize + offsetFor1); g.setFont(plainFont); int c = A[0].length - 2; for(int i = 1; i <= cellsInRow; i++) { int yPos = offset + (i - 1) * (int)(cellSize / sqrt2), labelYPos = yPos + (int)(0.25 * cellSize * sqrt2), startingMiddle = middle, r = 1, cCur = c; c--; String iStr = Integer.toString(i), jStr; if (type == M) jStr = Integer.toString(cellsInRow - i + 1); else jStr = Integer.toString(cellsInRow - i + 2); g.drawString(iStr, (int)(absoluteMiddle + i * cellSize / sqrt2 - (0.125 * cellSize * sqrt2)), labelYPos); g.drawString(jStr, (int)(absoluteMiddle - i * cellSize / sqrt2 + (0.125 * cellSize * sqrt2)) - g.getFontMetrics(plainFont).stringWidth(jStr), labelYPos); int[] xPoints = new int[4], yPoints = new int[4]; for(int j = 1; j <= i; j++) { xPoints[0] = middle; yPoints[0] = yPos; xPoints[1] = middle - (int)(cellSize / sqrt2); yPoints[1] = yPos + (int)(cellSize / sqrt2); xPoints[2] = middle; yPoints[2] = yPos + 2 * (int)(cellSize / sqrt2); xPoints[3] = middle + (int)(cellSize / sqrt2); yPoints[3] = yPos + (int)(cellSize / sqrt2); if (type == M) g.setColor(new Color(150, 190, 170)); else g.setColor(new Color(77, 222, 234)); g.fillPolygon(xPoints, yPoints, 4); g.setColor(Color.black); g.drawPolygon(xPoints, yPoints, 4); String str = Integer.toString(A[r][cCur]); g.drawString(str, middle - getFontMetrics(plainFont).stringWidth(str) / 2, yPoints[1] + getFontMetrics(plainFont).getHeight() / 3); if (type == M) { if (i == cellsInRow) { g.setFont(italicsFont); String s = alpha.charAt(j - 1) + ""; g.drawString(s, middle - getFontMetrics(italicsFont).stringWidth(s) / 2, yPoints[2] + 20); } } g.setFont(plainFont); middle = middle + 2 * (int)(cellSize / sqrt2); cCur++; r++; } middle = startingMiddle - (int)(cellSize / sqrt2); } } } }