001/* 002 * Grid.java 003 */ 004package minesweeper; 005 006import java.awt.*; 007//import java.awt.event.*; 008import javax.swing.*; 009 010import org.apache.logging.log4j.*; 011 012/** 013 * DESCRIBE {@link Grid} HERE. 014 * 015 * @author 2017-2018 APCS 016 * @author ADD @author TAG FOR EVERYONE WHO CONTRIBUTED TO THIS FILE 017 * @author <a href="https://github.com/wps-dpetty">David C. Petty</a> 018 */ 019public class Grid extends JPanel { 020 021 //////////////////////////////// FIELDS //////////////////////////////// 022 023 /** 024 * log4j {@link Logger}. 025 */ 026 private static Logger logger = LogManager.getLogger(Minesweeper.SHORT); 027 /** 028 * Constant minimum size of square buttons. 029 */ 030 public static final int MINIMUM_SIDE = 20; 031 /** 032 * Default number of rows in grid. 033 */ 034 public static final int DEFAULT_ROWS = 16; 035 /** 036 * Default number of columns in grid. 037 */ 038 public static final int DEFAULT_COLS = 30; 039 040 /** 041 * Actual number of rows in grid. 042 */ 043 private int rows; 044 /** 045 * Actual number of columns in grid. 046 */ 047 private int cols; 048 /** 049 * Actual size of square buttons. 050 */ 051 private int side; 052 053 ///////////////////////////// CONSTRUCTORS ///////////////////////////// 054 055 /** 056 * Create {@link Grid} of square {@link Button}s. 057 * 058 * @param rows number of rows in grid 059 * @param cols number of columns in grid 060 * @param side minimum size of square buttons 061 */ 062 public Grid(int rows, int cols, int side) { 063 super(new GridLayout(rows, cols, 0, 0)); 064 this.rows = rows; 065 this.cols = cols; 066 this.side = side; 067 for (int row = 0; row < rows; row++) 068 for (int col = 0; col < cols; col++) 069 add(new Button(row, col, side)); 070 //final int width = side * rows; // no need to set preferred size 071 //final int height = side * cols; // no need to set preferred size 072 setBackground(Color.BLACK); 073 setVisible(true); 074 logger.info(this); 075 } 076 077 /** 078 * Create {@link Grid} of square {@link Button}s with {@link #MINIMUM_SIDE} 079 * size of square buttons. 080 * 081 * @param rows number of rows in grid 082 * @param cols number of columns in grid 083 */ 084 public Grid(int rows, int cols) { 085 this(rows, cols, MINIMUM_SIDE); 086 } 087 088 /** 089 * Create {@link Grid} of square {@link Button}s with {@link #DEFAULT_ROWS} 090 * number of rows, {@link #DEFAULT_COLS} number of columns, and 091 * {@link #MINIMUM_SIDE} size of square buttons. 092 */ 093 public Grid() { 094 this(DEFAULT_ROWS, DEFAULT_COLS); 095 } 096 097 //////////////////////////////// METHODS /////////////////////////////// 098 099 /** 100 * Return number of rows in {@link Grid}. 101 * 102 * @return number of rows 103 */ 104 public int getRows() { 105 return rows; 106 } 107 108 /** 109 * Return number of columns in {@link Grid}. 110 * 111 * @return number of columns 112 */ 113 public int getCols() { 114 return cols; 115 } 116 117 /** 118 * Return side of square {@link Button}s in {@link Grid}. 119 * 120 * @return side of square {@link Button}s 121 */ 122 public int getSide() { 123 return side; 124 } 125 126 /** 127 * Return {@link Button} at column row <code>row</code> and <code>col</code>. 128 * 129 * @param row row of {@link Button} to find 130 * @param col column of {@link Button} to find 131 * @return {@link Button} at row <code>row</code> and column <code>col</code>, 132 * or null if no button matches "<code>row</code>,<code>col</code>" 133 */ 134 public Button findButton(int row, int col) { 135 Component[] components = getComponents(); 136 for (Component component : components) 137 if (component instanceof AbstractButton) { 138 String ac = ((Button) component).getActionCommand(); 139 Point point = Button.parseActionCommand(ac); 140 // Note: actionCommand is "row,col", but parsed point is (x,y). 141 if (row == point.x && col == point.y) 142 return (Button) component; 143 } 144 return null; 145 } 146 147 /** 148 * Paint the component using a {@link Graphics} rendering object. 149 * 150 * @param g the Graphics rendering object 151 */ 152 @Override 153 public void paintComponent(Graphics g) { 154 super.paintComponent(g); 155 } 156 157 /** 158 * Resizes this component so that it has width <code>width</code> and 159 * height <code>height</code>. This method changes layout-related 160 * information, and therefore, invalidates the component hierarchy. 161 * 162 * @param width new width of this component in pixels 163 * @param height new height of this component in pixels 164 */ 165 @Override 166 public void setSize(int width, int height) { 167 logger.info("{}.setSize: (from) {} (to) {}", 168 getClass().getName(), getSize(), new Dimension(width, height)); 169 logger.info("({},{}) ({},{}) {} == {}?", 170 width, height, rows, cols, width * rows, height * cols); 171 assert width * rows == height * cols : "bad aspect ratio"; 172 int side = Math.max(width / cols, MINIMUM_SIDE);// side = height / rows; 173 Component[] components = getComponents(); 174 for (Component component : components) 175 if (component instanceof AbstractButton) 176 component.setSize(side, side); 177 validate(); 178 repaint(); 179 } 180 181 /** 182 * Resizes this component so that it has width <code>size.width</code> and 183 * height <code>size.height</code>. This method changes layout-related 184 * information, and therefore, invalidates the component hierarchy. 185 * 186 * @param size dimension specifying the new size of this component 187 */ 188 @Override 189 public void setSize(Dimension size) { 190 // TODO: setSize(Dimension) calls setSize(int, int) else infinite recursion 191 setSize(size.width, size.height); 192 } 193 194/* 195 @Override 196 public Dimension getSize() { 197 return size; 198 } 199 200 @Override 201 public Dimension getPreferredSize() { 202 return preferredSize; 203 } 204 205 @Override 206 public Dimension getPreferredSize() { 207 return ((JFrame) SwingUtilities.getWindowAncestor(this)).getPreferredSize(); 208 } 209*/ 210 211 /** 212 * Return {@link String} representation of <code>this</code>. 213 * 214 * @return {@link String} representation of <code>this</code> 215 */ 216 @Override 217 public String toString() { 218 return new StringBuilder() 219 .append(getClass().getName()).append(":") 220 .append(getSize()).append(":").append("[") 221 .append(rows).append(",").append(cols).append(",") 222 .append(side).append("]") 223 .toString(); 224 } 225}