package org.limewire.ui.swing.properties; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.util.HashMap; import java.util.Map; import org.jdesktop.swingx.JXPanel; import org.jdesktop.swingx.painter.AbstractPainter; import org.jdesktop.swingx.painter.Painter; /** * Lightweight component for displaying a coloured grid. * * <p> At this moment specialised for displaying piece data, however could be extended. */ public class PiecesGrid extends JXPanel { private int rows = -1; private int columns = -1; private Paint[] gridFillPaint = null; private final Map<Integer,Paint> borderPaintMap = new HashMap<Integer,Paint>(); public PiecesGrid() { init(); } public PiecesGrid(int r, int c) { resizeGrid(r, c); init(); } private void init() { setBackgroundPainter(new GridPainter()); // Just for fun addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { if ((e.getModifiers() & MouseWheelEvent.CTRL_MASK) == 0) { return; } int newRows = rows; int newColumns = columns; if (e.getUnitsToScroll() < 0) { if (columns > 4) { newColumns = columns - 1; } if (rows > 4) { newRows = rows - 1; } } else if (e.getUnitsToScroll() > 0) { if (columns < 200) { newColumns = columns + 1; } if (rows < 200 ) { newRows = rows + 1; } } resizeGrid(newRows, newColumns); } }); } void resizeGrid(int rows, int columns) { this.rows = rows; this.columns = columns; gridFillPaint = new Paint[rows*columns]; } public void clear() { clearFillPaints(); clearBorderPaints(); } public void clearFillPaints() { gridFillPaint = new Paint[rows*columns]; } public void clearBorderPaints() { borderPaintMap.clear(); } boolean hasGrid() { return gridFillPaint != null; } public int getRows() { return rows; } public int getColumns() { return columns; } public int getCellCount() { return gridFillPaint.length; } public void setCellFillPaint(int cell, Paint paint) { gridFillPaint[cell] = paint; } public void setCellBorderPaint(int cell, Paint paint) { borderPaintMap.put(cell, paint); } public Paint getCellFillPaint(int cell) { return gridFillPaint[cell]; } public Paint getCellBorderPaint(int cell) { return borderPaintMap.get(cell); } @Override public void repaint() { Painter painter = getBackgroundPainter(); if (painter instanceof AbstractPainter) { ((AbstractPainter)painter).clearCache(); } super.repaint(); } /** * Hack to aid with alignment of components along the outer edge above * or below this component. No way to easily avoid. Only relevant with * centred x-alignment at this moment. */ public int getInnerMargin() { Painter painter = this.getBackgroundPainter(); if (painter instanceof GridPainter) { ((GridPainter)painter).marginUpdated = false; return ((GridPainter)painter).marginX; } return 0; } public boolean isMarginUpdated() { Painter painter = this.getBackgroundPainter(); if (painter instanceof GridPainter) { return ((GridPainter)painter).marginUpdated; } return false; } private static class GridPainter extends AbstractPainter<PiecesGrid> { /** * Variable used for hack to correct the margins of the components under the grid * despite loss of table width due to need for rounding. */ protected int marginX = 0; /** * Variable used for hack to correct the margins of the components under the grid * despite loss of table width due to need for rounding. */ protected boolean marginUpdated = false; GridPainter() { setCacheable(true); setAntialiasing(true); } @Override protected void doPaint(Graphics2D g, PiecesGrid grid, int width, int height) { if (!grid.hasGrid()) { g.setPaint(Color.BLACK); g.drawRect(0,0, width-1, height-1); return; } int columns = grid.getColumns(); int rows = grid.getRows(); int cellWidth = (width-2) / columns; int cellHeight = (height-2) / rows; int actualTableWidth = cellWidth*columns; int actualTableHeight = cellHeight*rows; int alignOffsetX = Math.round(grid.getAlignmentX() * (width-actualTableWidth)); int alignOffsetY = Math.round(grid.getAlignmentY() * (height-actualTableHeight)); if (marginX != alignOffsetX) { marginX = alignOffsetX; marginUpdated = true; } int cellRow = 0; for ( int i=0 ; i<grid.getCellCount() ; i++ ) { Paint cellPaint = grid.getCellFillPaint(i); int cellColumn = i % columns; if (i != 0 && i % columns == 0) { cellRow++; } g.setPaint(cellPaint); g.fillRect(cellColumn*cellWidth+1+alignOffsetX, cellRow*cellHeight+1+alignOffsetY, cellWidth, cellHeight); Paint borderPaint = grid.getCellBorderPaint(i); if (borderPaint != null) { g.setPaint(borderPaint); g.drawRect(cellColumn*cellWidth+1+alignOffsetX, cellRow*cellHeight+1+alignOffsetY, cellWidth-2, cellHeight-2); } g.setPaint(Color.BLACK); } g.setPaint(Color.BLACK); g.drawRect(0+alignOffsetX, 0+alignOffsetY, actualTableWidth, actualTableHeight); for ( int i=1 ; i<columns ; i++ ) { g.drawLine(i*cellWidth+alignOffsetX, 0+alignOffsetY, i*cellWidth+alignOffsetX, actualTableHeight+alignOffsetY); } for ( int i=1 ; i<rows ; i++ ) { g.drawLine(0+alignOffsetX, i*cellHeight+alignOffsetY , actualTableWidth+alignOffsetX, i*cellHeight+alignOffsetY); } } } }