//============================================================================= // Copyright 2006-2010 Daniel W. Dyer // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //============================================================================= package org.uncommons.watchmaker.examples.sudoku; import javax.swing.table.AbstractTableModel; /** * {@link javax.swing.table.TableModel} for displaying a Sudoku * grid in a {@link javax.swing.JTable}. * @author Daniel Dyer */ class SudokuTableModel extends AbstractTableModel { // In puzzle mode, the user can edit the given cells and all other // cells are blank. In solution mode, all cells have values and are // uneditable. private boolean puzzleMode = true; // Solution mode data. private Sudoku sudoku; // Puzzle mode data. private final Character[][] cells = new Character[Sudoku.SIZE][Sudoku.SIZE]; /** * Sets the Sudoku grid represented by this table model. */ public void setSudoku(Sudoku sudoku) { this.sudoku = sudoku; puzzleMode = false; fireTableRowsUpdated(0, getRowCount() - 1); } /** * @return The Sudoku grid represented by this table model. */ public Sudoku getSudoku() { return sudoku; } public int getRowCount() { return Sudoku.SIZE; } public int getColumnCount() { return Sudoku.SIZE; } public Object getValueAt(int row, int column) { if (puzzleMode) { return cells[row][column]; } else { return sudoku == null ? null : sudoku.getValue(row, column); } } @Override public boolean isCellEditable(int row, int column) { return puzzleMode; } @Override public void setValueAt(Object object, int row, int column) { Character value = (Character) object; if (!(value == null || (value >= '1' && value <= '9'))) { throw new IllegalArgumentException("Invalid character: " + value); } cells[row][column] = value; fireTableCellUpdated(row, column); } /** * Sets all cells at once using the same patterns as supported by * {@link SudokuFactory}. * @param pattern A String representation of a Sudoku puzzle. Each element * in the array represents a single row. There are 9 elements and each has 9 * characters, one per cell. Number cells are represented by the characters * '0' to '9' and blank cells are represented by dots. */ public void setPattern(String[] pattern) { if (pattern.length != Sudoku.SIZE) { throw new IllegalArgumentException("Pattern must have " + Sudoku.SIZE + " rows."); } for (int row = 0; row < pattern.length; row++) { String patternRow = pattern[row]; if (patternRow.length() != Sudoku.SIZE) { throw new IllegalArgumentException("Row must have " + Sudoku.SIZE + " columns."); } for (int column = 0; column < patternRow.toCharArray().length; column++) { char c = patternRow.toCharArray()[column]; cells[row][column] = c == '.' ? null : c; } } sudoku = null; puzzleMode = true; fireTableRowsUpdated(0, getRowCount() - 1); } /** * @return A Sudoku puzzle in the pattern format used by {@link SudokuFactory}. */ public String[] getPattern() { String[] pattern = new String[Sudoku.SIZE]; for (int i = 0; i < cells.length; i++) { Character[] row = cells[i]; StringBuilder rowString = new StringBuilder(); for (Character c : row) { rowString.append(c == null ? '.' : c); } pattern[i] = rowString.toString(); } return pattern; } }