package aima.gui.fx.views;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;
import java.util.ArrayList;
import java.util.List;
/**
* Provides a view for Sudoku puzzles. Digit positions are specified by column and row indices between 1 (top / left)
* and 9 (bottom / right). Fixed digits are shown in brackets.
*
* @author Ruediger Lunde
*/
public class SudokuViewCtrl {
private List<ComboBox<String>> combos = new ArrayList<>(81);
/**
* Adds a grid pane with combo boxes to the provided root pane and returns
* a controller class instance containing application logic.
*/
public SudokuViewCtrl(StackPane viewRoot) {
// create grid layout
GridPane gridPane = new GridPane();
viewRoot.getChildren().add(gridPane);
viewRoot.setAlignment(Pos.BOTTOM_CENTER);
gridPane.maxWidthProperty().bind(viewRoot.widthProperty().subtract(20));
gridPane.maxHeightProperty().bind(viewRoot.heightProperty().subtract(10));
for (int i = 0; i < 9; i++) {
RowConstraints rc = new RowConstraints();
rc.setPercentHeight(100.0 / 9);
rc.setValignment(i % 3 == 1 ? VPos.CENTER : (i % 3) == 0 ? VPos.BOTTOM : VPos.TOP);
gridPane.getRowConstraints().add(rc);
ColumnConstraints cc = new ColumnConstraints();
cc.setPercentWidth(100.0 / 9);
cc.setHalignment(i % 3 == 1 ? HPos.CENTER : (i % 3) == 0 ? HPos.RIGHT : HPos.LEFT);
gridPane.getColumnConstraints().add(cc);
}
// create digit combo boxes
List<String> values = new ArrayList<>();
values.add(" ");
for (int i = 1; i <= 9; i++)
values.add(" " + i + " ");
for (int i = 1; i <= 9; i++)
values.add("(" + i + ")");
for (int i = 0; i < 81; i++) {
ComboBox<String> combo = new ComboBox<>();
combo.setStyle("-fx-font: 18px \"Courier New\"; -fx-font-weight: bold;");
combo.getItems().addAll(values);
combo.getSelectionModel().select(0);
combos.add(combo);
gridPane.add(combo, i % 9, i / 9);
}
}
public void clear(boolean allDigits) {
for (int i = 0; i < 81; i++) {
ComboBox<String> combo = combos.get(i);
if (allDigits || !isFixed(i % 9 + 1, i / 9 + 1))
combo.getSelectionModel().select(0);
}
}
public void clearDigit(int col, int row) {
getCombo(col, row).getSelectionModel().select(0);
}
public void setDigit(int col, int row, int digit) {
getCombo(col, row).getSelectionModel().select(digit);
}
public void fixDigit(int col, int row, int digit) {
getCombo(col, row).getSelectionModel().select(digit + 9);
}
/** Return a digit between 1 and 9 or -1 if no value has been selected yet. */
public int getDigit(int col, int row) {
int selIdx = getCombo(col, row).getSelectionModel().getSelectedIndex();
if (selIdx == 0)
return -1;
else if (selIdx < 10)
return selIdx;
else
return selIdx - 9;
}
public boolean isFixed(int col, int row) {
int selIdx = getCombo(col, row).getSelectionModel().getSelectedIndex();
return selIdx >= 10;
}
private ComboBox<String> getCombo(int col, int row) {
assert col >= 1 && col <= 9;
assert row >= 1 && row <= 9;
return combos.get((row-1) * 9 + (col-1));
}
}