basic board implementation, connected to file inputs from user. additionally expanded available settings and created structure for theming.

This commit is contained in:
Josh Ashton
2024-03-22 08:32:09 -06:00
parent e6a299906a
commit e1d79f4e37
5 changed files with 614 additions and 21 deletions
+10 -7
View File
@@ -1,13 +1,12 @@
// GUI imports
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.UIManager; import javax.swing.UIManager;
import gui.Nav;
import gui.Root;
import gui.backend.Settings;
import gui.backend.SudokuChecker;
import java.awt.BorderLayout; import java.awt.BorderLayout;
// Project imports
import gui.*;
import gui.backend.*;
/** /**
* Runner class for the Sudoku App, managing the GUI and coordinating * Runner class for the Sudoku App, managing the GUI and coordinating
* internal logic. * internal logic.
@@ -15,6 +14,7 @@ import java.awt.BorderLayout;
public class App extends JFrame { public class App extends JFrame {
// GUI fields // GUI fields
private Nav nav; private Nav nav;
private Board board;
// Data fields // Data fields
private Settings s; private Settings s;
@@ -25,8 +25,10 @@ public class App extends JFrame {
public App() { public App() {
super("Sudoku"); super("Sudoku");
s = new Settings(); s = new Settings();
nav = new Nav(s, false);
initSetup(); initSetup();
nav = new Nav(s, false);
board = new Board(s, nav.getLoadedGrid());
nav.setBoard(board);
add(createApp()); add(createApp());
} }
@@ -68,6 +70,7 @@ public class App extends JFrame {
private Root createApp() { private Root createApp() {
Root root = new Root(s); Root root = new Root(s);
root.add(nav); root.add(nav);
root.add(board);
return root; return root;
} }
+162 -1
View File
@@ -1,8 +1,10 @@
package gui; package gui;
import java.awt.GridLayout; import java.awt.GridLayout;
import java.awt.LayoutManager;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JLabel;
import gui.backend.Settings; import gui.backend.Settings;
@@ -20,6 +22,7 @@ import gui.backend.Settings;
public class Board extends JPanel { public class Board extends JPanel {
private Settings s; private Settings s;
private Cell[][] grid; private Cell[][] grid;
private Cell selected;
/** /**
* Create a new Board object with the default styling from settings. * Create a new Board object with the default styling from settings.
@@ -31,6 +34,31 @@ public class Board extends JPanel {
this.s = s; this.s = s;
this.grid = grid; this.grid = grid;
style(); style();
createBoard();
}
/**
* Get the grid of the Board.
*
* @return
*/
public Cell[][] getGrid() {
return grid;
}
/**
* Set the grid of the Board to the given grid.
*
* Intended to be used when loading a new puzzle.
*
* @param grid
*/
public void setGrid(Cell[][] grid) {
this.grid = grid;
removeAll();
createBoard();
repaint();
revalidate();
} }
/** /**
@@ -41,6 +69,139 @@ public class Board extends JPanel {
} }
private void createBoard() { private void createBoard() {
// TODO: Create the board with the given grid. for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
CellGUI cell = new CellGUI(grid[i][j], s.getCellGUIStartMode());
add(cell);
}
}
}
/**
* GUI representation of a single cell in the Sudoku grid.
*/
private class CellGUI extends JPanel {
private static GridLayout noteLayout = new GridLayout(3, 3);
private static GridLayout valueLayout = new GridLayout(1, 1);
private Cell cell;
private JLabel valueLabel;
private JLabel[] notesLabels;
private boolean notes; // true for notes, false for value
private boolean startInNotesOrValueMode;
/**
* Create a new CellGUI object with the given single cell.
*
* Start blank cells in notes mode if startInNotesOrValueMode is true.
*
* @param cell
* @param startInNotesOrValueMode
*/
public CellGUI(Cell cell, boolean startInNotesOrValueMode) {
super();
this.cell = cell;
this.startInNotesOrValueMode = startInNotesOrValueMode;
// Populate the cell with the appropriate value or notes.
if(cell.getValue() == 0) {
generateNotes();
if(startInNotesOrValueMode) {
setLayout(noteLayout);
notes = true;
} else {
setLayout(valueLayout);
notes = false;
valueLabel = new JLabel("");
add(valueLabel);
}
} else {
valueLabel = new JLabel(Integer.toString(cell.getValue()));
add(valueLabel);
}
}
/**
* Get the value of the underlying Cell object.
*
* @return int
*/
public int getValue() {
return cell.getValue();
}
/**
* Add a possible value to the cell.
*
* @param value
*/
public void addPossibleValue(int value) {
cell.addPossibleValue(value);
}
/**
* Remove a possible value from the cell.
*
* @return
*/
public void removePossibleValue(int value) {
cell.removePossibleValue(value);
}
/**
* Get the possible values of the underlying Cell object.
*
* @return int[]
*/
public int[] getPossibleValues() {
return cell.getPossibleValues();
}
/**
* Toggle the mode of the cell between value and note, including the
* layout of the cell.
*/
public void setNoteMode() {
if(notes) {
removeAll();
setLayout(valueLayout);
repaint();
revalidate();
add(valueLabel);
} else {
removeAll();
setLayout(noteLayout);
repaint();
revalidate();
generateNotes();
}
notes = !notes;
}
/**
* Create the GUI components for the cell.
*/
private void generateNotes() {
if(cell.getPossibleValues().length == 0) {
notesLabels = new JLabel[9];
return;
}
// Add the noted possible values to the cell.
int index = 0;
for(int i = 1; i <= 9; i++) {
if(cell.getPossibleValues()[index] == i) {
notesLabels[index] = new JLabel(Integer.toString(i));
index++;
} else {
notesLabels[index] = new JLabel("");
}
add(notesLabels[index]);
}
}
} }
} }
+38 -1
View File
@@ -27,6 +27,7 @@ import javax.swing.JButton;
public class Nav extends JPanel { public class Nav extends JPanel {
private Settings s; private Settings s;
private File f; private File f;
private Board b;
private Cell[][] grid; private Cell[][] grid;
/** /**
@@ -77,8 +78,37 @@ public class Nav extends JPanel {
openFile(inputFilename); openFile(inputFilename);
// Otherwise, create the GUI for the Nav bar. // Otherwise, create the GUI for the Nav bar.
} else createGUI(); } else {
createGUI();
// TODO: Need to implement the default file options in Settings.
switch(s.getDefaultOpenState()) {
case 0:
openFile("input");
break;
case 1:
openFile("medium");
break;
case 2:
openFile("hard");
break;
default:
System.out.println("Invalid default file option.");
}
}
}
/**
* Set the Board object for the Nav bar.
*
* This is necessary for the Nav bar to be able to interact with the
* Board object and update the grid with file I/O operations. This
* shouldn't be necessary to change once the program is running.
*
* @param b
*/
public void setBoard(Board b) {
this.b = b;
} }
/** /**
@@ -174,6 +204,7 @@ public class Nav extends JPanel {
f = fc.getSelectedFile(); f = fc.getSelectedFile();
createGrid(f); createGrid(f);
} }
b.setGrid(grid);
} }
/** /**
@@ -196,6 +227,11 @@ public class Nav extends JPanel {
f.getAbsolutePath() f.getAbsolutePath()
); );
grid = new Cell[9][9];
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
grid[i][j] = new Cell(i, j, 0);
return; return;
} }
@@ -281,6 +317,7 @@ public class Nav extends JPanel {
); );
e.printStackTrace(); e.printStackTrace();
grid = new Cell[9][9];
return; return;
} }
} }
+70 -11
View File
@@ -44,6 +44,12 @@ public class Settings {
// Resizable setting // Resizable setting
private boolean resizable; private boolean resizable;
// Cell GUI Start Mode
private boolean cellGUIStartMode;
// Default open state for the application.
private int defaultOpenState;
/** /**
* Create a new Settings object, initializing the default settings * Create a new Settings object, initializing the default settings
* or reading in the settings from settings file if it exists. * or reading in the settings from settings file if it exists.
@@ -174,28 +180,78 @@ public class Settings {
* *
* @return boolean * @return boolean
*/ */
public boolean getResizable() { public boolean getResizable() {
return resizable; return resizable;
} }
/** /**
* Set the resizable setting and write it to the settings file. * Set the resizable setting and write it to the settings file.
* *
* @param resizable * @param resizable
*/ */
public void setResizable(boolean resizable) { public void setResizable(boolean resizable) {
this.resizable = resizable; this.resizable = resizable;
updateSettingsFile(); updateSettingsFile();
} }
/**
* The Cell GUI Start Mode is a configurable setting, where the user can
* specify whether the cell GUI should start in notes mode or value mode.
*
* By default, the cell GUI starts in value mode, ie. returns false.
* Set to true to start in notes mode.
*
* @return boolean
*/
public boolean getCellGUIStartMode() {
return cellGUIStartMode;
}
/**
* Set the cell GUI start mode and write it to the settings file.
*
* @param cellGUIStartMode
*/
public void setCellGUIStartMode(boolean cellGUIStartMode) {
this.cellGUIStartMode = cellGUIStartMode;
updateSettingsFile();
}
/**
* The default open state for the application. The following values
* are accepted:
* 0 - Open the default easy.sdku file, default behavior;
* 1 - Open the last opened .sdku file;
* 2 - Open a new, blank .sdku file; and
* 3 - Open a new, random .sdku file.
*
* NOTE: The value 2 is not yet supported.
*
* @return
*/
public int getDefaultOpenState() {
return defaultOpenState;
}
/**
* Set the default open state for the application and write it to the
* settings file.
*
* @param defaultOpenState
*/
public void setDefaultOpenState(int defaultOpenState) {
this.defaultOpenState = defaultOpenState;
updateSettingsFile();
}
/** /**
* Open and write the settings to the settings file. * Open and write the settings to the settings file.
* *
* This method is called whenever a setting is updated. * This method is called whenever a setting is updated.
*/ */
private void updateSettingsFile() { private void updateSettingsFile() {
// TODO: Write the settings to the settings file. // TODO: Write the settings to the settings file.
} }
/** /**
* Set the default settings for the application and write them to the * Set the default settings for the application and write them to the
@@ -221,6 +277,9 @@ public class Settings {
dimension = new Dimension(750, 550); dimension = new Dimension(750, 550);
resizable = false; resizable = false;
cellGUIStartMode = false;
defaultOpenState = 0;
updateSettingsFile(); updateSettingsFile();
} }
+333
View File
@@ -0,0 +1,333 @@
package gui.backend;
import java.awt.Color;
import java.io.File;
/**
* The Theme class represents the color scheme for the GUI components.
*
* The Theme class reads a theme file and sets the colors for the GUI components.
*
* The Theme class provides the following color customizations:
* - primaryBackground
* - secondaryBackground
* - primaryText
* - secondaryText
* - primaryHighlight
* - secondaryHighlight
* - primaryBorder
* - secondaryBorder
* - primaryButton
* - secondaryButton
* - primaryButtonHighlight
* - secondaryButtonHighlight
* - primaryButtonBorder
* - secondaryButtonBorder
*/
import java.awt.Color;
import java.io.File;
/**
* The Theme class represents a theme for the GUI components.
* It provides colors for various GUI elements.
*/
public class Theme {
private Color primaryBackground;
private Color secondaryBackground;
private Color primaryText;
private Color secondaryText;
private Color primaryHighlight;
private Color secondaryHighlight;
private Color primaryBorder;
private Color secondaryBorder;
private Color primaryButton;
private Color secondaryButton;
private Color primaryButtonHighlight;
private Color secondaryButtonHighlight;
private Color primaryButtonBorder;
private Color secondaryButtonBorder;
/**
* Constructs a new Theme object with the given theme file.
* This object provides the colors for the GUI components.
*
* @param theme the theme file
*/
public Theme(File theme) {
this.theme = theme;
readTheme();
}
/**
* Reads the .theme file and sets the colors for the GUI components.
* Once complete, sets the theme for the GUI components.
*/
private void readTheme() {
// TODO: Read the .theme file
setTheme();
}
/**
* Sets the theme for the GUI components.
*/
private void setTheme() {
primaryBackground = Color.WHITE;
secondaryBackground = Color.LIGHT_GRAY;
primaryText = Color.BLACK;
secondaryText = Color.DARK_GRAY;
}
/**
* Gets the primary background color.
*
* @return the primary background color
*/
public Color getPrimaryBackground() {
return primaryBackground;
}
/**
* Sets the primary background color.
*
* @param primaryBackground the primary background color
*/
public void setPrimaryBackground(Color primaryBackground) {
this.primaryBackground = primaryBackground;
}
/**
* Gets the secondary background color.
*
* @return the secondary background color
*/
public Color getSecondaryBackground() {
return secondaryBackground;
}
/**
* Sets the secondary background color.
*
* @param secondaryBackground the secondary background color
*/
public void setSecondaryBackground(Color secondaryBackground) {
this.secondaryBackground = secondaryBackground;
}
/**
* Gets the primary text color.
*
* @return the primary text color
*/
public Color getPrimaryText() {
return primaryText;
}
/**
* Sets the primary text color.
*
* @param primaryText the primary text color
*/
public void setPrimaryText(Color primaryText) {
this.primaryText = primaryText;
}
/**
* Gets the secondary text color.
*
* @return the secondary text color
*/
public Color getSecondaryText() {
return secondaryText;
}
/**
* Sets the secondary text color.
*
* @param secondaryText the secondary text color
*/
public void setSecondaryText(Color secondaryText) {
this.secondaryText = secondaryText;
}
/**
* Gets the primary highlight color.
*
* @return the primary highlight color
*/
public Color getPrimaryHighlight() {
return primaryHighlight;
}
/**
* Sets the primary highlight color.
*
* @param primaryHighlight the primary highlight color
*/
public void setPrimaryHighlight(Color primaryHighlight) {
this.primaryHighlight = primaryHighlight;
}
/**
* Gets the secondary highlight color.
*
* @return the secondary highlight color
*/
public Color getSecondaryHighlight() {
return secondaryHighlight;
}
/**
* Sets the secondary highlight color.
*
* @param secondaryHighlight the secondary highlight color
*/
public void setSecondaryHighlight(Color secondaryHighlight) {
this.secondaryHighlight = secondaryHighlight;
}
/**
* Gets the primary border color.
*
* @return the primary border color
*/
public Color getPrimaryBorder() {
return primaryBorder;
}
/**
* Sets the primary border color.
*
* @param primaryBorder the primary border color
*/
public void setPrimaryBorder(Color primaryBorder) {
this.primaryBorder = primaryBorder;
}
/**
* Gets the secondary border color.
*
* @return the secondary border color
*/
public Color getSecondaryBorder() {
return secondaryBorder;
}
/**
* Sets the secondary border color.
*
* @param secondaryBorder the secondary border color
*/
public void setSecondaryBorder(Color secondaryBorder) {
this.secondaryBorder = secondaryBorder;
}
/**
* Gets the primary button color.
*
* @return the primary button color
*/
public Color getPrimaryButton() {
return primaryButton;
}
/**
* Sets the primary button color.
*
* @param primaryButton the primary button color
*/
public void setPrimaryButton(Color primaryButton) {
this.primaryButton = primaryButton;
}
/**
* Gets the secondary button color.
*
* @return the secondary button color
*/
public Color getSecondaryButton() {
return secondaryButton;
}
/**
* Sets the secondary button color.
*
* @param secondaryButton the secondary button color
*/
public void setSecondaryButton(Color secondaryButton) {
this.secondaryButton = secondaryButton;
}
/**
* Gets the primary button highlight color.
*
* @return the primary button highlight color
*/
public Color getPrimaryButtonHighlight() {
return primaryButtonHighlight;
}
/**
* Sets the primary button highlight color.
*
* @param primaryButtonHighlight the primary button highlight color
*/
public void setPrimaryButtonHighlight(Color primaryButtonHighlight) {
this.primaryButtonHighlight = primaryButtonHighlight;
}
/**
* Gets the secondary button highlight color.
*
* @return the secondary button highlight color
*/
public Color getSecondaryButtonHighlight() {
return secondaryButtonHighlight;
}
/**
* Sets the secondary button highlight color.
*
* @param secondaryButtonHighlight the secondary button highlight color
*/
public void setSecondaryButtonHighlight(Color secondaryButtonHighlight) {
this.secondaryButtonHighlight = secondaryButtonHighlight;
}
/**
* Gets the primary button border color.
*
* @return the primary button border color
*/
public Color getPrimaryButtonBorder() {
return primaryButtonBorder;
}
/**
* Sets the primary button border color.
*
* @param primaryButtonBorder the primary button border color
*/
public void setPrimaryButtonBorder(Color primaryButtonBorder) {
this.primaryButtonBorder = primaryButtonBorder;
}
/**
* Gets the secondary button border color.
*
* @return the secondary button border color
*/
public Color getSecondaryButtonBorder() {
return secondaryButtonBorder;
}
/**
* Sets the secondary button border color.
*
* @param secondaryButtonBorder the secondary button border color
*/
public void setSecondaryButtonBorder(Color secondaryButtonBorder) {
this.secondaryButtonBorder = secondaryButtonBorder;
}
private File theme;
}