import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class GUI extends Frame
{
private static final long serialVersionUID = 1L;
private JButton newGame;
private JButton solveGame;
private JButton checkAnswers;
private JPanel centerPanel;
private JPanel eastPanel;
private JPanel gridBlocks;
private int answer;
/**Constructor:
* This GUI is made of two parts (East/Center) in a border layout.
* The East portion contains two buttons, centered vertically, of
* the same width. The Center portion contains the Sudoku game and
* will scale to the window's size after the preferred width of the
* East portion is satisfied.
*/
public GUI(int[][] map, int[][] key)
{
setLayout(new BorderLayout());
setBackground(Color.lightGray);
UIManager.getLookAndFeel();
setTitle("Sudoku!");
setPreferredSize(new Dimension(400, 400));
add("East", getEastPanel());
add("Center", getCenterPanel(map, key));
pack();
//Handles the exit call.
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
setVisible(false);
dispose();
System.exit(0);
}
});
/**Listeners*/
getNGButton().addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//TODO Create method to start new game.
}
});
getCAButton().addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
}
});
getSGButton().addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//TODO Add Solve Game button.
}
});
/**EndListeners*/
}
private JPanel getCenterPanel(int[][] map, int[][] key)
{
if(centerPanel==null)
{
centerPanel = new JPanel(new BorderLayout());
centerPanel.setBorder(BorderFactory.createLineBorder(Color.black));
centerPanel.add("Center",getGridBlocks(map, key));
}
return centerPanel;
}
private JPanel getEastPanel()
{
if(eastPanel==null)
{
/**
* 0,1 allows for only 1 column, but any amount
* of rows. Grid items are always the same size.
**/
eastPanel = new JPanel(new GridLayout(0,1));
eastPanel.add(getNGButton());
eastPanel.add(getCAButton());
eastPanel.add(getSGButton());
}
return eastPanel;
}
/**----Buttons----*/
private JButton getNGButton()
{
if (newGame == null)
newGame = new JButton("New Game");
return newGame;
}
private JButton getCAButton()
{
if (checkAnswers == null)
checkAnswers = new JButton("Check Answers");
return checkAnswers;
}
private JButton getSGButton()
{
if (solveGame == null)
solveGame = new JButton("Solve Game");
return solveGame;
}
/**----EndButtons----*/
// private void checkAnswers(int[][] map)
// {
// for(int i=0;i<map.length;i++)
//
// }
private JPanel getGridBlocks(int[][] map, int[][] key)
{
if(gridBlocks==null)
{
gridBlocks = new JPanel(new GridLayout(0,3));
for(int bBlocks=0;bBlocks<9;bBlocks++)
{
/**
* Generate the inner blocks that will
* be filled inside the larger grid.
**/
JPanel smallBlocks = new JPanel(new GridLayout(0,3));
smallBlocks.setBorder(BorderFactory.createLoweredBevelBorder());
Font font = new Font(smallBlocks.getFont().getName(),smallBlocks.getFont().getStyle(),35);
JTextField[][] cells = new JTextField[9][9];
for(int sBlocks=0;sBlocks<9;sBlocks++)
{
//Some math to determine current position aware of offset.
int row = sBlocks / 3 + (bBlocks / 3) * 3;
int col = sBlocks % 3 + (bBlocks % 3) * 3;
final int ref = map[row][col];
//If the reference == 0, print blank else print the reference.
cells[row][col] = new JTextField(ref==0?"":Integer.toString(ref));
final JTextField cell = cells[row][col];
//Lock cells that already have a correct value based on original map.
if(ref!=0) cell.setEditable(false);
//No need to create a listener if the cell is locked.
/**
* This will "listen" to each JTextField for a change.
* Changes will prompt a check, if the check is successful
* the cell's background will change to green. If the check
* shows that the number entered is wrong then you get a red
* background. If the cell becomes blank you get back to white.
**/
else cell.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
answer = ref;
JTextField cell = (JTextField) event.getSource();
System.out.print(cell.getText()+" response triggered..."+answer);
//Trim cells that are >1 length.
if(cell.getText().length()>1)
{
String str = cell.getText();
str = str.replaceAll("(.)*", "$1");
System.out.println(cell.getText());
cell.setText(str);
System.out.println("Changed to: " + cell.getText());
}
}
});
//Sets the cell's property name for callback later.
cell.getDocument().getProperty("val");
cell.setFont(font);
//Assigns the cell to the current 3x3 block.
smallBlocks.add(cell);
}
//Assigns all of the the 3x3 blocks to the 9x9 grid.
gridBlocks.add(smallBlocks);
}
}
return gridBlocks;
}
/** A simple main to let us test the GUI */
public static void main(java.lang.String[] args)
{
int[][] map=new int[9][9];
int[][] key=new int[9][9];
(new GUI(map,key)).setVisible(true);
}
}